On Mon, Jul 11, 2016 at 1:55 PM, Michał Brzuchalski <
michal.brzuchalski@gmail.com> wrote:
11 lip 2016 18:31 "Rasmus Schultz" rasmus@mindplay.dk napisał(a):
what's the actual added value of this sort of operator?
The only direct value to the language is brevity - mere convenience.
But I think the biggest indirectly added value, is that this will
discourage people from the chainable methods anti-pattern - so this
has value to the community; those who write chainable methods can
stop, and those who want chainable methods can get a wider choice of
libraries that were previously too verbose in use for their taste.For this sort of chaining I'd propose, in addition to the cascade
operator,
the chain operator. This would work like the cascade operator except
that
the return of the function is implicitly the first parameter of the
next
argument in the chainI don't like this idea, at all - I think we should aim for something
consistent with other languages. Per the Dart spec:A cascaded method invocation expression of the form e..suffix is
equivalent to the expression (t){t.suffix; return t;}(e).In other words, the expression always evaluates as the object, which
is fine for most cases, e.g. for everything you're doing with
chainable methods today - which can't actually return any values,
since they return $this. Note that something like PSR-7's HTTP
immutable models are actually factory methods, e.g. use-cases not
applicable to the cascade operator.The other marginal use case perhaps is cases where a builder of some
sort ends with a call to a factory method - this can be done without
adding a second operator, by using parens in a similar fashion to Dart
and others, e.g.:$object = ($builder ->>setFoo(1) ->>setBar(2) ->>setBaz(3) )->build();
Or obviously:
$builder ->>setFoo(1) ->>setBar(2) ->>setBaz(3); $object = $builder->build();
Regarding syntax - I feel the natural choice, e.g. similar to "." vs
"..", would be a longer arrow --> but that's ambiguous. (decrement
operator, greater than operator)The proposed |> operator looks horrible and is very awkward to type,
at least on both American and Danish keyboard - I use both. (it reads
like "or greater than" in my mind, so much so that glancing over
Sara's proposal earlier, I didn't even understand what it was.)Would something like ->> be ambiguous as well? That's fairly close too
- a double-headed arrow, not unlike the double dots of other
languages...IMHO double-headed arrow looks pretty nice and whole idea is great. Very
big +1 for this feature
Agreed, but what about static methods? Triple colon perhaps?
A::setFoo(1)
:::setBar(2)
:::setBaz(3);
And I do agree that the double period is cleaner, but the bus left the
station a very long time ago (PHP 3 at least) by making . the connotation
operator. Or at least I think so. If the parser could deal with it double
period would be best because it could apply to both contexts.
$object->setFoo(1)
..setBar(2)
..setBaz(3);
A_Class::setFoo(1)
..setBar(2)
..setBaz(3);
But again, I don't know how feasible the above is since I know next to
nothing about internals.
IMO, static methods have very little need for this feature - you
rarely need to make repeated series of static calls and static
property assignments. Let's not complicate this.
On Mon, Jul 11, 2016 at 1:55 PM, Michał Brzuchalski <
michal.brzuchalski@gmail.com> wrote:11 lip 2016 18:31 "Rasmus Schultz" rasmus@mindplay.dk napisał(a):
what's the actual added value of this sort of operator?
The only direct value to the language is brevity - mere convenience.
But I think the biggest indirectly added value, is that this will
discourage people from the chainable methods anti-pattern - so this
has value to the community; those who write chainable methods can
stop, and those who want chainable methods can get a wider choice of
libraries that were previously too verbose in use for their taste.For this sort of chaining I'd propose, in addition to the cascade
operator,
the chain operator. This would work like the cascade operator except
that
the return of the function is implicitly the first parameter of the
next
argument in the chainI don't like this idea, at all - I think we should aim for something
consistent with other languages. Per the Dart spec:A cascaded method invocation expression of the form e..suffix is
equivalent to the expression (t){t.suffix; return t;}(e).In other words, the expression always evaluates as the object, which
is fine for most cases, e.g. for everything you're doing with
chainable methods today - which can't actually return any values,
since they return $this. Note that something like PSR-7's HTTP
immutable models are actually factory methods, e.g. use-cases not
applicable to the cascade operator.The other marginal use case perhaps is cases where a builder of some
sort ends with a call to a factory method - this can be done without
adding a second operator, by using parens in a similar fashion to Dart
and others, e.g.:$object = ($builder ->>setFoo(1) ->>setBar(2) ->>setBaz(3) )->build();
Or obviously:
$builder ->>setFoo(1) ->>setBar(2) ->>setBaz(3); $object = $builder->build();
Regarding syntax - I feel the natural choice, e.g. similar to "." vs
"..", would be a longer arrow --> but that's ambiguous. (decrement
operator, greater than operator)The proposed |> operator looks horrible and is very awkward to type,
at least on both American and Danish keyboard - I use both. (it reads
like "or greater than" in my mind, so much so that glancing over
Sara's proposal earlier, I didn't even understand what it was.)Would something like ->> be ambiguous as well? That's fairly close too
- a double-headed arrow, not unlike the double dots of other
languages...IMHO double-headed arrow looks pretty nice and whole idea is great. Very
big +1 for this featureAgreed, but what about static methods? Triple colon perhaps?
A::setFoo(1)
:::setBar(2)
:::setBaz(3);And I do agree that the double period is cleaner, but the bus left the
station a very long time ago (PHP 3 at least) by making . the connotation
operator. Or at least I think so. If the parser could deal with it double
period would be best because it could apply to both contexts.$object->setFoo(1)
..setBar(2)
..setBaz(3);A_Class::setFoo(1)
..setBar(2)
..setBaz(3);But again, I don't know how feasible the above is since I know next to
nothing about internals.
Agreed, but what about static methods? Triple colon perhaps?
A::setFoo(1)
:::setBar(2)
:::setBaz(3);
This is a rather different feature, because you can't really express
that as an expression returning something. What is $result set to if I
run "$result = A:::setFoo(1)"? Or, equivalently, what is the value of
the chain you've written? (Presumably, the "::" on the first line should
be a ":::", otherwise I'm even less sure how to read it...)
I think saying "if you want the cascade operator, you have to use an
instance, not static methods" is reasonable enough. Especially with the
perennial discussion about namespaced functions being better than
classes with lots of static methods (if only we had function
autoloading, etc, etc).
Somebody quoted a concise explanation of the cascade operator earlier,
which bears repeating, in PHP context:
// Proposed
$result = $foo->>bar();
// Valid in PHP 7
$result = ( function($subject){ $subject->bar(); return $subject; } )(
$foo );
// Long-hand
$foo->bar(); // discard return result
$result = $foo;
There's no magic needed to create longer chains, or combine this with
other operators; it's not a transform done to the source code, just a
normal expression.
Regards,
Rowan Collins
[IMSoP]