With the branching of 7.1, and after some reflection on the previous
feedback, I'd like to reopen discussion of the Pipe Operator RFC
https://wiki.php.net/rfc/pipe-operator which I had previously put on
hold. I've changed much of the argument wording of the proposal, but
not the substantive feature set. If you still feel it's unworkable,
I'd like to encourage you to respond with what you think would make it
workable (if anything). Thanks.
-Sara
to me this code is perfectly readable and static code analysis is only complaining about missing semicolons at the end of the lines and short variable names:
$x = loadConfig();
$x = buildDic($x);
$x = getApp($x)
$x = getRouter($x)
$x = getDispatcher($x, $request)
$x = dispatchBusinessLogic($x, $request, new Response())
$x = renderResponse($x)
$x = buildPsr7Response($x)
$response =emit($x);
I'm not sure if there is a ORM or database library out there which constructs SQL queries with non-oop calls, maybe you can give a real-world example.
Regards
Thomas
Sara Golemon wrote on 21.07.2016 01:42:
With the branching of 7.1, and after some reflection on the previous
feedback, I'd like to reopen discussion of the Pipe Operator RFC
https://wiki.php.net/rfc/pipe-operator which I had previously put on
hold. I've changed much of the argument wording of the proposal, but
not the substantive feature set. If you still feel it's unworkable,
I'd like to encourage you to respond with what you think would make it
workable (if anything). Thanks.-Sara
Hi Thomas,
to me this code is perfectly readable and static code analysis is only complaining about missing semicolons at the end of the lines and short variable names:
$x = loadConfig();
$x = buildDic($x);
$x = getApp($x)
$x = getRouter($x)
$x = getDispatcher($x, $request)
$x = dispatchBusinessLogic($x, $request, new Response())
$x = renderResponse($x)
$x = buildPsr7Response($x)
$response =emit($x);
I agree the example code is readable, but it makes me feel the
language is a little obsolete.
Many coding standards, if not most, require to have meaningful
variable names even for temp variables.
$response = loadConfig()
|> buildDic($$)
|> getApp($$)
|> getRouter($$)
|> getDispatcher($$, $request)
|> dispatchBusinessLogic($$, $request, new Response())
|> renderResponse($$)
|> buildPsr7Response($$)
|> emit($$);
Nice, clean, readable and explicit. i.e. Don't have convert $x is
return value from previous call in programmer's head.
I'm not sure if there is a ORM or database library out there which constructs SQL queries with non-oop calls, maybe you can give a real-world example.
F# supports function pipelining by |> operator
It differs a little, but real world function pipelining examples could
be found in F#/OCaml codes.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
to me this code is perfectly readable and static code analysis is only complaining about missing semicolons at the end of the lines and short variable names:
$x = loadConfig();
$x = buildDic($x);
$x = getApp($x)
$x = getRouter($x)
$x = getDispatcher($x, $request)
$x = dispatchBusinessLogic($x, $request, new Response())
$x = renderResponse($x)
$x = buildPsr7Response($x)
$response =emit($x);
A proper static analyzer would also not that $x is continuously
changing types, another heave code smell.
I'm not sure if there is a ORM or database library out there which constructs
SQL queries with non-oop calls, maybe you can give a real-world example.
The third example in the RFC (FBShipIt) shows this exact operator in a
real-world usage in "php-like" code.
-Sara
Hi!
$x = loadConfig();
$x = buildDic($x);
$x = getApp($x)
$x = getRouter($x)
$x = getDispatcher($x, $request)
$x = dispatchBusinessLogic($x, $request, new Response())
$x = renderResponse($x)
$x = buildPsr7Response($x)
$response =emit($x);I agree the example code is readable, but it makes me feel the
language is a little obsolete.
This is a mindset that I feel to be objectionable and take issue with.
The idea that we have to constantly invent new syntax to replace working
old one, just because old is somehow "obsolete", even though new
syntax's only advantage is doing things slightly differently - it seems
to me an exactly wrong idea. It may be exciting to invent new syntaxes -
but for an industry programmer that has other priorities, like code
stability, compatibility, maintainability, etc. "new" is not a positive
things unless it gives them measurable or at least perceivable
improvement on these qualities.
Existing syntax is not "obsolete" and works completely well. New syntax
invents new magic variables (thing that never existed in PHP before,
adding a whole new conceptual level to PHP mental model) and a new way
of doing the same thing that is already perfectly doable right now with
exactly the same effort. I personally strongly object to such changes.
There is a lot of ways in which PHP needs improvement, but right now I
think inventing more syntax tricks in not one of them. Even in syntax
department, PHP has areas where we could use improvement (e.g. to name
named arguments as one) but this one doesn't seem to do much but doing
the same thing in a shiny new way. Read: less comprehensible for people
not watching "latest new 20 syntaxes PHP invented in the next version",
more things to learn to read PHP code, more things to maintain, more
complexity for the language that once was supposed to be accessible to
beginners.
This is the price of all innovation, but sometimes benefits are much
greater and the price is completely warranted. I do not feel this is the
case here.
Stas Malyshev
smalyshev@gmail.com
There is a lot of ways in which PHP needs improvement, but right now I
think inventing more syntax tricks in not one of them. Even in syntax
department, PHP has areas where we could use improvement (e.g. to name
named arguments as one) but this one doesn't seem to do much but doing
the same thing in a shiny new way. Read: less comprehensible for people
not watching "latest new 20 syntaxes PHP invented in the next version",
more things to learn to read PHP code, more things to maintain, more
complexity for the language that once was supposed to be accessible to
beginners.
This is the price of all innovation, but sometimes benefits are much
greater and the price is completely warranted. I do not feel this is the
case here.
I just want to make sure you know that I 100% respect your feelings on
this RFC. I can't comprehensively argue against them, so I won't try.
I'll only say that I don't expect to see |> in rampant use in the next
two years, maybe not in five. But that's okay, because that feature
will (I hope) be there for private codebases soon, and public
codebases later, and I believe it will make code more readable.
-Sara
With the branching of 7.1, and after some reflection on the previous
feedback, I'd like to reopen discussion of the Pipe Operator RFC
https://wiki.php.net/rfc/pipe-operator which I had previously put on
hold. I've changed much of the argument wording of the proposal, but
not the substantive feature set. If you still feel it's unworkable,
I'd like to encourage you to respond with what you think would make it
workable (if anything). Thanks.-Sara
I am still generally in favor of this proposal. Especially when dealing
with nested array functions this operator would be a big boon to
readability.
However, the introduction discusses fluent chained methods of objects,
and states " This RFC aims to improve code readability by bringing
fluent expressions to functional and OOP libraries not originally
designed for the task." The examples, however, all seem to be centered
around procedural calls. (A static method call is the same thing as a
procedural function call in this respect.) When dealing with methods on
an object, it seems it wouldn't offer much.
This other recent discussion/proposal for a "Cascade" operator seems
like it would handle the OOP/method case much better:
http://news.php.net/php.internals/94466
Note: I am not suggesting one is a substitute for the other; rather,
that they are complementary by addressing different parts of the problem
space, and the Pipe RFC should likely not emphasize OOP usage potential
as I see not a great deal there. I am still in favor of it, but let's
not over-state its use cases.
PS: I am very disappointed that you chose to name the $$ token
T_PIPE_VARIABLE and not T_BLINGBLING.
--Larry Garfield
I am still generally in favor of this proposal. Especially when dealing
with nested array functions this operator would be a big boon to
readability.
That's honestly my 90% use-case as well. array_merge and array_filter
in particular.
However, the introduction discusses fluent chained methods of objects, and
states " This RFC aims to improve code readability by bringing fluent
expressions to functional and OOP libraries not originally designed for the
task." The examples, however, all seem to be centered around procedural
calls. (A static method call is the same thing as a procedural function
call in this respect.) When dealing with methods on an object, it seems it
wouldn't offer much.
In this context, I'd argue instance method calls aren't much different
from static method calls either, but I wanted to avoid too many
abstract/contrived examples.
I suppose one might do something like:
return $this->loadConfig()
|> $arg->useConfig($$)
|> $this->loadUser($$)
|> array_merge($$, $this->userDefaults);
But the PSR7 example is already contrived as it is.
This other recent discussion/proposal for a "Cascade" operator seems like it
would handle the OOP/method case much better:http://news.php.net/php.internals/94466
Note: I am not suggesting one is a substitute for the other; rather, that
they are complementary by addressing different parts of the problem space,
and the Pipe RFC should likely not emphasize OOP usage potential as I see
not a great deal there. I am still in favor of it, but let's not over-state
its use cases.
Fair enough. They certainly complement one another and I wouldn't
argue either is a one-job-fits-all solution. I wasn't trying to
emphasize OOP usage so much as include it as applicable. I think we
might actually be agreeing in principle even if we're diverging in our
word choices. :)
PS: I am very disappointed that you chose to name the $$ token
T_PIPE_VARIABLE and not T_BLINGBLING.
I leave the silly token names to Ze'ev/Andi (T_PAAMAYIM_NEKUDOTAYIM)
and Davey (T_SPACESHIP).
I am nothing if not entirely serious and professional. ;p
-Sara
P.S. - I'm totes going to make that a secondary voting choice now.
Name the token, 50% majority wins.
[...]
return $this->loadConfig()
|> $arg->useConfig($$)
|> $this->loadUser($$)
|> array_merge($$, $this->userDefaults);But the PSR7 example is already contrived as it is.
This other recent discussion/proposal for a "Cascade" operator seems like it
would handle the OOP/method case much better:http://news.php.net/php.internals/94466
Note: I am not suggesting one is a substitute for the other; rather, that
they are complementary by addressing different parts of the problem space,
and the Pipe RFC should likely not emphasize OOP usage potential as I see
not a great deal there. I am still in favor of it, but let's not over-state
its use cases.Fair enough. They certainly complement one another and I wouldn't
argue either is a one-job-fits-all solution.
[...]
Hi,
Would joining the two be an option?
If $$ is in the parameter-list, use that as the position for the
parameter. If not, use the parameter as first argument?
Kind regards,
Stefan
However, the introduction discusses fluent chained methods of objects, and
states " This RFC aims to improve code readability by bringing fluent
expressions to functional and OOP libraries not originally designed for the
task." The examples, however, all seem to be centered around procedural
calls. (A static method call is the same thing as a procedural function
call in this respect.) When dealing with methods on an object, it seems it
wouldn't offer much.In this context, I'd argue instance method calls aren't much different
from static method calls either, but I wanted to avoid too many
abstract/contrived examples.I suppose one might do something like:
return $this->loadConfig()
|> $arg->useConfig($$)
|> $this->loadUser($$)
|> array_merge($$, $this->userDefaults);But the PSR7 example is already contrived as it is.
This other recent discussion/proposal for a "Cascade" operator seems like it
would handle the OOP/method case much better:http://news.php.net/php.internals/94466
Note: I am not suggesting one is a substitute for the other; rather, that
they are complementary by addressing different parts of the problem space,
and the Pipe RFC should likely not emphasize OOP usage potential as I see
not a great deal there. I am still in favor of it, but let's not over-state
its use cases.Fair enough. They certainly complement one another and I wouldn't
argue either is a one-job-fits-all solution. I wasn't trying to
emphasize OOP usage so much as include it as applicable. I think we
might actually be agreeing in principle even if we're diverging in our
word choices. :)
I agree. I'm entirely on board with the feature; more just critiquing
the RFC intro text, which mentions OOP fluency as a use case, which I
think is an over-reach. It's a useful enough feature even without
talking about that, and it seems we agree that the syntax when used with
methods is a bit awkward.
P.S. - I'm totes going to make that a secondary voting choice now.
Name the token, 50% majority wins.
:-)
--Larry Garfield
FWIW, I've read the manual page for the Hack page, and the RFC, a couple of
times now, and I simply don't understand it.
Are most PHP developers going to understand this feature, the meaning of
$$, and when/how to use this?
Are they going to be able to read code written in this way?
To your knowledge, are there any other languages where this feature is
found, or is it another one of those exotic features currently found in
Hack and nowhere else? (I know a bunch of languages, and this feature
doesn't ring any bells.)
How does this feature compare with the cascade operator more commonly found
in other languages?
I mean, maybe it's just me, because I'm familiar with the cascade operator
from other languages - but it seems simpler, more intuitive, easier to pick
up, and appears to solve most of the same problems? If so, perhaps it would
be right to consider the cascade operator as an alternative to this feature.
I know that Hack may be closer in nature to PHP than some other languages,
but if someone is familiar with both, likely they're not coming from Hack
and moving to PHP, they're likely moving from PHP to Hack, so language
similarity might not be the best argument for referencing Hack on this
point, as opposed to referencing other languages...
It seems to me, the main difference between the pipe operator and a cascade
operator, is the anonymous context variable $$ created by the pipe operator
- I think, partially, this is what makes those expression hard to read; the
context changes (or does it?) along the way, but the (nameless) symbol used
to reference those objects, in the same expression, are identical.
Rather than writing extremely long expressions, as demonstrated in the RFC,
I think, personally, if this feature were introduced, I'd lean more on
intermediary variables, with names, that clarify the meaning - referencing
a bunch of intermediaries with a nameless variable doesn't help readability
at all, in my opinion.
In contrast, I have no issue reading expressions with the cascade operator;
again, maybe that's just because I'm familiar with that operator from other
languages, but I don't think the nameless $$ variable helps readability or
understanding.
Just my two cents.
On Fri, Jul 22, 2016 at 5:54 PM, Larry Garfield larry@garfieldtech.com
wrote:
However, the introduction discusses fluent chained methods of objects,
and
states " This RFC aims to improve code readability by bringing fluent
expressions to functional and OOP libraries not originally designed
for the
task." The examples, however, all seem to be centered around
procedural
calls. (A static method call is the same thing as a procedural
function
call in this respect.) When dealing with methods on an object, it
seems it
wouldn't offer much.In this context, I'd argue instance method calls aren't much different
from static method calls either, but I wanted to avoid too many
abstract/contrived examples.I suppose one might do something like:
return $this->loadConfig()
|> $arg->useConfig($$)
|> $this->loadUser($$)
|> array_merge($$, $this->userDefaults);But the PSR7 example is already contrived as it is.
This other recent discussion/proposal for a "Cascade" operator seems
like it
would handle the OOP/method case much better:http://news.php.net/php.internals/94466
Note: I am not suggesting one is a substitute for the other; rather,
that
they are complementary by addressing different parts of the problem
space,
and the Pipe RFC should likely not emphasize OOP usage potential as I
see
not a great deal there. I am still in favor of it, but let's not
over-state
its use cases.Fair enough. They certainly complement one another and I wouldn't
argue either is a one-job-fits-all solution. I wasn't trying to
emphasize OOP usage so much as include it as applicable. I think we
might actually be agreeing in principle even if we're diverging in our
word choices. :)I agree. I'm entirely on board with the feature; more just critiquing
the RFC intro text, which mentions OOP fluency as a use case, which I
think is an over-reach. It's a useful enough feature even without
talking about that, and it seems we agree that the syntax when used with
methods is a bit awkward.P.S. - I'm totes going to make that a secondary voting choice now.
Name the token, 50% majority wins.:-)
--Larry Garfield
I mean, maybe it's just me, because I'm familiar with the cascade operator
from other languages - but it seems simpler, more intuitive, easier to pick
up, and appears to solve most of the same problems? If so, perhaps it would
be right to consider the cascade operator as an alternative to this feature.
They're not really the same thing at all; in some ways they're actually
opposites. The cascade operator is a way of discarding the result of an
object-oriented expression, and reusing the same context repeatedly. The
pipe operator is a way of capturing the result of a procedural
expression, and passing it forward to the next expression.
It seems to me, the main difference between the pipe operator and a cascade
operator, is the anonymous context variable $$ created by the pipe operator
- I think, partially, this is what makes those expression hard to read; the
context changes (or does it?) along the way, but the (nameless) symbol used
to reference those objects, in the same expression, are identical.
Yes, the $$ means "result of last expression". In essence, it's a bit
like Perl's $_ variable, except that it doesn't exist outside the pipe
syntax. It has to exist to say where you're going to use that result in
the next expression.
In the cascade operator, you don't need a notation for it, because the
context is always on the left of the operator:
$foo
->>setBar(1) // context is $foo->...
->>setBar(2); // context is still $foo->...
But again, this isn't the primary difference between the operators; the
difference is that one is a way of discarding results, the other is a
way of carrying results forward.
Regards,
--
Rowan Collins
[IMSoP]
FWIW, I've read the manual page for the Hack page, and the RFC, a couple of
times now, and I simply don't understand it.
Perhaps the documentation needs clarifying then.
Are most PHP developers going to understand this feature, the meaning of
$$, and when/how to use this?
Yes. PHP developers are excellent at Google and StackOverflow.
Are they going to be able to read code written in this way?
Yes.
To your knowledge, are there any other languages where this feature is
found, or is it another one of those exotic features currently found in
Hack and nowhere else? (I know a bunch of languages, and this feature
doesn't ring any bells.)
Elixir, F#, Swift (via library extension), ISTR a few others when I
was researching a few months ago, but can't recall them offhand.
How does this feature compare with the cascade operator more commonly found
in other languages?
To turn your previous question around, what languages?
I see them complementing one another, serving different goals and
solving different problems. I suppose you could ask how this compares
with short ternaries, coalesce, or bitwise xor, and the question will
make as much sense.
I mean, maybe it's just me, because I'm familiar with the cascade operator
from other languages - but it seems simpler, more intuitive, easier to pick
up, and appears to solve most of the same problems? If so, perhaps it would
be right to consider the cascade operator as an alternative to this feature.
I would rather consider them both since they solve different problems
in different ways.
I know that Hack may be closer in nature to PHP than some other languages,
but if someone is familiar with both, likely they're not coming from Hack
and moving to PHP, they're likely moving from PHP to Hack, so language
similarity might not be the best argument for referencing Hack on this
point, as opposed to referencing other languages...
Fair point, I'll add mentioned of the above languages to the RFC.
It seems to me, the main difference between the pipe operator and a cascade
operator, is the anonymous context variable $$ created by the pipe operator
- I think, partially, this is what makes those expression hard to read; the
context changes (or does it?) along the way, but the (nameless) symbol used
to reference those objects, in the same expression, are identical.
It's also what makes the cascade operator unable to solve all the
problems which the pipe operator is capable of solving. Cascade
applies to a very narrow band of instance method calls. Pipe applies
best to static methods and procedural functions (which some
applicability to methods). The flexibility of being able to place
that lhs element in an arbitrary location is what makes it powerful.
Rather than writing extremely long expressions, as demonstrated in the RFC,
I think, personally, if this feature were introduced, I'd lean more on
intermediary variables, with names, that clarify the meaning - referencing
a bunch of intermediaries with a nameless variable doesn't help readability
at all, in my opinion.
The RFC states why this may not be a preferred course. How do we
know, at a glance, that these well named intermediates are/aren't used
later in the scope? What happens to destructor ordering when the
variable lives till the end of the function? How does this impact
optimization potential?
In contrast, I have no issue reading expressions with the cascade operator;
again, maybe that's just because I'm familiar with that operator from other
languages, but I don't think the nameless $$ variable helps readability or
understanding.
You keep acting as if pipe vs cascade is even a competition. It's
not. They're different solutions to different problems which require
different approaches.
-Sara
This is a great idea in general, but I think that this kind of
operator is not the ideal (expect for $$ that seems very good).
Some possibilities to think about:
|> (as suggested) seems strange and not very clear, mainly in linear calls
--> can be too long, but can make more sense or continuing, but can
confuse with simple ->
$> seems like terminal, but can tell like "keep this root-variable and
run it", bad for linear too
<- is short, maybe can tells "call it and return to root-variable", in
linear can be confused with "minus" minus operation ($x<-a())
=> is short, but can be confused why array syntax, but good for linear
.. (like Dart) is short, but can be confused why a (double?) concat,
not seems PHP in general (but still a good option)
Another option is make calls without define an operator, the problem
is that can be not clear or then cause break changes (very bad for
linear).
Or defining a new keyword, but it can be exhaustive or reduce readability.
Should be think about the linear readability too, for instance:
$object->a()->b()->c() vs. $object|>a()|>b()|>c().
Examples: http://pastebin.com/rguUSxDr
It can works to avoid matroska (as initial suggestion) but for objects too.
PHP should identify if this operator is used over object or other type
(that allows the use of $$).
The problem is it can be confused: are you executing an object method
or another function with the object?
Like in: $clockObject |> setHour(12) |> is_string($$). 'is_string' is
from Clock or PHP native function?
Example: http://pastebin.com/t79kjaHQ
This is a great idea in general, but I think that this kind of
operator is not the ideal (expect for $$ that seems very good).Some possibilities to think about:
|> (as suggested) seems strange and not very clear, mainly in linear calls
[...]
Should be think about the linear readability too, for instance:
$object->a()->b()->c() vs. $object|>a()|>b()|>c().
I think it's quite clear, personally, particularly if you just add a bit
of whitespace:
$thing |> a($$) |> b($$) |> c($$)
The |> looks kind of like a triangle pointing to the next pipe.
It can works to avoid matroska (as initial suggestion) but for objects too.
PHP should identify if this operator is used over object or other type
(that allows the use of $$).
The problem is it can be confused: are you executing an object method
or another function with the object?
Like in: $clockObject |> setHour(12) |> is_string($$). 'is_string' is
from Clock or PHP native function?
I think you may be confusing this with the other, somewhat
complementary, proposal of a "method cascade" operator. Since this
operator always takes the result of one expression as the input to the
next, the equivalent for object methods already exists: ->
Your example wouldn't do anything much, because there's no $$ in
setHour(12), but:
$clockObject -> setHour(12) |> is_string($$)
would be equivalent to:
is_string( $clockObject -> setHour(12) )
That said, if there's a possibility we'll have both features, we need to
think about how the operators will look next to each other, and how easy
it will be to pick the right one.
Regards,
Rowan Collins
[IMSoP]
With the branching of 7.1, and after some reflection on the previous
feedback, I'd like to reopen discussion of the Pipe Operator RFC
https://wiki.php.net/rfc/pipe-operator which I had previously put on
hold. I've changed much of the argument wording of the proposal, but
not the substantive feature set. If you still feel it's unworkable,
I'd like to encourage you to respond with what you think would make it
workable (if anything). Thanks.
It looks like the examples are all still function calls. Could you
clarify what expressions would be acceptable on the right-hand side?
In particular, can I assign to a variable at the end of the pipe?
foo() |> bar($$) |> $result = $$;
As discussed before, I think pipes would be most useful if values could
"exit on the right". For which I would also like to be able to do this:
foo() |> bar($$) |> return $$;
(Or, as discussed, special syntax for one or both of these.)
Regards,
Rowan Collins
[IMSoP]
With the branching of 7.1, and after some reflection on the previous
feedback, I'd like to reopen discussion of the Pipe Operator RFC
https://wiki.php.net/rfc/pipe-operator which I had previously put on
hold. I've changed much of the argument wording of the proposal, but
not the substantive feature set. If you still feel it's unworkable,
I'd like to encourage you to respond with what you think would make it
workable (if anything). Thanks.It looks like the examples are all still function calls. Could you clarify
what expressions would be acceptable on the right-hand side?
Any non-terminal expression.
In particular, can I assign to a variable at the end of the pipe?
foo() |> bar($$) |> $result = $$;
Sure. ($result = $$) is an expression which returns the assigned
value, so it's a valid non-terminal.
$alsoResult = foo() |> bar($$) |> $result = $$;
var_dump($alsoResult === $result); // bool(true)
As discussed before, I think pipes would be most useful if values could
"exit on the right". For which I would also like to be able to do this:foo() |> bar($$) |> return $$;
Are you picturing the return statement returning from the current
function? Or "returning" from the current pipe chain?
I think you mean the former, in which case I'd ask how that'd better/worse than:
return foo() |> bar($$);
(Or, as discussed, special syntax for one or both of these.)
As above, I don't think special syntax adds anything for either of these cases.
-Sara
Are you picturing the return statement returning from the current
function? Or "returning" from the current pipe chain?I think you mean the former, in which case I'd ask how that'd better/worse than:
return foo() |> bar($$);
I do indeed mean returning from the current function. I went into more
detail (perhaps too much!) on the previous thread, but the basic premise
is the pipe operator gives you code that reads left to right. Adding an
element where you have to jump back to the beginning of the expression
feels like it defeats that.
You picked an example with a very short pipeline, and the "return" is
fairly obvious; but then "return bar(foo());" is not a great candidate
for using the operator in the first place. Take a longer example:
return loadConfig()
|> buildDic($$)
|> getApp($$)
|> getRouter($$)
|> getDispatcher($$, $request)
|> dispatchBusinessLogic($$, $request, new Response())
|> renderResponse($$)
|> buildPsr7Response($$)
|> emit($$);
If you read through that pipeline, you get down to emit($$), and then
have to scan back up to figure out where result of that is going to end
up. Compare:
loadConfig()
|> buildDic($$)
|> getApp($$)
|> getRouter($$)
|> getDispatcher($$, $request)
|> dispatchBusinessLogic($$, $request, new Response())
|> renderResponse($$)
|> buildPsr7Response($$)
|> emit($$)
|> return $$;
Here you can read through all the steps in order, right up to the last
action, which is returning the resulting value.
Even the name "pipe" is suggesting that something goes in one end, and
comes out the other, so having the output pop out next to the input just
feels weird.
Regards,
--
Rowan Collins
[IMSoP]
Are you picturing the return statement returning from the current
function? Or "returning" from the current pipe chain?I think you mean the former, in which case I'd ask how that'd better/worse
than:return foo() |> bar($$);
I do indeed mean returning from the current function. I went into more
detail (perhaps too much!) on the previous thread, but the basic premise is
the pipe operator gives you code that reads left to right. Adding an element
where you have to jump back to the beginning of the expression feels like it
defeats that.
Ah! I understand your point now. Indeed, in terms of code-scan,
there's something of a whiplash effect going on. Now I understand the
motivation behind $> assignment and/or using a terminal like return $$
at the end.
Adding in support for some terminals (like return) could make sense,
it's an exception to a rule, but it's a reasonable looking one (at
first glance, anyway).
The assign to var at the end however, is something I'd rather handle
with the following:
foo() |> bar($$) |> $baz = qux($$);
Which is both legal with the syntax as-is, and entirely readable
without adding an extra operator.
-Sara
It's possible to use the tilde ~ easyly on keyboards?
For on BR/ABNT2 is easy. So maybe use ~> as operator could be fine,
instead of the triangle |>, and linear sounds good too, like:
$string~>escape($$)~>dump($$);
It's used currently on PHP for a bitwise operation (not), so I think
that the usage are not a problem in general.
Too will not have a conflict, because ~> no make any sense to PHP today.
2016-07-22 2:52 GMT-03:00 Sara Golemon pollita@php.net:
Are you picturing the return statement returning from the current
function? Or "returning" from the current pipe chain?I think you mean the former, in which case I'd ask how that'd better/worse
than:return foo() |> bar($$);
I do indeed mean returning from the current function. I went into more
detail (perhaps too much!) on the previous thread, but the basic premise is
the pipe operator gives you code that reads left to right. Adding an element
where you have to jump back to the beginning of the expression feels like it
defeats that.Ah! I understand your point now. Indeed, in terms of code-scan,
there's something of a whiplash effect going on. Now I understand the
motivation behind $> assignment and/or using a terminal likereturn $$
at the end.Adding in support for some terminals (like return) could make sense,
it's an exception to a rule, but it's a reasonable looking one (at
first glance, anyway).The assign to var at the end however, is something I'd rather handle
with the following:foo() |> bar($$) |> $baz = qux($$);
Which is both legal with the syntax as-is, and entirely readable
without adding an extra operator.-Sara
--
--
David Rodrigues
Den 2016-07-22 kl. 17:05, skrev David Rodrigues:
It's possible to use the tilde ~ easyly on keyboards?
For on BR/ABNT2 is easy. So maybe use ~> as operator could be fine,
instead of the triangle |>, and linear sounds good too, like:
$string~>escape($$)~>dump($$);It's used currently on PHP for a bitwise operation (not), so I think
that the usage are not a problem in general.
Too will not have a conflict, because ~> no make any sense to PHP today.
There was an RFC proposing that operator for short closures, see:
Recall that the operator was a bit controversial due to
e.g. japanese keyboard. Personally I liked the proposal
and I think the "pipe" sign fit well into an pipe operator:)
Regards //Björn Larsson
Morning Sara,
This has generated some very decent discussion.
It seems like time to put this to a vote, could you maybe find some time to
do that please ?
Alternatively, if there are outstanding issues that are stopping this
going to a vote, could we know what they are, and maybe your plan to
resolve them ?
Cheers
Joe
On Mon, Jul 25, 2016 at 3:52 PM, Björn Larsson bjorn.x.larsson@telia.com
wrote:
Den 2016-07-22 kl. 17:05, skrev David Rodrigues:
It's possible to use the tilde ~ easyly on keyboards?
For on BR/ABNT2 is easy. So maybe use ~> as operator could be fine,
instead of the triangle |>, and linear sounds good too, like:
$string~>escape($$)~>dump($$);It's used currently on PHP for a bitwise operation (not), so I think
that the usage are not a problem in general.
Too will not have a conflict, because ~> no make any sense to PHP today.There was an RFC proposing that operator for short closures, see:
Recall that the operator was a bit controversial due to
e.g. japanese keyboard. Personally I liked the proposal
and I think the "pipe" sign fit well into an pipe operator:)Regards //Björn Larsson
On Mon, Jul 25, 2016 at 11:52 PM, Björn Larsson bjorn.x.larsson@telia.com
wrote:
Den 2016-07-22 kl. 17:05, skrev David Rodrigues:
It's possible to use the tilde ~ easyly on keyboards?
For on BR/ABNT2 is easy. So maybe use ~> as operator could be fine,
instead of the triangle |>, and linear sounds good too, like:
$string~>escape($$)~>dump($$);It's used currently on PHP for a bitwise operation (not), so I think
that the usage are not a problem in general.
Too will not have a conflict, because ~> no make any sense to PHP today.There was an RFC proposing that operator for short closures, see:
Recall that the operator was a bit controversial due to
e.g. japanese keyboard. Personally I liked the proposal
and I think the "pipe" sign fit well into an pipe operator:)
I'm surprised someone noticed Japanese "~" char issue.
We have "~" char issue, but it would not be problem for programmers.
I guess you mentioned this issue.
https://ja.wikipedia.org/wiki/%E6%B3%A2%E3%83%80%E3%83%83%E3%82%B7%E3%83%A5
http://qiita.com/kasei-san/items/3ce2249f0a1c1af1cbd2
They are written in Japanese. Please use google translate or similar.
Wrongly configured keyboard could be another problem. We may ignore such
environment.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Ah! I understand your point now. Indeed, in terms of code-scan,
there's something of a whiplash effect going on. Now I understand the
motivation behind $> assignment and/or using a terminal likereturn $$
at the end.Adding in support for some terminals (like return) could make sense,
it's an exception to a rule, but it's a reasonable looking one (at
first glance, anyway).
Glad it makes sense. :) I realise "return $$" would have to have some
special handling, but it would feel more natural to me. I guess the only
concern is what happens when a pipeline has a return terminal and is
used in expression context:
$foo = bar() |> baz($$) |> return $$;
// theoretically translates to this invalid PHP:
$foo = return baz(bar());
I'm not sure how easily the compiler would be able to pick up that
that's an illegal construction.
I was going to say that "yield" would be worth considering at the same
time, but presumably that's already legal, because yield can appear as
an expression (to receive variables sent into a co-routine).
It's a shame neither "echo" nor "print" is useful for getting $$ out to
screen and leaving it unchanged (echo doesn't work in expression context
at all; print doesn't have a useful return value).
The assign to var at the end however, is something I'd rather handle
with the following:foo() |> bar($$) |> $baz = qux($$);
Which is both legal with the syntax as-is, and entirely readable
without adding an extra operator.
Yes, on reflection I think "|> $foo = $$" is probably easier to follow
than extra syntax. I quite like the idea of a whole language where data
always flows left-to-right, but we're used to that being what assignment
looks like.
It might be worth coming up with some examples to add to the RFC where
$$ is used in an expression other than a function call, because I wasn't
entirely sure when I read it if that was even allowed. It might also
clear up some of the confusion around this being anything to do with OO.
Off the top of my head, how about some maths:
$foo * $bar
|> 2 ** $$
|> sin($$ + 1)
|> $$ / 20
|> $result = $$;
Compiles to:
$result = sin((2 ** ($foo * $bar)) + 1) / 20;
Or:
$temp = $foo * $bar;
$temp = 2 ** $temp;
$temp = sin($temp + 1);
$result = $temp / 20;
Regards,
--
Rowan Collins
[IMSoP]
Glad it makes sense. :) I realise "return $$" would have to have some
special handling, but it would feel more natural to me. I guess the only
concern is what happens when a pipeline has a return terminal and is used in
expression context:$foo = bar() |> baz($$) |> return $$;
// theoretically translates to this invalid PHP:
$foo = return baz(bar());I'm not sure how easily the compiler would be able to pick up that that's an
illegal construction.
Right, which is where I'm hesitant to go down that road.
I was going to say that "yield" would be worth considering at the same time,
but presumably that's already legal, because yield can appear as an
expression (to receive variables sent into a co-routine).
Yep. Perfectly valid as-is, so a non-issue.
It's a shame neither "echo" nor "print" is useful for getting $$ out to
screen and leaving it unchanged (echo doesn't work in expression context at
all; print doesn't have a useful return value).
Yeah, those pegs really don't fit into this hole...
It might be worth coming up with some examples to add to the RFC where $$ is
used in an expression other than a function call, because I wasn't entirely
sure when I read it if that was even allowed. It might also clear up some of
the confusion around this being anything to do with OO.Off the top of my head, how about some maths:
$foo * $bar
|> 2 ** $$
|> sin($$ + 1)
|> $$ / 20
|> $result = $$;Compiles to:
$result = sin((2 ** ($foo * $bar)) + 1) / 20;
Or:
$temp = $foo * $bar;
$temp = 2 ** $temp;
$temp = sin($temp + 1);
$result = $temp / 20;
Fair point, I took those as a given, but they should be added. (And
yes, they're valid).
-Sara
With the branching of 7.1, and after some reflection on the previous
feedback, I'd like to reopen discussion of the Pipe Operator RFC
https://wiki.php.net/rfc/pipe-operator which I had previously put on
hold. I've changed much of the argument wording of the proposal, but
not the substantive feature set. If you still feel it's unworkable,
I'd like to encourage you to respond with what you think would make it
workable (if anything). Thanks.-Sara
--
I've talked to you about this RFC off-list, but I figured I should
mention it on-list as well. I think we should make |>
and $$
two
independent operators that work well together (rather than only
together).
The |>
symbol would be the piping operator with these semantics:
1. Evaluate the left-hand side.
2. Evaluate the right-hand side. Assert that the result is callable.
3. Pass the result from 1. as the single argument to 2.
The $$
symbol would be the partial function application operator
with these semantics:
1. When function application has `$$` as a parameter it becomes a
partial application instead. This result of a partial application is a
closure.
2. Each non-$$
parameter is evaluated and then bound at that position.
3. Each $$
will become a parameter to the closure which will be
passed to the inner function call at its original position.
4. Each parameter and closed variable will be done by reference or
by value depending on the function being called. The type will also be
inherited.
5. The return type of the closure will be inherited from the
function it is calling.
As an optimization when |>
and $$
are used in conjunction there is
no need to create closures. This would make the outlined semantics be
equivalent to the currently proposed RFC when used together.
What do the rest of you think about this instead?
Le 19/01/2017 à 13:54, Levi Morrison a écrit :
The
|>
symbol would be the piping operator with these semantics:
1. Evaluate the left-hand side.
2. Evaluate the right-hand side. Assert that the result is callable.
3. Pass the result from 1. as the single argument to 2.
May I suggest extending your 3rd rule to : when the right hand side has
the form of a function call, insert the result from 1. as first argument
of 2. This way, right hand side may specify additional arguments. Based
on the fact that, in 99% of PHP builtin functions where the concept
applies, the 'input' argument is the first one.
Example :
$string |> trim('.,;:')
$string |> trim()
IMO, not acceptable : $string |> trim
Regards
François
Le 19/01/2017 à 13:54, Levi Morrison a écrit :
The
|>
symbol would be the piping operator with these semantics:
1. Evaluate the left-hand side.
2. Evaluate the right-hand side. Assert that the result is callable.
3. Pass the result from 1. as the single argument to 2.May I suggest extending your 3rd rule to : when the right hand side has the
form of a function call, insert the result from 1. as first argument of 2.
This way, right hand side may specify additional arguments
If we only had |>
this may be good but since we are also proposing
$$
then this renders your suggestion unnecessary:
$string |> trim($$)
Would work just fine with no performance overhead.
Additionally, you could write:
$input |> array_map($fn, $$)
Or:
$input |> array_filter($$, $fn)
Basically, $$
gives the flexibility of passing additional arguments
and keeps |>
simple. No need for additional rules for |>
.
Le 19/01/2017 à 22:53, Levi Morrison a écrit :
Le 19/01/2017 à 13:54, Levi Morrison a écrit :
The
|>
symbol would be the piping operator with these semantics:
1. Evaluate the left-hand side.
2. Evaluate the right-hand side. Assert that the result is callable.
3. Pass the result from 1. as the single argument to 2.May I suggest extending your 3rd rule to : when the right hand side has the
form of a function call, insert the result from 1. as first argument of 2.
This way, right hand side may specify additional arguments
If we only had|>
this may be good but since we are also proposing
$$
then this renders your suggestion unnecessary:$string |> trim($$)
Would work just fine with no performance overhead.
Additionally, you could write:
$input |> array_map($fn, $$)
Or:
$input |> array_filter($$, $fn)
Basically,
$$
gives the flexibility of passing additional arguments
and keeps|>
simple. No need for additional rules for|>
.
Right, I just suggest to make the '$$' optional when used as first arg
of a rhs call. Except complex cases like array_xx() functions which will
generally require an explicit '$$', most cases will feature a '$$' as
first arg of a function call. This may be considered as better because
more explicit, but I think the case is prominent enough to justify this
'shortcut'.
Another question: Will you accept several occurences of '$$' in a RHS ?
Last, a cosmetic suggestion : replace '$$' with '$<' (more explicit as
'input data', imo).
Regards
François
On mobile, sorry for top posting.
Multiple $$ means the resulting closure will accept multple arguments.
I'm definitely against dropping the ($$) on the right hand side because it
would use non standard symbol lookup rules.
$x = trim;
This normally will look up a constant, and then apply barewords if it
doesn't exist. Let's not go down the road of special casing things.
Le 19/01/2017 à 22:53, Levi Morrison a écrit :
On Thu, Jan 19, 2017 at 11:12 AM, François Laupretre flaupretre@free.fr
wrote:Le 19/01/2017 à 13:54, Levi Morrison a écrit :
The
|>
symbol would be the piping operator with these semantics:
1. Evaluate the left-hand side.
2. Evaluate the right-hand side. Assert that the result is
callable.
3. Pass the result from 1. as the single argument to 2.May I suggest extending your 3rd rule to : when the right hand side has
the
form of a function call, insert the result from 1. as first argument of
This way, right hand side may specify additional arguments
If we only had
|>
this may be good but since we are also proposing
$$
then this renders your suggestion unnecessary:$string |> trim($$)
Would work just fine with no performance overhead.
Additionally, you could write:
$input |> array_map($fn, $$)
Or:
$input |> array_filter($$, $fn)
Basically,
$$
gives the flexibility of passing additional arguments
and keeps|>
simple. No need for additional rules for|>
.Right, I just suggest to make the '$$' optional when used as first arg of
a rhs call. Except complex cases like array_xx() functions which will
generally require an explicit '$$', most cases will feature a '$$' as first
arg of a function call. This may be considered as better because more
explicit, but I think the case is prominent enough to justify this
'shortcut'.Another question: Will you accept several occurences of '$$' in a RHS ?
Last, a cosmetic suggestion : replace '$$' with '$<' (more explicit as
'input data', imo).Regards
François
Le 19/01/2017 à 22:53, Levi Morrison a écrit :
On Thu, Jan 19, 2017 at 11:12 AM, François Laupretre flaupretre@free.fr
wrote:Le 19/01/2017 à 13:54, Levi Morrison a écrit :
The
|>
symbol would be the piping operator with these semantics:
1. Evaluate the left-hand side.
2. Evaluate the right-hand side. Assert that the result is
callable.
3. Pass the result from 1. as the single argument to 2.May I suggest extending your 3rd rule to : when the right hand side has
the
form of a function call, insert the result from 1. as first argument of
This way, right hand side may specify additional arguments
If we only had
|>
this may be good but since we are also proposing
$$
then this renders your suggestion unnecessary:$string |> trim($$)
Would work just fine with no performance overhead.
Additionally, you could write:
$input |> array_map($fn, $$)
Or:
$input |> array_filter($$, $fn)
Basically,
$$
gives the flexibility of passing additional arguments
and keeps|>
simple. No need for additional rules for|>
.Right, I just suggest to make the '$$' optional when used as first arg of a
rhs call. Except complex cases like array_xx() functions which will
generally require an explicit '$$', most cases will feature a '$$' as first
arg of a function call. This may be considered as better because more
explicit, but I think the case is prominent enough to justify this
'shortcut'.Another question: Will you accept several occurences of '$$' in a RHS ?
Last, a cosmetic suggestion : replace '$$' with '$<' (more explicit as
'input data', imo).Regards
François
Oops, sorry for an email that just quotes others; mis-clicked send.
Last, a cosmetic suggestion : replace '$$' with '$<' (more explicit as
'input data', imo).
If we aren't going to use $$
I'd like to use _
or __
which read
similar to "fill in the blank" and has precedence in other languages.
But at this stage I'd much rather focus on changing the general model
to what I've proposed instead of what is outlined in the RFC. I care
much more about the feature than the exact syntax for it.
Isn't _
more generally used as a "discard" placeholder in most languages?
At least in Swift, Go, Scala, Dart and C# (starting with v7) I think?
I don't recall having seen it mean "fill in the blank". In what languages?
Oops, sorry for an email that just quotes others; mis-clicked send.
Last, a cosmetic suggestion : replace '$$' with '$<' (more explicit as
'input data', imo).If we aren't going to use
$$
I'd like to use_
or__
which read
similar to "fill in the blank" and has precedence in other languages.But at this stage I'd much rather focus on changing the general model
to what I've proposed instead of what is outlined in the RFC. I care
much more about the feature than the exact syntax for it.
Isn't
_
more generally used as a "discard" placeholder in most languages?At least in Swift, Go, Scala, Dart and C# (starting with v7) I think?
I don't recall having seen it mean "fill in the blank". In what languages?
Oops, sorry for an email that just quotes others; mis-clicked send.
Last, a cosmetic suggestion : replace '$$' with '$<' (more explicit as
'input data', imo).If we aren't going to use
$$
I'd like to use_
or__
which read
similar to "fill in the blank" and has precedence in other languages.But at this stage I'd much rather focus on changing the general model
to what I've proposed instead of what is outlined in the RFC. I care
much more about the feature than the exact syntax for it.--
Scala does use it this way. It also uses it in pattern matching to
mean "match anything else" or "I don't care about this one".
As a userland developer I feel $$ (or some variation starting with $) is reasonably natural - it's a variation on a regular variable.
Sent from my iPhone
Isn't
_
more generally used as a "discard" placeholder in most languages?At least in Swift, Go, Scala, Dart and C# (starting with v7) I think?
I don't recall having seen it mean "fill in the blank". In what languages?
Oops, sorry for an email that just quotes others; mis-clicked send.
Last, a cosmetic suggestion : replace '$$' with '$<' (more explicit as
'input data', imo).If we aren't going to use
$$
I'd like to use_
or__
which read
similar to "fill in the blank" and has precedence in other languages.But at this stage I'd much rather focus on changing the general model
to what I've proposed instead of what is outlined in the RFC. I care
much more about the feature than the exact syntax for it.--
Scala does use it this way. It also uses it in pattern matching to
mean "match anything else" or "I don't care about this one".
Besides, I mean, I'm sure this has occurred to everyone, right?
https://gist.github.com/mindplay-dk/4ef61fd5c0a35e5aa8fc699febb86487
I personally find that this new syntax you're proposing requires a lot of
parsing.
I mean, whenever you see substr()
or array_map()
etc. you're intuitively
expecting the first argument to be the first argument, right? Now you have
to backtrack through other lines and figure out the context, or try to spot
the $$ and count arguments to figure out which is which.
Just using intermediary variables seems pretty straight-forward and
harmless, so that would be my personal preference - if my coworkers started
using this everywhere, I would likely refactor the code and introduce more
variables in the process of trying to parse and make sense of it.
IMO, shorter, isolated constructions are always easier to read, write,
understand and change than the much longer constructions with the new
operator shown in the RFC.
But I also stay away from fluent APIs for the same reason, so there's that.
Maybe it comes down to personal preference - it's definitely not to my
taste, sorry...
On Wed, Jan 25, 2017 at 7:06 AM, Stephen Reay php-lists@koalephant.com
wrote:
As a userland developer I feel $$ (or some variation starting with $) is
reasonably natural - it's a variation on a regular variable.Sent from my iPhone
On Tue, Jan 24, 2017 at 12:25 PM, Rasmus Schultz rasmus@mindplay.dk
wrote:
Isn't_
more generally used as a "discard" placeholder in most
languages?At least in Swift, Go, Scala, Dart and C# (starting with v7) I think?
I don't recall having seen it mean "fill in the blank". In what
languages?Oops, sorry for an email that just quotes others; mis-clicked send.
Last, a cosmetic suggestion : replace '$$' with '$<' (more explicit as
'input data', imo).If we aren't going to use
$$
I'd like to use_
or__
which read
similar to "fill in the blank" and has precedence in other languages.But at this stage I'd much rather focus on changing the general model
to what I've proposed instead of what is outlined in the RFC. I care
much more about the feature than the exact syntax for it.--
Scala does use it this way. It also uses it in pattern matching to
mean "match anything else" or "I don't care about this one".
Besides, I mean, I'm sure this has occurred to everyone, right?
https://gist.github.com/mindplay-dk/4ef61fd5c0a35e5aa8fc699febb86487
I personally find that this new syntax you're proposing requires a lot of
parsing.I mean, whenever you see
substr()
orarray_map()
etc. you're intuitively
expecting the first argument to be the first argument, right? Now you have
to backtrack through other lines and figure out the context, or try to spot
the $$ and count arguments to figure out which is which.
I didn't follow this. Here is the example from your gist written with
either Sara's or my proposal:
$output = $input
|> array_filter($$, function($n) { return $n % 2 == 0; })
|> array_map(function($n) { return $n ** 2; }, $$)
|> array_reduce($$, function($x, $y) { return $x + $y; })
;
Maybe you can explain it a bit more with this code?
With the branching of 7.1, and after some reflection on the previous
feedback, I'd like to reopen discussion of the Pipe Operator RFC
https://wiki.php.net/rfc/pipe-operator which I had previously put on
hold. I've changed much of the argument wording of the proposal, but
not the substantive feature set. If you still feel it's unworkable,
I'd like to encourage you to respond with what you think would make it
workable (if anything). Thanks.-Sara
--
I've talked to you about this RFC off-list, but I figured I should
mention it on-list as well. I think we should make|>
and$$
two
independent operators that work well together (rather than only
together).The
|>
symbol would be the piping operator with these semantics:1. Evaluate the left-hand side. 2. Evaluate the right-hand side. Assert that the result is callable. 3. Pass the result from 1. as the single argument to 2.
When you say assert the right hand side is callable, does that mean to
call an object method, you would do [$obj, 'method']? What about functions,
is it just the name like $str |> trim, or is it $str |>trim()
? Neither
makes sense to me in the context of PHP since methods/functions are named
objects, which is why when you pass a callback you have to give the string
name of the function instead of just the name of the function, IE
array_filter($arr, 'trim') vs array_filter($arr, trim).
I've talked to you about this RFC off-list, but I figured I should
mention it on-list as well. I think we should make|>
and$$
two
independent operators that work well together (rather than only
together).
Firstly, Levi, can I say I really like this line of thinking at first
sight. As long as we can avoid it becoming too cryptically Perlish...
When you say assert the right hand side is callable, does that mean to
call an object method, you would do [$obj, 'method']? What about functions,
is it just the name like $str |> trim, or is it $str |>trim()
?
This is a good point. The difference between the pipe operator as
proposed by Sara and the combination of two separate operators is that
in Sara's proposal you'd always write this:
$str |> trim($$)
But in Levi's proposal as I understand it, the right-hand side is not
syntax, it's just constrained to be callable, so the simpler (but rather
ugly) form would be:
$str |> 'trim'
On its own, trim($$) rather pointlessly wraps a function with one
argument into another function, still with one argument, effectively
short-hand for Closure::fromCallable('trim') [incidentally, fromCallable
isn't actually listed in the documentation yet].
Since ($$) would leave a closure effectively unchanged, you could
actually write:
$str |> trim($$)($$)($$)($$)
And interestingly, the $$ magic couldn't be used to turn a function with
one argument into one with zero, because trim($$)($foo) actually
executes the function.
This all feels fiddly for the same reason I dislike generators being
introduced with "function" rather than their own keyword: it's one
syntax hiding behind another. Which is a shame, because as I say, I
liked the general idea.
Regards,
--
Rowan Collins
[IMSoP]
On Thu, Jan 19, 2017 at 4:08 PM, Rowan Collins rowan.collins@gmail.com
wrote:
When you say assert the right hand side is callable, does that mean to
call an object method, you would do [$obj, 'method']? What about
functions,
is it just the name like $str |> trim, or is it $str |>trim()
?This is a good point. The difference between the pipe operator as proposed
by Sara and the combination of two separate operators is that in Sara's
proposal you'd always write this:$str |> trim($$)
But in Levi's proposal as I understand it, the right-hand side is not
syntax, it's just constrained to be callable, so the simpler (but rather
ugly) form would be:$str |> 'trim'
See I don't like that at all, I hate having to put functions/methods in
strings, as find usages and refactor tools generally don't find the
strings. But sometimes I have to yield my preference to those who outrank
me (aka those with voting power)
On Thu, Jan 19, 2017 at 4:08 PM, Rowan Collins rowan.collins@gmail.com
wrote:When you say assert the right hand side is callable, does that mean to
call an object method, you would do [$obj, 'method']? What about
functions,
is it just the name like $str |> trim, or is it $str |>trim()
?This is a good point. The difference between the pipe operator as proposed
by Sara and the combination of two separate operators is that in Sara's
proposal you'd always write this:$str |> trim($$)
But in Levi's proposal as I understand it, the right-hand side is not
syntax, it's just constrained to be callable, so the simpler (but rather
ugly) form would be:$str |> 'trim'
See I don't like that at all, I hate having to put functions/methods in
strings, as find usages and refactor tools generally don't find the
strings. But sometimes I have to yield my preference to those who outrank
me (aka those with voting power)
While this would be permitted:
$str |> 'trim'
So would:
$str |> trim($$)
I empathize that you don't like string-name callables (I really don't
like them either) but this RFC helps avoid the string if you want to.
Consider
// without my proposal:
array_map('trim', $input)
// with it:
array_map(trim($$), $input)
Which makes a bigger difference for namespaced functions:
// without my proposal:
array_map('namespaced\func\map', $input)
// with it (assuming you are in the correct namespace or
// did `use function namespaced\func\map`:
array_map(map($$), $input)
So to summarize, the right-hand-side of |>
being callable doesn't
mean you "have to" put it in a string; you can pair it with $$
to
avoid that.
I empathize that you don't like string-name callables (I really don't
like them either) but this RFC helps avoid the string if you want to.
Consider// without my proposal:
array_map('trim', $input)// with it:
array_map(trim($$), $input)
Sure, like I said in my previous message, ($$) acts as a shorthand for Closure::fromCallable on any callable that takes one argument. But syntax for getting a reference to a function has been discussed before, and it would be a shame to be able to do it for this special case but not others.
Straw manning, if name::fn got a reference to a function from its name, you could do:
$foo |> trim::fn
Which makes more sense than using a partial application operator without applying anything.
Regards,
--
Rowan Collins
[IMSoP]