Nikita Nefedov wrote on 01/10/2015 15:58:
On Thu, 01 Oct 2015 15:33:51 +0300, Rowan Collins
<rowan.coll...@gmail.com> wrote:
It is a tool for making them shorter, yes, but it is not the only
way, and it comes with a cost of changing established behaviour.
Again, look at C++'s lambda syntax - it is much shorter than PHP's,
but requires a list of all variables from the outer scope being
captured.
C++11 doesn't *require* the list of all variables, but it does require
explicit "wildcard" ([=] for copy semantics, [&] for capturing by
reference).
I'm not actually that familiar with C++'s lambdas, and was basing my
understanding on this page:
https://msdn.microsoft.com/en-us/library/dd293608.aspx
I read this line as implying the same behaviour as PHP's:
> An empty capture clause, *[ ]*, indicates that the body of the lambda
expression accesses no variables in the enclosing scope.
But on closer inspection, the meaning of [=] on its own is just not
terribly clear on that particular description, so I stand corrected.
But C++ is not the best place for picking up syntax choices, quite
frankly it's one of the least readable languages in a way that it
allows you to write very cryptic code easily (but still allows to
write perfectly readable code as well).
Sure, short syntax leads to hard-to-read code. A good argument to stick
to the existing PHP verbosity.
And, again, I was not advocating C++'s exact syntax (it conflicts with
existing syntax anyway), merely showing that "short" and "explicitly
listed captures" are not mutually exclusive.
I don't think there was a dozen of different ideas, I could only find
those about `lambda(arg-list; use-list; expression)` and variations of
it with different keywords and different return-type syntax.
Fair enough. But there's no point me addressing bikeshedding details
about semi-colon vs other punctuation, etc, etc, if you are
fundamentally opposed to requiring an explicit list of used variables.
And one thing that makes auto capture much better choice than explicit
capture (as it've been said a couple of times already) is partial
application:
$mul = fn($x) => fn($y) => fn($z) => $x * $y * $z;
Looks simpler than:
$mul = fn($x) => fn($y; $x) => fn($z; $x, $y) => $x * $y * $z;
It looks simpler, but it's an illusion - there is actually a closure
hidden in there that has argument ($z) and captures ($x, $y). To someone
not used to chaining, and not expecting scopes to be inherited, it's far
from simple to follow where $x and $y come from and end up.
Let's pick another syntax - again, completely off the top of my head,
may not even be possible:
# { args|captures => return }
$double = { $x => $x * 2 }
$mul = {$x => {$y|$x => {$z|$x,$y => $x * $y * $z} } }
Note that the nesting is indicated explicitly, rather than via
associativity, the captured variables are listed explicitly, but clearly
separated from the argument list.
So my question is: if a short syntax was suggested which required
explicit capture but otherwise seemed compact and elegant, would you be
interested, or do you consider auto-capture a non-negotiable feature?
Regards,
--
Rowan Collins
[IMSoP]