▲ | donatj 7 days ago | |||||||||||||||||||||||||||||||||||||
I had this argument in the PHP community when the feature was being discussed, but I think the syntax is much more complicated to read, requiring backtracking to understand. It might be easier to write. Imagine you're just scanning code you're unfamiliar with trying to identify the symbols. Make sense of inputs and outputs, and you come to something as follows.
Look at this operation imaging your reading a big section of code you didn't write. This is embedded within hundreds or thousands of lines. Try to just make sense of what "result" is here? Do your eyes immediately shoot to its final line to get the return type?My initial desire is to know what $result is generally speaking, before I decide if I want to dive into its derivation. It's a string. To find that out though, you have to skip all the way to the final line to understand what the type of $result is. When you're just making sense of code, it's far more about the destination than the path to get there, and understanding these require you to read them backwards. Call me old fashioned, I guess, but the self-documentating nature of a couple variables defining what things are or are doing seems important to writing maintainable code and lowering the maintainers' cognitive load.
| ||||||||||||||||||||||||||||||||||||||
▲ | hombre_fatal 7 days ago | parent | next [-] | |||||||||||||||||||||||||||||||||||||
The problem with intermediate assignment is that they pollute your scope. You might have $values and then you transform it into $b, $values2, $foo, $whatever, and your code has to be eternally vigilant that it never accidentally refers to $values or any of the intermediate variables ever again since they only existed in service to produce some downstream result. Sometimes this is slightly better in languages that let you repeatedly shadow variables, `$values = xform1($values)`, but we can do better. That it's hard to name intermediate values is only a symptom of the problem where many intermediate values only exist as ephemeral immediate state. Pipeline style code is a nice general way to keep the top level clean. | ||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||
▲ | drakythe 7 days ago | parent | prev | next [-] | |||||||||||||||||||||||||||||||||||||
I don't disagree with you. I had trouble reading the examples at first. But what immediately struck me is this syntax is pretty much identical to chaining object methods that return values.
so while the syntax is not my favorite, it at least maintains consistency between method chaining and now function chaining (by pipe). | ||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||
▲ | altairprime 7 days ago | parent | prev | next [-] | |||||||||||||||||||||||||||||||||||||
It reads well to me, as someone familiar with Perl map and jq lambda. But I would syntactic sugar it rather more strongly using a new `|=>` operator implying a distributive `|>` into its now-inferred-and-silent => arguments:
As teaching the parser to distribute `fn($x) |=> ELEM1, ELEM2` into `fn($x) => ELEM1 |> fn($x) => ELEM2 |> …` so that the user isn’t wasting time repeating it is exactly the sort of thing I love from Perl, and it’s more plainly clear what it’s doing — and in what order, without having to unwrap parens — without interfering with any successive |> blocks that might have different needs.Of course, since I come from Perl, that lends itself well to cleaning up the array rollup in the middle using a reduce pipe, and then replacing all the words with operators to make incomprehensible gibberish but no longer needing to care about $x at all:
Which rolls up nicely into a one-liner that is completely comprehensible if you know that | is column, + is merge, < is reduce, and have the : represent the syntactic sugar for conserving repetitions of fn($x) into $x using a stable syntax that the reduce can also take advantage of:
Which reads as a nice simple sentence, since I grew up on Perl, that can be interpreted at a glance because it fits within a glance!So. I wouldn’t necessarily implement everything I can see possible here, because Perl proved that the space of people willing to parse symbols rather than words is not the complete programmer space. But I do stand by the helpfulness of the switch-like |=> as defined above =) | ||||||||||||||||||||||||||||||||||||||
▲ | philjohn 7 days ago | parent | prev | next [-] | |||||||||||||||||||||||||||||||||||||
This is what a good IDE brings to the table, it'll show that $result is of type string. The pipe operator (including T_BLING) was one of the few things I enjoyed when writing Hack at Meta. | ||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||
▲ | epolanski 7 days ago | parent | prev | next [-] | |||||||||||||||||||||||||||||||||||||
You're conflating different concepts: familiarity and simplicity. I don't find the pipe alternative to be much harder to read, but I'd also favour the first one. In any case, we shouldn't judge software and it's features on familiarity. | ||||||||||||||||||||||||||||||||||||||
▲ | sandbags 7 days ago | parent | prev | next [-] | |||||||||||||||||||||||||||||||||||||
I don’t disagree with your reasoning but I would have thought this pipe would be in an appropriately named function (at least that’s how I’d use it in Elixir) to help understand the result. | ||||||||||||||||||||||||||||||||||||||
▲ | troupo 7 days ago | parent | prev | next [-] | |||||||||||||||||||||||||||||||||||||
> I think the syntax is much more complicated to read, requiring backtracking to understand. Same as with `array_merge(...array_column($arr, 'values'));` or similar nested function calls. > Imagine you're just scanning code you're unfamiliar with trying to identify the symbols. Make sense of inputs and outputs, and you come to something as follows. We don't have to imagine :) People working in languages supporting pipes look at similar code all day long. > but the self-documentating nature of a couple variables defining what things are or are doing seems important to writing maintainable code Pipes do not prevent you from using a couple of variables. In your example I need to keep track of $values variable, see where it's used, unwrap nested function calls etc. Or I can just look at the sequential function calls. What PHP should've done though is just pass the piped value as the first argument of any function. Then it would be much cleaner:
I wouldn't be surprised if that's what will eventually happen | ||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||
▲ | mcaruso 7 days ago | parent | prev | next [-] | |||||||||||||||||||||||||||||||||||||
People use method chaining all the time and don't have any issue with it? It's equivalent to something like:
I think this just comes down to familiarity. | ||||||||||||||||||||||||||||||||||||||
▲ | tracker1 7 days ago | parent | prev | next [-] | |||||||||||||||||||||||||||||||||||||
I think it's more a matter of what you're used to. It's simply an operator and syntax that you aren't used to seeing. Like if they added back a character into English that you aren't familiar with and started using it in words that you no longer recognize. A lot of people could say the same of the rest/spread syntax as well. | ||||||||||||||||||||||||||||||||||||||
▲ | layer8 7 days ago | parent | prev | next [-] | |||||||||||||||||||||||||||||||||||||
I completely agree about intermediate variables (and with explicit type annotations in a typed language) to make the code more intelligible. But maybe also, the pipe syntax would be better as:
| ||||||||||||||||||||||||||||||||||||||
▲ | int_19h 7 days ago | parent | prev [-] | |||||||||||||||||||||||||||||||||||||
It's no different than chained property accesses or method calls, or more generally nested expressions. Which is to say, if you overuse it, you hamper readability, but if you have a named result for every single operation, it is also hard to read because it introduces too much noise. |