Member since
While I'm not against the concept in general, this implementation is not well-done. The $value variables comes from nowhere and makes it confusing - it looks like an undefined variable and a quick glance at it, was the first thing I thought - where is $value coming from? Why not just use $name within that block? Same with $field? Why not just return the value that is going to be set? This is one of the more confusing RFCs I've seen and does not follow the PHP-code style, makes things confusing for both new and experienced coders. In it's current format, I can't approve with good conscience.
In my opinion the solution as is proposed is ambigious because you would have to guess the variable names and these variables by themselfs only suggest their functionality. Like other langauge constructs which have specific keywords or syntax. The concept I support but this variant I do not.
I like the clean syntax. It would allow chaining items and removing the function within a function within a function that quickly becomes an ugly and confusing mess of code.
Short closures were meant to be that - short. If you need multiple lines, just create a function (it can even be a closure). Or just use a standard anonymous function instead of a short closure. It will also create confusion with having access to variables outside the short closure scope while letting it look like a normal function.
I think complaints about the syntax being messy are really about the array manipulation functions being inherently hard to format nicely.
To be clear I agree that the proposed example isn't great, nested closures are never going to win any readabillity prizes. If however we look at any non-array based manipulation I think the readabillity is objectively better:
$name = 'my_user_name' |> fn (string $string): string => str_replace('_', ' ', $string) |> strtolower(...) |> ucwords(...) |> trim(...);
Or without first class callables:
$name = 'my_user_name' |> fn (string $string): string => str_replace('_', ' ', $string) |> fn (string $string): string => strtolower($string) |> fn (string $string): string => ucwords($string) |> fn (string $string): string => trim($string);
Bonus: this also adds runtime type checks to each step. Eg strreplace
returns string|array
I can't imagine anyone would think this is better:
$name = trim( ucwords( strtolower( str_replace('_', ' ', 'my_user_name') ) ) );
For example:
$result = "Hello World"
|> 'htmlentities'
|> 'str_split'
|> fn($x) => array_map('strtoupper', $x)
|> fn($x) => array_filter($x, fn($v) => $v != 'O');
Is 'nicer' since it has better readability and clearer syntax than:
$result = array_filter(
str_split(
strtoupper(
htmlentities("Hello World")
)
),
fn($v) => $v != '0'
);
I could have used it multiple times for array transformations. But the RFC still built on really ancient PHP behaviour (mapping functions as strings) and should be redone by fosucing only on modern syntax:
|> fn($x) => array_filter($x, fn($v) => $v != 'O')
|> str_split(...)
mmh, seems to me that just replacing function by fn and having such a different behaviour is risky
Auto capture by-value is clear enough with a single expression closure, but I think for multiple statement functions it could be confusing to have to keep track of scope. Being explicit (with use()
) makes it simple and concise.
If this were to pass, I think the syntax should continue to include the arrow to signify the auto capture by-value intention. Just like in JavaScript, the arrow is used whether single expression or multiple, and the use of brackets is what separates them.
Whether it's:
I really do not want to see this in PHP because it tempts to apply closures on everything. The question is not if we can but if we should.