Welcome! Log In Create A New Profile

Advanced

[PHP-DEV] [RFC] Pre-draft for PipeOp v2

Posted by Sara Golemon 
Sara Golemon
[PHP-DEV] [RFC] Pre-draft for PipeOp v2
September 20, 2017 12:40AM
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.

-Sara

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Levi Morrison
Re: [PHP-DEV] [RFC] Pre-draft for PipeOp v2
September 20, 2017 12:50AM
On Tue, Sep 19, 2017 at 4:32 PM, Sara Golemon <[email protected]> wrote:
> 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.
>
> -Sara
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php

Thank you for making this proposal! As alluded to I had concerns on
the original proposal and fully support this version. Sometimes
simplicity is the mark of a good RFC and I think this is one of those
times.

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Nikita Popov
Re: [PHP-DEV] [RFC] Pre-draft for PipeOp v2
September 20, 2017 12:10PM
On Wed, Sep 20, 2017 at 6:32 AM, Sara Golemon <[email protected]> wrote:

> 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
Ilija Tovilo
Re: [PHP-DEV] [RFC] Pre-draft for PipeOp v2
September 20, 2017 01:50PM
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


On 20 Sep, 2017, at 12:01 PM, Nikita Popov <[email protected]> wrote:

On Wed, Sep 20, 2017 at 6:32 AM, Sara Golemon <[email protected]> wrote:

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
Derick Rethans
Re: [PHP-DEV] [RFC] Pre-draft for PipeOp v2
September 20, 2017 07:00PM
On Wed, 20 Sep 2017, Nikita Popov wrote:

> On Wed, Sep 20, 2017 at 6:32 AM, Sara Golemon <[email protected]> wrote:
>
> > 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.

<snip>

> > 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.

What do you mean here by "partial application"?

cheers,
Derick

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Christoph M. Becker
Re: [PHP-DEV] [RFC] Pre-draft for PipeOp v2
September 20, 2017 07:20PM
On 20.09.2017 at 18:52, Derick Rethans wrote:

> On Wed, 20 Sep 2017, Nikita Popov wrote:
>
>> 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.
>
> What do you mean here by "partial application"?

Partial application is a common concept in functional/applicative
programming languages, which facilitates to get a closure over another
function where some of the parameters are already applied, e.g.
something like (pseudocode):

incr = partial(plus, 1);
print incr(2); // 3
print incr(100); // 101

--
Christoph M. Becker


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Sara Golemon
Re: [PHP-DEV] [RFC] Pre-draft for PipeOp v2
September 20, 2017 07:40PM
On Wed, Sep 20, 2017 at 12:52 PM, Derick Rethans <[email protected]> wrote:
> On Wed, 20 Sep 2017, Nikita Popov wrote:
>> > 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 generally agree with this statement, and it's why the original
pipe-op (as with hacklang's version) included (a form of) pfa
implicitly. If that means we should nail down the specifics of PFA
and/or Short-Lambdas before even bothering to move into full draft of
PipeOp, then that's fine.

Levi made the very solid argument that they can be independently
considered even if they compliment each other well, and given the
triviality of the pipe half of that equation, I put it together first
so that we have something to look at.

On the topic of pipe2 specifically:
The positive side of this diff is that it has zero impact on the
backend compiler or opcache since it doesn't produce any new AST
elements. On the minus side, the AST it produces opaques the original
format. In practice, this hack is only visible if you're using your
or my ast extensions, or if you use a failing assert. This is what I
like the least about the approach I included in my link. It's not the
first place we've hidden original intent behind AST transformations,
but it's certainly the most visually jarring when serialized.

> What do you mean here by "partial application"?
>
$trimX = trim($$, $x);

In this example, trim isn't invoked immediately, instead, $trimX
becomes a callable (closure) which takes a single argument and invokes
trim() with that argument and the captured $x variable. We've
"partially applied" some arguments to the trim() function, but we
haven't finished forming a function call yet.

Essentially, the above turns into this:
$trimX = function($arg) use ($x) { return trim($arg, $x); };

The '$$' token used by HackLang's PipeOp works well enough because we
know that RHS is only ever going to receive one argument (the result
of LHS). A more generic approach to PFA would probably involve
allowing for multiple positional arguments, perhaps like:

$myInArray = in_array($2, $1); // Reverse the arg order, effectively

PFA and ShortLambdas have the same scope capture issues however, which
make them thornier issues to tackle.

-Sara

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Stanislav Malyshev
Re: [PHP-DEV] [RFC] Pre-draft for PipeOp v2
September 21, 2017 11:20PM
Hi!

> 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.

I am still feeling it is a bit weird to do things that way, but other
than that (which is just my personal issue) I do not see any problems in
this proposal. With magic weird $$ thing gone, it seems to be
straightforward and mostly intuitive. So while I am not feeling this is
a must, I think it may be nice to have it.

It'd be also nice then if we could have some syntax that allowed us to
refer to functions/methods as callables - mostly for the benefit of the
code readers and IDEs. I.e. you can do "hello" |> "strtoupper" and it's
fine but it is not at all intuitive what you're doing sending one string
into another. Same with "hello" |> [$this, 'bar']. Now, if we could do
something like this:
"hello" |> &{strtoupper}
"hello" |> &{$this->bar}

(yes I know the syntax is ugly, I hope you get the idea though to have a
syntax for this) then you could have better readability, easier IDE
autocompletion and other benefits. Not for this RFC, clearly, but just
putting it out there so I don't forget.

--
Stas Malyshev
smalyshev@gmail.com

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Levi Morrison
Re: [PHP-DEV] [RFC] Pre-draft for PipeOp v2
September 22, 2017 01:10AM
On Thu, Sep 21, 2017 at 3:13 PM, Stanislav Malyshev <[email protected]> wrote:
> Hi!
>
>> 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.
>
> I am still feeling it is a bit weird to do things that way, but other
> than that (which is just my personal issue) I do not see any problems in
> this proposal. With magic weird $$ thing gone, it seems to be
> straightforward and mostly intuitive. So while I am not feeling this is
> a must, I think it may be nice to have it.
>
> It'd be also nice then if we could have some syntax that allowed us to
> refer to functions/methods as callables - mostly for the benefit of the
> code readers and IDEs. I.e. you can do "hello" |> "strtoupper" and it's
> fine but it is not at all intuitive what you're doing sending one string
> into another. Same with "hello" |> [$this, 'bar']. Now, if we could do
> something like this:
> "hello" |> &{strtoupper}
> "hello" |> &{$this->bar}
>
> (yes I know the syntax is ugly, I hope you get the idea though to have a
> syntax for this) then you could have better readability, easier IDE
> autocompletion and other benefits. Not for this RFC, clearly, but just
> putting it out there so I don't forget.
>
> --
> Stas Malyshev
> smalyshev@gmail.com
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php

I don't want to get too far off topic but since Stas has wandered off
a bit already I'll mention this. Scala has "placeholders":

val sum = List(1,2,3,4,5).reduceLeft(_+_)

The expression `_ + _` will create a function that takes two
parameters and then returns the result of adding them together,
equivalent to this:

val sum = List(1,2,3,4,5).reduceLeft((a, b) => a + b)

The single underscore `_` might not work for PHP because `gettext` has
used a single underscore as an alias for... a long time, maybe since
its inception. But for this example I'll use it anyway:

"hello" |> strtoupper(_) |> $this->bar(_)

It's saying, pretty literally, fill in the blank. Remember, though,
it's actually creating closures and doesn't directly mean "put the
result of the left-hand side here" unlike the previous proposal for
`$$`.

I brought it up because this can fill the same need as Stas' proposal
creating callables with something like `&{strtoupper}`. If we used
the symbol `$$` for the same placeholder mechanism from Scala it
becomes a more general purpose mechanism that could be used for any
callables, not just ones involved in a pipe:

$potentially_valid_emails =
array_filter($this->isProperlyFormattedEmailAddress($$), $email_list);

Anyway, the purpose of this thread is to talk about the pipe operator
so I'll stop talking now.

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Sara Golemon
Re: [PHP-DEV] [RFC] Pre-draft for PipeOp v2
September 27, 2017 10:00PM
On Thu, Sep 21, 2017 at 5:13 PM, Stanislav Malyshev <[email protected]> wrote:
> It'd be also nice then if we could have some syntax that allowed us to
> refer to functions/methods as callables - mostly for the benefit of the
> code readers and IDEs. I.e. you can do "hello" |> "strtoupper" and it's
> fine but it is not at all intuitive what you're doing sending one string
> into another. Same with "hello" |> [$this, 'bar']. Now, if we could do
> something like this:
> "hello" |> &{strtoupper}
> "hello" |> &{$this->bar}
>
Super-hacky implementation (that I wouldn't want to merge, but it
shows the syntax at work).

https://github.com/php/php-src/compare/master...sgolemon:lambda
which provides a form of both short-closures and partial functions.

Combined with also-super-hacky pipe diff from earlier, you get:

$x = "Hello"
|> &{strtoupper($0)}
|> &{ $0 . "world" }
|> &{strrev($0)};

var_dump($x);
// string(10) "dlrowOLLEH"

-Sara

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Levi Morrison
Re: [PHP-DEV] [RFC] Pre-draft for PipeOp v2
September 28, 2017 09:10PM
On Wed, Sep 27, 2017 at 1:56 PM, Sara Golemon <[email protected]> wrote:

> On Thu, Sep 21, 2017 at 5:13 PM, Stanislav Malyshev <[email protected]>
> wrote:
> > It'd be also nice then if we could have some syntax that allowed us to
> > refer to functions/methods as callables - mostly for the benefit of the
> > code readers and IDEs. I.e. you can do "hello" |> "strtoupper" and it's
> > fine but it is not at all intuitive what you're doing sending one string
> > into another. Same with "hello" |> [$this, 'bar']. Now, if we could do
> > something like this:
> > "hello" |> &{strtoupper}
> > "hello" |> &{$this->bar}
> >
> Super-hacky implementation (that I wouldn't want to merge, but it
> shows the syntax at work).
>
> https://github.com/php/php-src/compare/master...sgolemon:lambda
> which provides a form of both short-closures and partial functions.
>
> Combined with also-super-hacky pipe diff from earlier, you get:
>
> $x = "Hello"
> |> &{strtoupper($0)}
> |> &{ $0 . "world" }
> |> &{strrev($0)};
>
> var_dump($x);
> // string(10) "dlrowOLLEH"
>
> -Sara
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>

By the way the `&` is not required. When experimenting with possible short
closure syntax I created an implementation for `{}` to make sure it was
possible:

$x = "Hello"
|> {strtoupper($0)}
|> { $0 . "world" }
|> {strrev($0)};

If people would prefer that syntax for short-closures then that's fine by
me. If we made it this concise there wouldn't be a need for a `$$` proposal
anyway.

---

My impression from the community is that the pipe operator is desirable but
not if it encourages string or array callables. In that vein which syntax
do you prefer?

// brace style
$x = "Hello"
|> {strtoupper($0)}
|> { $0 . "world" }
|> {strrev($0)};

// fn style
$x = "Hello"
|> fn($x) => strtoupper($x)}
|> fn($x) => $x . "world"
|> fn($x) => strrev($0);

// caret style
$x = "Hello"
|> ^($x) => strtoupper($x)}
|> ^($x) => $x . "world"
|> ^($x) => strrev($0);

I included these two styles because they are the most promising versions
from the arrow functions discussions. I think my preferred order is the one
I wrote them in. The brace style is concise, nicely delimits the
expression, and seems the clearest for me to read because the symbols don't
dominate. The fn style seems nicer than caret which has too many symbols in
close proximity for my taste.

Community thoughts? Which short closure style pairs the nicest with the
pipe operator?
Rowan Collins
Re: [PHP-DEV] [RFC] Pre-draft for PipeOp v2
September 29, 2017 12:00AM
On 28/09/2017 20:07, Levi Morrison wrote:
> The brace style is concise, nicely delimits the
> expression, and seems the clearest for me to read because the symbols don't
> dominate.


This is something that I tried to push for in previous discussions -
I've never liked the syntaxes where the expression floats away from the
operator, and you have to work out where it ends. The counter-argument I
got was that some people actually like writing things like this,
although I'm not entirely clear why:

fn($x) => fn($y) => in_array($x, $y)


Which brings us to the question of how we might generalise the {} syntax
for more complex situations. Clearly, we can't just nest them if the
first parameter is always called $0:

{ { in_array($0, $0) } }  #WAT?

Obviously named variables are kind of useful anyway, so maybe $0 could
be the default, but allow them to be specified:

// Simple definition
{ $0 . ' world' }
==
{ $greeting => $greeting . ' world' )

// Nested definitions
{ $x => { in_array($x, $0) } }
==
{ $x => { $y => in_array($x, $y) } }

// 2-parameter function
{ $x, $y => in_array($x, $y) }


> My impression from the community is that the pipe operator is
desirable but
> not if it encourages string or array callables.

Yeah, my first thought on this thread that I liked this version of the
proposal significantly less than the previous one, because I always
liked the idea of this being a programming style, with the RHS being a
statement to be rewritten. So you could write $input |> $foo = $$ |>
echo $$ |> return $$ ...

But with a suitable way of creating a callable to pass to it, I could
live with it.


What if the syntax for taking a reference to function was just a special
case of the partial application / lambda syntax? At risk of turning into
Perl, we could use "$..." to mean "copy in all the parameters":

$foo = { in_array($...) };

This would be logically equivalent to:

$foo = function(...$x) { return in_array(...$x); }

But the compiler could actually optimise it as something more like
Closure::fromCallable('in_array')


Just throwing some thoughts out there to see if any of them stick...

--
Rowan Collins
[IMSoP]


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Tony Marston
Re: [PHP-DEV] [RFC] Pre-draft for PipeOp v2
September 29, 2017 11:30AM
"Rowan Collins" wrote in message
news:[email protected]
>
>On 28/09/2017 20:07, Levi Morrison wrote:
>> The brace style is concise, nicely delimits the
>> expression, and seems the clearest for me to read because the symbols
>> don't
>> dominate.
>
>
>This is something that I tried to push for in previous discussions - I've
>never liked the syntaxes where the expression floats away from the
>operator, and you have to work out where it ends. The counter-argument I
>got was that some people actually like writing things like this, although
>I'm not entirely clear why:
>
>fn($x) => fn($y) => in_array($x, $y)
>

Just because some people would like to write code like this does not make it
acceptable for the majority of the programming community. You should never
forget that the primary aim of a programmer is to write code which can be
read by a human, and only incidentally to be executed by a machine (H.
Abelson and G. Sussman in "The Structure and Interpretation of Computer
Programs", 1984).

Some people complain that PHP is too verbose, so they strive to replace long
words, or groups of words, with abbreviations or even symbols. This, IMHO,
converts a readable program into a bunch of hieroglyphics and should
therefore be avoided.

I think there should be a rule which states that if something can already be
done with 5 lines or less of userland code then it should not be built into
the core language as it would be adding unnecessary complications that would
only benefit a small minority of programmers but would be to the detriment
of the majority.

--
Tony Marston


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Michał Brzuchalski
Re: [PHP-DEV] [RFC] Pre-draft for PipeOp v2
September 29, 2017 11:40AM
2017-09-28 21:07 GMT+02:00 Levi Morrison <[email protected]>:

> On Wed, Sep 27, 2017 at 1:56 PM, Sara Golemon <[email protected]> wrote:
>
> > On Thu, Sep 21, 2017 at 5:13 PM, Stanislav Malyshev <[email protected]
> >
> > wrote:
> > > It'd be also nice then if we could have some syntax that allowed us to
> > > refer to functions/methods as callables - mostly for the benefit of the
> > > code readers and IDEs. I.e. you can do "hello" |> "strtoupper" and it's
> > > fine but it is not at all intuitive what you're doing sending one
> string
> > > into another. Same with "hello" |> [$this, 'bar']. Now, if we could do
> > > something like this:
> > > "hello" |> &{strtoupper}
> > > "hello" |> &{$this->bar}
> > >
> > Super-hacky implementation (that I wouldn't want to merge, but it
> > shows the syntax at work).
> >
> > https://github.com/php/php-src/compare/master...sgolemon:lambda
> > which provides a form of both short-closures and partial functions.
> >
> > Combined with also-super-hacky pipe diff from earlier, you get:
> >
> > $x = "Hello"
> > |> &{strtoupper($0)}
> > |> &{ $0 . "world" }
> > |> &{strrev($0)};
> >
> > var_dump($x);
> > // string(10) "dlrowOLLEH"
> >
> > -Sara
> >
> > --
> > PHP Internals - PHP Runtime Development Mailing List
> > To unsubscribe, visit: http://www.php.net/unsub.php
> >
>
> By the way the `&` is not required. When experimenting with possible short
> closure syntax I created an implementation for `{}` to make sure it was
> possible:
>
> $x = "Hello"
> |> {strtoupper($0)}
> |> { $0 . "world" }
> |> {strrev($0)};
>
> If people would prefer that syntax for short-closures then that's fine by
> me. If we made it this concise there wouldn't be a need for a `$$` proposal
> anyway.
>

I love this syntax with braces, I wanted to do like it in
https://wiki.php.net/rfc/short-closures
but only for replacement of string or array callables as closures.


>
> ---
>
> My impression from the community is that the pipe operator is desirable but
> not if it encourages string or array callables. In that vein which syntax
> do you prefer?
>
> // brace style
> $x = "Hello"
> |> {strtoupper($0)}
> |> { $0 . "world" }
> |> {strrev($0)};
>
> // fn style
> $x = "Hello"
> |> fn($x) => strtoupper($x)}
> |> fn($x) => $x . "world"
> |> fn($x) => strrev($0);
>
> // caret style
> $x = "Hello"
> |> ^($x) => strtoupper($x)}
> |> ^($x) => $x . "world"
> |> ^($x) => strrev($0);
>
> I included these two styles because they are the most promising versions
> from the arrow functions discussions. I think my preferred order is the one
> I wrote them in. The brace style is concise, nicely delimits the
> expression, and seems the clearest for me to read because the symbols don't
> dominate. The fn style seems nicer than caret which has too many symbols in
> close proximity for my taste.
>
> Community thoughts? Which short closure style pairs the nicest with the
> pipe operator?
>



--
regards / pozdrawiam,
--
Michał Brzuchalski
about.me/brzuchal
brzuchalski.com
Christoph M. Becker
[PHP-DEV] Re: [RFC] Pre-draft for PipeOp v2
September 29, 2017 02:30PM
On 20.09.2017 at 00:32, Sara Golemon wrote:

> 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.

I'm not particularly fond of a pipe(line) operator. I don't see a great
advantage over a simple compose function:

$appendWorld = function ($x) {return "$x world";};
$x = compose('strtoupper', $appendWorld)('hello');

The benefit of using a compose function would be the possibility of
point-free programming without explicitely declaring another function:

$toUpperAppendWorld = compose(
'strtoupper',
function ($x) {return "$x world";}
);
$x = $toUpperAppendWorld('hello');
$y = $toUpperAppendWorld('goodbye');

Basically, the compose function would be like the pipe operator without
special casing the (first) input.

See also Andreas's suggestion regarding built-in functions for common
functional primitives (http://news.php.net/php.internals/100739).

--
Christoph M. Becker

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Sorry, only registered users may post in this forum.

Click here to login