Agree.
Even if we already had partial application the previously suggested syntax is still more readable IMO. Consider the following example:
$array
|> array_map(function ($element) { ... }, $$);
vs
$array
|> apply(flip('array_map'), function ($element) { ... });
Not to mention that we'd have to implement flip
and apply
ourselves.
Regards
I was planning to update the RFC, but wiki.php.net is having issues
atm and isn't coming back up with basic coaxing, so I'll just start
discussion informally, and the RFC can be updates later.
Background: I made an RFC some time ago to implement HackLang's Pipe
Operator https://docs.hhvm.com/hack/operators/pipe-operator which
provides fluent calling for non-object interfaces.
I circulated it to mixed reviews, many negative, with the negativity
feeling like it centered on the use of a magic placeholder token $$
.
After discussion with Levi and others who suggested a simpler
approach, I'd like to offer
https://github.com/php/php-src/compare/master...sgolemon:pipe2 as an
alternate possibility.
This version removes the $$ token, and instead treats the RHS of the
expression as a callable obeying the same rules as the callable
typehint elsewhere in the language. Specifically:
- Free functions as strings containing the function name. (e.g. 'funcname')
- Object methods as array($object, 'methodname')
- Static methods as array('Classname', 'methodname')
- Closure expression (e.g. function($x) { return ...; } )
- Object instance with an __invoke() method.
In a given pipe expression, the output of the LHS expression feeds a
single arg to the callable on the RHS.
Examples:
$x = "hello"
|> 'strtoupper'
|> function($x) { return $x . " world"; };
// $x === "HELLO world"
Non-Goal: I didn't include support for base function names (e.g.
"hello" |> strtoupper
) because of the conflict with constants.
Using a constant to store your function name is totes legit and
consistent with language syntax.
Future Scope: Short Lambdas $x => $x + 1
and Partial Functions
someFunc('fixed val1', ..., 'fixed val2')
would help make this
functionality more useful and are worth discussing as a sub-thread,
but are not required to be implemented at the same time.
I think this feature makes very little sense if it's not introduced
together with a way of making partial application much more ergonomic than
it is now. I understand the desire to keep things separate, but I don't
think that this proposal can land without partial application syntax being
introduced beforehand or in conjunction with it.
From a previous R11 discussion, I remember that two strong contenders were
foo(...) for getting a callable with an arbitrary number of unbound
parameters and foo($$) for a single unbound parameter. In the latter case
the proposal has a similar expressive power as the previous pipe operator
proposal. Another option was to make $$ a more general construct for
obtaining single-parameter closures in compact form. Then you would also be
able to write "$$->getFoo()" to get the equivalent of "function($x) {
return $x->getFoo(); }" and similar. A disadvantage is that the precedence
here is less clear and that a short closure syntax might be more clear for
the cases that go beyond partial application.
Regards,
Nikita