• sumeetdas 14 hours ago

    The first typed programming language where I've seen pipe operator |> in action was in F#. You can write something like:

      sum 1 2
      |> multiply 3
    
    
    and it works because |> pushes the output of the left expression as the last parameter into the right-hand function. multiply has to be defined as:

      let multiply b c = b \* c
    
    
    so that b becomes 3, and c receives the result of sum 1 2.

    RHS can also be a lambda too:

      sum 1 2 |> (fun x -> multiply 3 x)
    
    
    |> is not a syntactic sugar but is actually defined in the standard library as:

      let (|>) x f = f x
    
    
    For function composition, F# provides >> (forward composition) and << (backward composition), defined respectively as:

      let (>>) f g x = g (f x)
      let (<<) f g x = f (g x)
    
    
    We can use them to build reusable composed functions:

      let add1 x = x + 1
      let multiply2 x = x \* 2
      let composed = add1 >> multiply2 
    
    
    F# is a beautiful language. Sad that M$ stopped investing into this language long back and there's not much interest in (typed) functional programming languages in general.
    • christophilus 13 hours ago

      F# is excellent. It’s tooling, ecosystem, and compile times are the reason I don’t use it. I learned it alongside OCaml, and OCaml’s compilation speed spoiled me.

      It is indeed a shame that F# never became a first class citizen.

      • cosmos64 13 hours ago

        Lots of this, especially the tooling and ecosystem, improved considerably in the last couple of years.

        OCaml is a great language, as are others in the ML family. Isabelle is the first language that has introduced the |> pipe character, I think.

      • Akronymus 7 hours ago

        There are also ||> and |||> for automatically destructuring tuples and passing each part as a separate value along.

        And there are also the reverse pipes (<|, <|| and <|||)

        F# is, for me, the single most ergonomic language to work in. But yeah, M$ isn't investing in it, so there are very few oppurtunities to actually work with f# in the industry either.

        • tracker1 8 hours ago

          It's kind of wild that PHP gets a pipe(line) operator before JS finalizes its' version... of course they've had multiple competing proposals, of which I liked the F# inspired one the most... I've stopped relying on the likes of Babel (too much bloat) or I'd like to be able to use it. I used it for years for async functions and module syntax before they were implemented in node and browsers. Now it's hard to justify.

          • rpeden 10 hours ago

            Is |> actually an operator in F#? I think it's just a regular function in the standard library but maybe I'm remembering incorrectly.

            • laurentlb 9 hours ago

              It's defined in the standard library and can be redefined by anyone.

              It's usually called operator because it uses an infix notation.

              • int_19h 8 hours ago

                All operators are functions in F#, e.g. this is valid: (+) 1 2

              • dmead 12 hours ago

                Haskell seems pretty dead as well. Good think php has another option for line noise though.

                • gylterud 11 hours ago

                  What makes you believe Haskell is dead or even dying? New versions of GHC are coming out, and in my experience, developing Haskell has never been smoother (that’s not to say it is completely smooth).

                  • munificent 8 hours ago

                    Compare the Redmonk rankings in 2020 to 2025:

                    https://redmonk.com/sogrady/2020/02/28/language-rankings-1-2...

                    https://redmonk.com/sogrady/2025/06/18/language-rankings-1-2...

                    I think of languages as falling in roughly 3 popularity buckets:

                    1. A dominant conservative choice. These are ones you never have to justify to your CTO, the "no one ever got fired for buying IBM" languages. That's Java, Python, etc.

                    2. A well-known but deliberate choice. These are the languages where there is enough ecosystem and knowledge to be able to justify choosing them, but where doing so still feels like a deliberate engineering choice with some trade-offs and risk. Or languages where they are a dominant choice in one domain but less so in others. Ruby, Scala, Swift, Kotlin.

                    3. Everything else. These are the ones you'd have to fight to use professionally. They are either new and innovative or old and dying.

                    In 2020, Haskell was close to Kotlin, Rust, and Dart. They were in the 3rd bucket but their vector pointed towards the second. In 2025, Kotlin and Dart have pulled ahead into the second bucket, but Haskell is moving in the other direction. It's behind Perl, and Perl itself is not exactly doing great.

                    None of this is to say that Haskell is a bad language. There are many wonderful languages that aren't widely used. Popularity is hard and hinges on many extrinsic factors more than the merits of the language itself. Otherwise JavaScript wouldn't be at the top of the list.

                    • instig007 5 hours ago

                      > In 2020, Haskell was close to Kotlin, Rust, and Dart. [...] In 2025, Kotlin and Dart have pulled ahead into the second bucket, but Haskell is moving in the other direction.

                      > It's behind Perl, and Perl itself is not exactly doing great.

                      Your comment reminded me of gamers who "play games" by watching "letsplay" videos on youtube.

                    • epolanski 10 hours ago

                      And yet, while PHPs, Javas, and even nicher/newer languages like Kotlin, Clojure or Scala have plenty of killer software (software that makes it worth learning a language just to use that library/framework) Haskell has none after 30 years. Zero.

                      Mind you, I know and like Haskell, but its issues are highly tied to the failure of the simple haskell initiative (also the dreadful state of its tooling).

                      • gylterud 9 hours ago

                        There are lots of great libraries, like repa, servant, megaparsec, gloss, yampa… as well as bindings to lots of standard stuff. I consider parsing to be one of Haskell’s killer strengths and I would definitely use it to write a compiler.

                        There is also some popular user facing software like Pandoc, written in Haskell. And companies using it internally.

                        • epolanski 7 hours ago

                          The only non irrelevant compiler ever written in Haskell is for another borderline dead project: Elm.

                          • gylterud 5 hours ago

                            What are you on about?

                            The Agda compiler, Pugs, Cryptol, Idris, Copilot (not that copilot you are thinking of), GHC, PureScript, Elm…

                            These might not be mainstream, but are (or were for Pugs, but the others are current) important within their niche.

                        • milutinovici 10 hours ago

                          It has PostgREST, which is the heart of supabase

                          • myko 6 hours ago

                            I will not stand for this Xmonad slander

                            • instig007 5 hours ago

                              > also the dreadful state of its tooling

                              this is plain and unsubstantiated FUD

                              > Haskell has none after 30 years

                              > I know Haskell

                              I doubt it

                              • dmead 10 hours ago

                                yea I agree. haskell was my primary language for several years in the 00s. it's since had almost zero industry uptake. Don't come at me with jane street or the one off startup.

                                I thought for a while I'd be able to focus on getting jobs that liked haskell. it never happened.

                                • chriswarbo 9 hours ago

                                  I certainly wouldn't focus on getting a Haskell job. Yet they are out there; e.g. my current job is Haskell, and happens to be in the same sector (public transport) as my last job (which was mostly Scala).

                                  Also, I've found Haskell appropriate for some one-off tasks over the years, e.g.

                                  - Extracting a load of cross-referenced data from a huge XML file. I tried a few of our "common" languages/systems, but they all ran out of memory. Haskell let me quickly write something efficient-enough. Not sure if that's ever been used since (if so then it's definitely tech debt).

                                  - Testing a new system matched certain behaviours of the system it was replacing. This was a one-person task, and was thrown away once the old system was replaced; so no tech debt. In fact, this was at a PHP shop :)

                                  • dmead 8 hours ago

                                    Yea of course, its not really the focus for me either way. my point was that how great haskell seemed in grad school didn't match up with the real world interest.

                                    I use spark for most tasks like that now. Guido stole enough from haskell that pyspark is actually quite appealing for a lot of these tasks.

                                    • instig007 5 hours ago

                                      > Guido stole enough from haskell that pyspark is actually quite appealing for a lot of these tasks.

                                      He didn't do his homework. Guido or whoever runs things around the python language committee nowadays didn't have enough mental capacity to realize that the `match` must be a variable bindable expression and never a statement to prevent type-diverging case branches. They also refuse to admit that a non-blocking descriptor on sockets has to be a default property of runtime and never assigned a language syntax for, despite even Java folks proving it by example.

                              • dmead 10 hours ago

                                it's easy to learn and speak latin as well.

                                • gylterud 9 hours ago

                                  Yes, but there is very little modern latin slang. While GHC gives us great new extensions of Haskell quite often.

                                  • 1-more 8 hours ago

                                    Latin never paid my mortgage. Helped on the SATs though.

                            • donatj 13 hours 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.

                                  $result = $arr
                                      |> fn($x) => array_column($x, 'values')
                                      |> fn($x) => array_merge(...$x)
                                      |> fn($x) => array_reduce($x, fn($carry, $item) => $carry + $item, 0)
                                      |> fn($x) => str_repeat('x', $x);
                              
                              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.

                                  $values = array_merge(...array_column($arr, 'values'));
                                  $total  = array_reduce($values, fn($carry, $item) => $carry + $item, 0);
                              
                                  $result = str_repeat('x', $x);
                              • hombre_fatal 9 hours ago

                                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.

                                • donatj 3 hours ago

                                  If PHP scoped to blocks, it would be less of an issue, you could just wrap your procedural code in curly braces and call it a day

                                      {
                                          $foo = 'bar'; // only defined in this block
                                      }
                                  
                                  I use this reasonably often in Go, I wish it were a thing in PHP. PHP allows blocks like this but they seem to be noops best I can tell.
                                  • procaryote 9 hours ago

                                    Put it in a function and the scope you pollute is only as big as you make it.

                                    • hombre_fatal 8 hours ago

                                      Functions also pollute the scope the same way. And you don't want to be forced to extract a function that is never reused just to hide intermediate values; you should only have to extract a function when you want the abstraction.

                                      The pipeline transformation specifically lets you clean this up with functions at the scope of each ephemeral intermediate value.

                                      • ckdot 5 hours ago

                                        You definitely want to extract code into functions, even if you don’t need to reuse it. Functions names are documentation. And you reduce the mental load from those who read the code.

                                        • skoskie 5 hours ago

                                          That’s why we have classes and namespaces.

                                          Anyone can write good or bad code. Avoiding new functionality and syntax won’t change that.

                                    • drakythe 10 hours ago

                                      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.

                                        $result = $obj->query($sqlQuery)->fetchAll()[$key]
                                      
                                      so while the syntax is not my favorite, it at least maintains consistency between method chaining and now function chaining (by pipe).
                                      • 8n4vidtmkvmk 8 hours ago

                                        Speaking of query builders, we no longer have to guess whether it's mutating the underlying query object or cloning it with each operation. That's another big win for pipe IMO.

                                      • altairprime 9 hours ago

                                        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:

                                            $result = $arr |> fn($x) |=>
                                                array_column($x, 'values'),
                                                array_merge(...$x),
                                                array_reduce($x, fn($carry, $item) => $carry + $item, 0),
                                                str_repeat('x', $x);
                                        
                                        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:

                                            $result = $arr |> $x:
                                                ||> 'values'
                                                |+< $i: $x + $i
                                                |> str_repeat('x', $x);
                                        
                                        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:

                                            $result = $arr |> $x: ||> 'values' |+< $i: $x + $i |> str_repeat('x', $x);
                                        
                                        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 12 hours ago

                                          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.

                                          • xienze 12 hours ago

                                            > This is what a good IDE brings to the table, it'll show that $result is of type string.

                                            I think the parent is referring to what the result _means_, rather than its type. Functional programming can, at times, obfuscate meaning a bit compared to good ol’ imperative style.

                                            • 8n4vidtmkvmk 8 hours ago

                                              If you want meaning, don't call your variable "result"

                                          • tracker1 8 hours ago

                                            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.

                                            • sandbags 13 hours ago

                                              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.

                                              • epolanski 10 hours ago

                                                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.

                                                • int_19h 8 hours ago

                                                  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.

                                                  • layer8 11 hours ago

                                                    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:

                                                        $arr
                                                        |> fn($x) => array_column($x, 'values')
                                                        |> fn($x) => array_merge(...$x)
                                                        |> fn($x) => array_reduce($x, fn($carry, $item) => $carry + $item, 0)
                                                        |> fn($x) => str_repeat('x', $x)
                                                        |= $result;
                                                    • mcaruso 10 hours ago

                                                      People use method chaining all the time and don't have any issue with it? It's equivalent to something like:

                                                          $result = $arr
                                                              ->column('values')
                                                              ->merge()
                                                              ->reduce(fn($carry, $item) => $carry + $item, 0)
                                                              ->repeat('x');
                                                      
                                                      I think this just comes down to familiarity.
                                                      • troupo 11 hours ago

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

                                                          $result = $arr
                                                            |> array_column('values')
                                                            |> array_merge()
                                                            |> array_reduce(fn($carry, $item) => $carry + $item, 0)
                                                            |> fn($x) => str_repeat('x', $x);
                                                        
                                                        I wouldn't be surprised if that's what will eventually happen
                                                        • WorldMaker 7 hours ago

                                                          The article addresses this pretty well.

                                                          Quick summary: Hack used $$ (aka T_BLING) as the implicit parameter in a pipeline. That wasn't accepted as much fun as the name T_BLING can be. PHP looked for a solution and started looking for a Partial Function Application syntax they were happy with. That effort mostly deadlocked (though they hope to return to it) except for syntax some_function(...) for an unapplied function (naming a function without calling it).

                                                          Seems like an interesting artifact of PHP functions not being first class objects. I wish them luck on trying to clean up their partial application story further.

                                                      • bapak 19 hours ago

                                                        Meanwhile the JS world has been waiting for 10 years for this proposal, which is still in stage 2 https://github.com/tc39/proposal-pipeline-operator/issues/23...

                                                        • avaq 17 hours ago

                                                          Not only have we been waiting for 10 years, the most likely candidate to go forward is not at all what we wanted when the proposal was created:

                                                          We wanted a pipe operator that would pair well with unary functions (like those created by partial function application, which could get its own syntax), but that got rejected on the premise that it would lead to a programming style that utilizes too many closures[0], and which could divide the ecosystem[1].

                                                          Yet somehow PHP was not limited by these hypotheticals, and simply gave people the feature they wanted, in exactly the form it makes most sense in.

                                                          [0]: https://github.com/tc39/proposal-pipeline-operator/issues/22... [1]: https://github.com/tc39/proposal-pipeline-operator/issues/23...

                                                          • lexicality 16 hours ago

                                                            Am I correct in my understanding that you're saying that the developers of the most widely used JS engine saying "hey we can't see a way to implement this without tanking performance" is a silly hypothetical that should be ignored?

                                                            • jeroenhd 15 hours ago

                                                              With JS' async/await system basically running on creating temporary closures, I don't think things will change all that much to be honest.

                                                              Furthermore, I don't see why engines should police what is or isn't acceptable performance. Using functional interfaces (map/forEach/etc.) is slower than using for loops in most cases, but that didn't stop them from implementing those interfaces either.

                                                              I don't think there's that much of a performance impact when comparing

                                                                  const x = fun1(abc);
                                                                  const y = fun2(x);
                                                                  const z = fun3(y);
                                                                  fun4(z);
                                                              
                                                              and

                                                                  abc |> fun1 |> fun2 |> fun3 |> fun4
                                                              
                                                              especially when you end up writing code like

                                                                  fun1(abc).then( (x) => fun2(x)).then( (y) => fun3(y)).then((z) => fun4(z))
                                                              
                                                              when using existing language features.
                                                              • ufo 7 hours ago

                                                                The problem they were discussion in the linked Github issue are pipelines where the functions receive more than one argument.

                                                                    const x = fun1(a, 10)
                                                                    const y = fun2(x, 20)
                                                                    const z = fun3(y, 30)
                                                                
                                                                In this case the pipeline version would create a bunch of throwaway closures.

                                                                    a |> ((a) => fun1(a, 10))
                                                                      |> ((x) => fun2(x, 20))
                                                                      |> ((y) => fun3(y, 30))
                                                              • avaq 16 hours ago

                                                                They can't implement function application without tanking performance? I find that hard to believe. Especially considering that function application is already a commonly used (and, dare I say: essential) feature in the language, eg: `Math.sqrt(2)`.

                                                                All we're asking for is the ability to rewrite that as `2 |> Math.sqrt`.

                                                                What they're afraid of, my understanding goes, is that people hypothetically, may start leaning more on closures, which themselves perform worse than classes.

                                                                However I'm of the opinion that the engine implementors shouldn't really concern themselves to that extent with how people write their code. People can always write slow code, and that's their own responsibility. So I don't know about "silly", but I don't agree with it.

                                                                Unless I misunderstood and somehow doing function application a little different is actually a really hard problem. Who knows.

                                                                • nilslindemann 14 hours ago

                                                                  Your simple example (`2 |> Math.sqrt`) looks great, but when the code gets more complex, then the advantage of the pipe syntax is less obvious. For example,

                                                                      foo(1, bar(2, baz(3)), 3)
                                                                  
                                                                  becomes something like

                                                                      1 (2, (3 |> baz) > bar), 3 |> foo
                                                                  
                                                                  or

                                                                      (3 |> baz) |> (2, % |> bar) |> (1, %, 3 |> foo)
                                                                      
                                                                  
                                                                  That looks like just another way to write a thing in JavaScript, and it is not easier to read. What is the advantage?
                                                                  • avaq 13 hours ago

                                                                    Uhm, don't do it, then. That's like arguing that the addition of the ternary operator is a bad one because not all if/else blocks look better when translated into it.

                                                                    The goal is to linearlize unary function application, not to make all code look better.

                                                                    • sir_eliah 11 hours ago

                                                                      I think the commenter meant that once the new syntax is approved and adopted by the community, you have no choice to not use the syntax. You'll eventually change your project and will be forced to deal with reviewing this code.

                                                                • hajile 9 hours ago

                                                                  Closures won over OOP in Javascript a long time ago (eg, React switching from classes to functions + closures), but they still keep trying to force garbage like private variables on the community.

                                                                  Loads of features have been added to JS that have worse performance or theoretically enable worse performance, but that never stopped them before.

                                                                  Some concrete (not-exhaustive) examples:

                                                                  * Private variables are generally 30-50% slower than non-private variables (and also break proxies).

                                                                  * let/const are a few percent slower than var.

                                                                  * Generators are slower than loops.

                                                                  * Iterators are often slower due to generating garbage for return values.

                                                                  * Rest/spread operators hide that you're allocating new arrays and objects.

                                                                  * Proxies cause insane slowdowns of your code.

                                                                  * Allowing sub-classing of builtins makes everything slow.

                                                                  * BigInt as designs is almost always slower than the engine's inferred 31-bit integers.

                                                                  Meanwhile, Google and Mozilla refuse to implement proper tail calls even though they would INCREASE performance for a lot of code. They killed their SIMD projects (despite having them already implemented) which also reduced performance for the most performance-sensitive applications.

                                                                  It seems obvious that performance is a non-issue when it's something they want to add and an easy excuse when it's something they don't want to add.

                                                                  • tracker1 8 hours ago

                                                                    I wish I could upvote this more than once. I really liked the F# inspired pipe operator proposal and even used it a bit when I used to lean on 6to4/babel more, but it just sat and languished forever it seems. I can't really think of any other language feature I've seen since that I would have wanted more. The new Temporal being one exception.

                                                                    • hajile 8 hours ago

                                                                      It seems like none of the really good language proposals have much traction. Proper Tail Calls have been in the language for TEN YEARS now, but v8 and Spidermonkey still violate the spec and refuse to implement for no good reason.

                                                                      Record/tuple was killed off despite being the best proposed answer for eliminating hidden class mutation, providing deep O(1) comparisons, and making webworkers/threads/actors worth using because data transfer wouldn't be a bottleneck.

                                                                      Pattern matching, do expressions, for/while/if/else expressions, binary AST, and others have languished for years without the spec committee seemingly caring that these would have real, tangible upsides for devs and/or users without adding much complexity to the JIT.

                                                                      I'm convinced that most of the committee is completely divorced from the people who actually use JS day-to-day.

                                                                      • jedwards1211 2 hours ago

                                                                        I think it’s mainly because they struggled to get consensus on which syntax to go with for pipelines, since people were divided into three different camps. I wish they would just standardize all three options with a slightly different operator for each one

                                                                      • int_19h 8 hours ago

                                                                        > * Rest/spread operators hide that you're allocating new arrays and objects.

                                                                        Only in function calls, surely? If you're using spread inside [] or {} then you already know that it allocates.

                                                                        • hajile 7 hours ago

                                                                          It used to be said that "Lisp programmers know the value of everything and the cost of nothing."

                                                                          This applies to MOST devs today in my experience and doubly to JS and Python devs as a whole largely due to a lack of education. I'm fine with devs who never went to college, but it becomes an issue when they never bothered to study on their own either.

                                                                          I've worked with a lot of JS devs who have absolutely no understand of how the system works. Allocation and garbage collection are pure magic. They also have no understanding of pointers or the difference between the stack and heap. All they know is that it's the magic that makes their code run. For these kinds of devs, spread just makes the object they want and they don't understand that it has a performance impact.

                                                                          Even among knowledgeable devs, you often get the argument that "it's fast enough" and maybe something about optimizing down the road if we need it. The result is a kind of "slow by a thousand small allocations" where your whole application drags more than it should and there's no obvious hot spot because the whole thing is one giant, unoptimized ball of code.

                                                                          At the end of the day, ease of use, developer ignorance, and deadline pressure means performance is almost always the dead-last priority.

                                                                      • nobleach 6 hours ago

                                                                        I know that was the reasoning for the Records/Tuples proposal being shot down. I haven't dug too deeply into the pipeline operators other than to get a feel for both proposals.

                                                                        Most of the more interesting proposals tend to languish these days. When you look at everything that's advanced to Stage 3-4, it's like. "ok, I'm certain this has some amazing perf bump for some feature I don't even use... but do I really care?"

                                                                      • xixixao 16 hours ago

                                                                        I guess partially my fault, but even in the article, you can see how the Hack syntax is much nicer to work with than the functional one.

                                                                        Another angle is “how much rewriting does a change require”, in this case, what if I want to add another argument to the rhs function call. (I obv. don’t consider currying and point-free style a good solution)

                                                                        • WorldMaker 7 hours ago

                                                                          I am wondering if PHP explicitly rejecting Hack-style pipes (especially given the close ties between PHP and Hack, and that PHP doesn't have partial application, but JS does, sort of, though its UX could be improved) will add leverage to the F#-style proposal over the Hack-style.

                                                                          It may be useful data that the TC-29 proposal champions can use to fight for the F# style.

                                                                        • wouldbecouldbe 19 hours ago

                                                                          It’s really not needed, syntax sugar. With dots you do almost the same. Php doesn’t have chaining. Adding more and more complexity doesn’t make a language better.

                                                                          • chilmers 15 hours ago

                                                                            I'm tired of hearing the exact same arguments, "not needed", "just syntax sugar", "too much complexity", about every new syntax feature that gets added to JS. Somehow, once they are in the language, nobody's head explodes, and people are soon using them and they become uncontroversial.

                                                                            If people really this new syntax will make it harder to code in JS, show some evidence. Produce a study on solving representative tasks in a version of the language with and without this feature, showing that it has negative effects on code quality and comprehension.

                                                                            • robertlagrant 13 hours ago

                                                                              Presumably it's up to the change proposers to produce said study showing the opposite.

                                                                            • bapak 19 hours ago

                                                                              Nothing is really needed, C89 was good enough.

                                                                              Dots are not the same, nobody wants to use chaining like underscore/lodash allowed because it makes dead code elimination impossible.

                                                                              • pjmlp 17 hours ago

                                                                                K&R C was good enough for UNIX System V, why bother with C89.

                                                                                • boobsbr 15 hours ago

                                                                                  K&R C was the apex, we've just been going downhill since.

                                                                                  • lioeters 9 hours ago

                                                                                    This but unironically.

                                                                              • hajile 8 hours ago

                                                                                Chaining requires creating a class and ensuring everything sticks to the class and returns it properly so the chain doesn't blow up. As you add more options and do more stuff, this becomes increasingly hard to write and maintain.

                                                                                If I'm using a chained library and need another method, I have to understand the underlying data model (a leaky abstraction) and also must have some hack-ish way of extending the model. As I'm not the maintainer, I'm probably going to cause subtle breakages along the way.

                                                                                Pipe operators have none of these issues. They are obvious. They don't need to track state past the previous operator (which also makes debugging easier). If they need to be extended, look at your response value and add the appropriate function.

                                                                                Composition (whether with the pipe operator or not) is vastly superior to chaining.

                                                                                • Martinussen 15 hours ago

                                                                                  When you say chaining, do you mean autoboxing primitives? PHP can definitely do things like `foo()->bar()?->baz()`, but you'd have to wrap an array/string yourself instead of the methods being pulled from a `prototype` to use it there.

                                                                                  • troupo 19 hours ago

                                                                                    > With dots you do almost the same.

                                                                                    Keyword: almost. Pipes don't require you to have many different methods on every possible type: https://news.ycombinator.com/item?id=44794656

                                                                                    • purerandomness 14 hours ago

                                                                                      If your team prefers not to use this new optional feature, just enable a PHPStan rule in your CI/CD pipeline that prevents code like this getting merged.

                                                                                      • EGreg 19 hours ago

                                                                                        It’s not really chaining

                                                                                        More like thenables / promises

                                                                                        • wouldbecouldbe 19 hours ago

                                                                                          It looks like chaining, but with possibility of adding custom functions?

                                                                                          • bapak 19 hours ago

                                                                                            It's chaining without having to vary the return of each function. In JS you cannot call 3.myMethod(), but you could with 3 |> myMethod

                                                                                            • cyco130 18 hours ago

                                                                                              It requires parentheses `(3).myMethod()` but you can by monkey patching the Number prototype. Very bad idea, but you absolutely can.

                                                                                              • EGreg 10 hours ago

                                                                                                Not only that

                                                                                                In chaining, methods all have to be part of the same class.

                                                                                                In C++ we had this stuff ages ago, it’s called abusing streaming operators LMAO

                                                                                          • te_chris 18 hours ago

                                                                                            Dots call functions on objects, pipe passes arguments to functions. Totally missing the point.

                                                                                          • fergie 16 hours ago

                                                                                            Good- the [real world examples of pipes in js](https://github.com/tc39/proposal-pipeline-operator?tab=readm...) are deeply underwhelming IMO.

                                                                                            • epolanski 10 hours ago

                                                                                              Sadly they went obsessing over pipes with promises which don't fit the natural flow.

                                                                                              Go explain them that promises already have a natural way to chain operations through the "then" method, and don't need to fit the pipe operator to do more than needed.

                                                                                              • lacasito25 18 hours ago

                                                                                                in typescript we can do this

                                                                                                let res res = op1() res = op2(res.op1) res = op3(res.op2)

                                                                                                type inference works great, and it is very easy to debug and refactor. In my opinion even more than piping results.

                                                                                                Javascript has enough features.

                                                                                                • defraudbah 16 hours ago

                                                                                                  do not let me start on monads in golang...

                                                                                                  both are going somewhere and super popular though

                                                                                                  • 77pt77 13 hours ago

                                                                                                    Best you'll git will be 3 new build systems and 10 new frameworks

                                                                                                  • mort96 16 hours ago

                                                                                                    I'm surprised that the example requires lambdas... What's the purpose of the `|> foo(...)' syntax if the function has to take exactly one operand? Why is it necessary to write this?

                                                                                                        $arr
                                                                                                            |> fn($x) => array_column($x, 'tags')
                                                                                                    
                                                                                                    Why doesn't this work?

                                                                                                        $arr
                                                                                                            |> array_column(..., 'tags')
                                                                                                    
                                                                                                    And when that doesn't work, why doesn't this work?

                                                                                                        $arr
                                                                                                            |> array_unique
                                                                                                    • ptx 15 hours ago

                                                                                                      Apparently "foo(...)" is just the PHP syntax for a function reference, according to the "first-class callable" RFC [1] linked from the article.

                                                                                                      So where in Python you would say e.g.

                                                                                                        callbacks = [f, g]
                                                                                                      
                                                                                                      PHP requires the syntax

                                                                                                        $callbacks = [f(...), g(...)];
                                                                                                      
                                                                                                      As for the purpose of the feature as a whole, although it seems like it could be replaced with function composition as mentioned at the end of the article, and the function composition could be implemented with a utility function instead of dedicated syntax, the advantage of adding these operators is apparently [2] performance (fewer function calls) and facilitating static type-checking.

                                                                                                      [1] https://wiki.php.net/rfc/first_class_callable_syntax

                                                                                                      [2] https://wiki.php.net/rfc/function-composition#why_in_the_eng...

                                                                                                      • mort96 13 hours ago

                                                                                                        Thanks, that makes sense!

                                                                                                      • moebrowne 12 hours ago

                                                                                                        There is a complementary RFC for partial function application which will allow calling a function with more than one parameter.

                                                                                                        https://wiki.php.net/rfc/partial_function_application_v2 https://wiki.php.net/rfc/pipe-operator-v3#rejected_features

                                                                                                        • tossandthrow 16 hours ago

                                                                                                          It is to interject the chained value at the right position in the function.

                                                                                                          They write that elixir has a slightly fancier version, it is likely around this, they mean (where elixir has first class support for arity > 1 functions)

                                                                                                          • mort96 16 hours ago

                                                                                                            But the example suggests that it can't interject the chained value at the right position; if that was the case, the example would've been written as `|> array_column('tags', ...)`.

                                                                                                            • wink 15 hours ago

                                                                                                              yeah that sounds weird. defaulting to the first (or only) parameter would have made sense.

                                                                                                        • abrookewood 18 hours ago

                                                                                                          I love the pipe operator - one of the things I dig about Elixir though many languages have it. It's so much easier to reason about:

                                                                                                            $result = $arr
                                                                                                              |> fn($x) => array_column($x, 'tags')
                                                                                                              |> fn($x) => array_merge(...$x)
                                                                                                              |> array_unique(...)
                                                                                                              |> array_values(...)
                                                                                                          
                                                                                                          VS array_values(array_unique(array_merge(...array_column($arr, 'tags'))));
                                                                                                          • qwertox 17 hours ago

                                                                                                            I don't see how this is hard to reason about, assuming this is the resulting code when using variables:

                                                                                                              $tags        = ...array_column($arr, 'tags');
                                                                                                              $merged_tags = array_merge($tags);
                                                                                                              $unique_tags = array_unique($merged_tags);
                                                                                                              $tag_values  = array_values($unique_tags);
                                                                                                            
                                                                                                            It also makes it easier to inspect the values after each step.
                                                                                                            • jeroenhd 16 hours ago

                                                                                                              Correctly naming things is one of the harder challenges in computer programming. Putting effort into naming intermediates that you're going to throw out is a waste. Plus, the more variables you introduce, the more likely you'll accidentally re-use a variable name somewhere down the line.

                                                                                                              With PHP allowing variable initialization in one branch but not the other, and continuing execution by default when an undeclared variable is passed, declaring more variables can lead to an annoying class of bugs that would require significant (breaking) changes to the core language to completely eliminate.

                                                                                                              • const_cast 4 hours ago

                                                                                                                The main problem with this approach, as someone who programs in PHP daily, is it pollutes the scope. That makes debugging much, much harder - you lose track of variables, and the current state of the program is complicated. IMO, if a value is a throwaway, like an intermediate, we shouldn't be able to use it. So method chaining or nesting function calls prevents them. Then, when we break after these functions, we can't see fake values. It also prevents someone in the future mutating the throwaway values. Someone could easily insert logic or a call that mutates something in the middle of this and breaks the chain.

                                                                                                                One way this is prevented in PHP is just using functions. But then you have functions just for the sake of scope, which isn't really what they're for. That introduces other annoyances.

                                                                                                                • agos 16 hours ago

                                                                                                                  I don't think inspecting this is easier than adding |> IO.inspect() to a pipe chain

                                                                                                                  • harg 16 hours ago

                                                                                                                    Or putting `|> dbg()` at the end and let it print the value at every step of the chain

                                                                                                                    • wraptile 11 hours ago

                                                                                                                      modifying code just to attach a breakpoint is kinda silly in this day and age.

                                                                                                                    • kristopolous 14 hours ago

                                                                                                                      It's easier to write, copy paste, compose and comment

                                                                                                                      • lawn 15 hours ago

                                                                                                                        Introducing a new variable every single line adda a bunch of cognitive load compared to the pipe operator.

                                                                                                                        It's much easier skim with the pipe operator and it's more robust too (for example reordering is a pain with variables, it's easy to introduce errors).

                                                                                                                        • cess11 16 hours ago

                                                                                                                          Such variable threading tends to be harder to skim through in production code, the intermediates become noise that's harder to filter out than a repeated symbol like |>.

                                                                                                                          Preferably you should also be sure that the functions are compatible with the data type going in and only rarely have to break it to dump data mid-chain. If you expect that kind of erroring it's likely a builder-chain with -> is a better alternative and do logging in the methods.

                                                                                                                          • r34 17 hours ago

                                                                                                                            Your version includes 4 variables. Pipes don't create those intermediate variables, so they are more memory efficient.

                                                                                                                            Readability is mostly matter of habit. One reads easily what he/she is used to read.

                                                                                                                            • qwertox 17 hours ago

                                                                                                                              It's true that pipes are more readable, and for many cases they will be the better option, but the example of nested functions just doesn't hold.

                                                                                                                              That's like saying someone would use this:

                                                                                                                                 $result = $arr |> fn($x) => array_column($x, 'tags') |> fn($x) => array_merge(...$x) |> array_unique(...) |> array_values(...)
                                                                                                                              
                                                                                                                              which is harder to reason about than the nested functions.

                                                                                                                                 array_values( array_unique( array_merge( ...array_column($arr, 'tags') ) ) );
                                                                                                                              
                                                                                                                              or

                                                                                                                                 array_values(
                                                                                                                                   array_unique(
                                                                                                                                     array_merge(
                                                                                                                                       ...array_column($arr, 'tags')
                                                                                                                                     )
                                                                                                                                   )
                                                                                                                                 );
                                                                                                                              • navalino 16 hours ago

                                                                                                                                It is more readable and better option — you have to parse it from the innermost function to the outermost just to understand what it's doing. With the pipe, it's more straightforward: you read it step by step — do this, then that, then the next — just like how you'd naturally read instructions.

                                                                                                                                • account42 14 hours ago

                                                                                                                                  The pipe syntax is much more readable than nested function calls when you need additional arguments for intermediate functions. With nested functions it becomes hard to see which functions those arguments belong to even if you try to help it with formatting.

                                                                                                                                  • troupo 11 hours ago

                                                                                                                                    Why didn't you format the pipes, too?

                                                                                                                                      $result = $arr
                                                                                                                                        |> fn($x) => array_column($x, 'tags')
                                                                                                                                        |> fn($x) => array_merge(...$x)
                                                                                                                                        |> array_unique(...)
                                                                                                                                        |> array_values(...)
                                                                                                                                    
                                                                                                                                    vs

                                                                                                                                       array_values(
                                                                                                                                         array_unique(
                                                                                                                                           array_merge(
                                                                                                                                             ...array_column($arr, 'tags')
                                                                                                                                           )
                                                                                                                                         )
                                                                                                                                       );
                                                                                                                                    
                                                                                                                                    With pipes you have linear sequence of data transformations. With nested function calls you have to start with innermost function and proceed all the way top the outermost layer.
                                                                                                                                  • girvo 17 hours ago

                                                                                                                                    > so they are more memory efficient

                                                                                                                                    They can be. It depends on the language, interpreter, compiler, and whether you do anything with those intermediate variables and the optimiser can get rid of them.

                                                                                                                                    • r34 17 hours ago

                                                                                                                                      I thought we are talking about PHP8.5:)

                                                                                                                                      • girvo 3 hours ago

                                                                                                                                        Ah, I thought we were talking more generally about PL constructs that let you avoid intermediate variables, apologies :)

                                                                                                                                • someothherguyy 17 hours ago

                                                                                                                                  > It's so much easier to reason about

                                                                                                                                  Is it though? I don't think so.

                                                                                                                                  • andrewflnr 17 hours ago

                                                                                                                                    It tends to work a little better in Elixir, because you very rarely have to include one-off lambdas in your pipeline. The standard library functions are designed to work with the pipeline operator, where the thing you probably want to thread through is usually the first argument.

                                                                                                                                • sandreas 19 hours ago

                                                                                                                                  While I appreciate the effort and like the approach in general, in this use case I really would prefer extensions / extension functions (like in Kotlin[1]) or an IEnumerable / iterator approach (like in C#).

                                                                                                                                    $arr = [
                                                                                                                                      new Widget(tags: ['a', 'b', 'c']),
                                                                                                                                      new Widget(tags: ['c', 'd', 'e']),
                                                                                                                                      new Widget(tags: ['x', 'y', 'a']),
                                                                                                                                    ];
                                                                                                                                    
                                                                                                                                    $result = $arr
                                                                                                                                        |> fn($x) => array_column($x, 'tags') // Gets an array of arrays
                                                                                                                                        |> fn($x) => array_merge(...$x)       // Flatten into one big array
                                                                                                                                        |> array_unique(...)                  // Remove duplicates
                                                                                                                                        |> array_values(...)                  // Reindex the array.
                                                                                                                                    ;
                                                                                                                                  
                                                                                                                                  feels much more complex than writing

                                                                                                                                    $result = $arr->column('tags')->flatten()->unique()->values()
                                                                                                                                  
                                                                                                                                  having array extension methods for column, flatten, unique and values.

                                                                                                                                  1: https://kotlinlang.org/docs/extensions.html#extension-functi...

                                                                                                                                  • hn8726 15 hours ago

                                                                                                                                    Kotlin also has extensions function `let` (and a couple of variants) which let you chain arbitrary methods:

                                                                                                                                    ``` val arr = ... val result = arr .let { column(it, "tags") .let { merge(it) } .let { unique(it) } .let { values(it) } ```

                                                                                                                                    You add function references for single-argument functions too:

                                                                                                                                    ``` arr.let(::unique) // or (List<>::unique), depends on the function ```

                                                                                                                                    all without adding a special language construct.

                                                                                                                                    • Contortion 12 hours ago

                                                                                                                                      Basically what Collections do in Laravel.

                                                                                                                                      • sandreas 12 hours ago

                                                                                                                                        Exactly... similar in Symfony.

                                                                                                                                        While converting arrays to collection-object is a suitable option that does work, it would feel much more "native", if there were extension methods for Iterable / Traversable.

                                                                                                                                      • cess11 18 hours ago

                                                                                                                                        PHP has traits, just invent that API, put it in a trait and add it to your data classes.

                                                                                                                                        • sandreas 12 hours ago

                                                                                                                                          Well, while traits might be a workaround for certain use cases, simple arrays with scalar data types could not be extended via traits.

                                                                                                                                          While I know that there are Collection classes in Symfony, Laravel, etc., I'm not a huge fan of wrapping a PHP array with a class to get method chaining, even with generators.

                                                                                                                                            $sum = [1, 2, 3]->filter(fn($x) => $x%2!= 0)->concat([5,7])->sum();
                                                                                                                                          
                                                                                                                                          cannot be solved with traits. Additionally, I think traits should be used very carefully and they do not have this many use cases that aren't a code smell to me.
                                                                                                                                          • stefanfisk 14 hours ago

                                                                                                                                            How would that work if a library supplies a function that takes a string and returns an array? I can’t make it use my array class.

                                                                                                                                            • cess11 13 hours ago

                                                                                                                                              Could you give a realistic example?

                                                                                                                                              The PHP pipes as described in the articles about it will require a bunch of wrapping anyway so you could just do that. There are several alternatives, from a function or method that just converts from raw array to class, to abstractions involving stuff like __invoke, __call, dispatchers and such.

                                                                                                                                              Also the expectation to not have to put facades on libraries is a bit suspicious, in my experience it is very common. I find it unlikely you actually want to use raw arrays instead of leveraging type guards in your code.

                                                                                                                                              • stefanfisk 12 hours ago

                                                                                                                                                If I use Laravel’s Str in an app where both myself and a third party library want to add a chainable method, how do I make the API make sense? We can’t both subclass Str. The only option I see is Macroable and that’s a rabbit hole I’d rather avoid.

                                                                                                                                          • troupo 19 hours ago

                                                                                                                                            The advantage is that pipes don't care about the type of the return value.

                                                                                                                                            Let's say you add a reduce in the middle of that chain. With extension methods that would be the last one you call in the chain. With pipes you'd just pipe the result into the next function

                                                                                                                                            • sandreas 12 hours ago

                                                                                                                                              Yeah, I agree. That's an advantage of pipes - although much harder to read and write than chained methods in my opinion.

                                                                                                                                              The use-case in the article could still be solved easier with extension methods in my opinion :-)

                                                                                                                                              • troupo 12 hours ago

                                                                                                                                                Yeah, the examples should also show that you can use arbitrary functions, not just library functions. E.g. your own business logic, validation etc.

                                                                                                                                          • gbalduzzi 19 hours ago

                                                                                                                                            I like it.

                                                                                                                                            I really believe the thing PHP needs the most is a rework of string / array functions to make them more consistent and chain able. Now they are at least chainable.

                                                                                                                                            I'm not a fan of the ... syntax though, especially when mixed in the same chain with the spread operator

                                                                                                                                            • account42 15 hours ago

                                                                                                                                              The syntax could be improved by allowing you to omit the (...) part entirely for single argument functions and using currying for functions that need additional arguments. So you would end up with something like:

                                                                                                                                                $result = $arr
                                                                                                                                                    |> select_column('tags')         // Gets an array of arrays
                                                                                                                                                    |> fn($x) => array_merge(...$x)  // Flatten into one big array
                                                                                                                                                    |> array_unique                  // Remove duplicates
                                                                                                                                                    |> array_value                   // Reindex the array.
                                                                                                                                              • noduerme 18 hours ago

                                                                                                                                                Agree, the ... syntax feels confusing when each fn($x) in the example uses $x as the name of its argument.

                                                                                                                                                My initial instinct would be to write like this:

                                                                                                                                                `$result = $arr

                                                                                                                                                    |> fn($arr) => array_column($arr, 'tags') // Gets an array of arrays
                                                                                                                                                
                                                                                                                                                    |> fn($cols) => array_merge(...$cols)`
                                                                                                                                                
                                                                                                                                                Which makes me wonder how this handles scope. I'd imagine the interior of some chained function can't reference the input $arr, right? Does it allow pass by reference?
                                                                                                                                                • Einenlum 18 hours ago

                                                                                                                                                  You can write it this way. The parameter name is arbitrary. And no, to my knowledge you can't access the var from the previous scope

                                                                                                                                                  • cess11 16 hours ago

                                                                                                                                                    You can do

                                                                                                                                                         function ($parameter) use ($data) { ... }
                                                                                                                                                    
                                                                                                                                                    to capture stuff from the local environment.

                                                                                                                                                    Edit: And you can pass by reference:

                                                                                                                                                       > $stuff = [1]
                                                                                                                                                       = [
                                                                                                                                                           1,
                                                                                                                                                         ]
                                                                                                                                                    
                                                                                                                                                       > $fn = function ($par) use (&$stuff) { $stuff[] = $par; }
                                                                                                                                                       = Closure($par) {#3980 …2}
                                                                                                                                                    
                                                                                                                                                       > $fn(2)
                                                                                                                                                       = null
                                                                                                                                                    
                                                                                                                                                       > $stuff
                                                                                                                                                       = [
                                                                                                                                                           1,
                                                                                                                                                           2,
                                                                                                                                                         ]
                                                                                                                                                    
                                                                                                                                                    
                                                                                                                                                    Never done it in practice, though, not sure if there are any footguns besides the obvious hazards in remote mutation.
                                                                                                                                                  • colecut 18 hours ago

                                                                                                                                                    PHP string / array functions are consistent.

                                                                                                                                                    string functions use (haystack, needle) and array functions use (needle, haystack)

                                                                                                                                                    because that's the way the underlying C libraries also worked

                                                                                                                                                    • Einenlum 18 hours ago

                                                                                                                                                      They're not though.

                                                                                                                                                      array_filter takes (arr, callback)

                                                                                                                                                      https://www.php.net/manual/en/function.array-filter.php

                                                                                                                                                      array_map takes (callback, arr)

                                                                                                                                                      https://www.php.net/manual/en/function.array-map.php

                                                                                                                                                      • goykasi 9 hours ago

                                                                                                                                                        array_map is variadic. It is actually (callback, ...arr)

                                                                                                                                                        One function works against a single element, whereas the other works against multiple. In that case, the parameter order is more meaningful. You can use array_walk if you want (arr, callback), but that only works against a single array -- similarly to array_filter.

                                                                                                                                                        • exasperaited 17 hours ago

                                                                                                                                                          This is "english-sentence-order-consistent", as it goes.

                                                                                                                                                          Array filter is "filter this array with this function".

                                                                                                                                                          Array map is "map this function over this array".

                                                                                                                                                          But I agree any replacement function should be consistent with Haskell.

                                                                                                                                                          • eurleif 17 hours ago

                                                                                                                                                            One can construct English sentences in the opposite order. There is no singular "English sentence order".

                                                                                                                                                            "Filter for this function in this array"

                                                                                                                                                            "Map over this array with this function"

                                                                                                                                                            • goykasi 10 hours ago

                                                                                                                                                              But thats not correct. array_map is variadic. So it should actually be "Map over these arrays with this function."

                                                                                                                                                              When you use the correct verbiage, the parameter order makes sense.

                                                                                                                                                              • exasperaited 16 hours ago

                                                                                                                                                                Right, but these are both more unwieldy.

                                                                                                                                                                One filters something with something else, in the real world. Filter water with a mesh etc.

                                                                                                                                                                And (in maths, at least) one maps something onto something else. (And less commonly one maps an area onto paper etc.)

                                                                                                                                                                Just because you can make your two sentences does not make them natural word order.

                                                                                                                                                                • quietbritishjim 16 hours ago

                                                                                                                                                                  > And (in maths, at least) one maps something onto something else.

                                                                                                                                                                  Yes, but that's the opposite of what you said earlier. You might map x onto 2*x, for example. Or, if you're talking about a collection, you might map the integers 0..10 on to double their value. Data first, then the way you're manipulating it. I'm a mathematician and this is what makes sense to me.

                                                                                                                                                                  I would only say "map this function..." if the function itself is being manipulated somehow (mapped onto some other value).

                                                                                                                                                                  • hnlmorg 16 hours ago

                                                                                                                                                                    When you consider that PHP is used by hundreds of thousands of non-native English speakers, I don’t really think you can make a legitimate claim that “English sentence order” trumps “consistent argument ordering”.

                                                                                                                                                                    There’s enough viral videos online of how even neighbouring European counties order common sentences differently. Even little things like reading the time (half past the previous hour vs half to the next hour) and counting is written differently in different languages.

                                                                                                                                                                    So modelling the order of parameters based on English vernacular doesn’t make a whole lot of sense for programming languages used by programmers of all nationalities.

                                                                                                                                                                    • exasperaited 15 hours ago

                                                                                                                                                                      > When you consider that PHP is used by hundreds of thousands of non-native English speakers, I don’t really think you can make a legitimate claim that “English sentence order” trumps “consistent argument ordering”.

                                                                                                                                                                      Well that’s good, because I didn’t.

                                                                                                                                                            • Y-bar 16 hours ago

                                                                                                                                                              > because that's the way the underlying C libraries also worked

                                                                                                                                                              I feel like this is a weak defence of the internally inconsistent behaviour. As someone who has been programming with PHP for over twenty years now, most of them professionally, I still cannot remember the needle/haystack order in these functions, I thank intellisense for keeping me sane here.

                                                                                                                                                              As evident with this pipe operator, or with for example Attributes, PHP does not need to religiously follow the C way of doing things, so why not improve it instead of dismissing it as "it is the way it is because that is the way it was"?

                                                                                                                                                              • chuckadams 11 hours ago

                                                                                                                                                                It's not so much a defense as it is an explanation of the historical origins. Even the creator of the language doesn't defend the inconsistencies and admits that they were a mistake. PHP also takes backward compatibility pretty seriously and doesn't rearrange things for consistency's sake alone.

                                                                                                                                                              • account42 15 hours ago

                                                                                                                                                                So they are consistent because they are consistently inconsistent??

                                                                                                                                                                There isn't a good reason for PHP to have inherited C's issues here.

                                                                                                                                                                • goykasi 12 hours ago

                                                                                                                                                                  In the early days of PHP, it relied heavily on wrapping the underlying C libraries and preserving their naming conventions.

                                                                                                                                                                  https://news-web.php.net/php.internals/70950

                                                                                                                                                                  • gbalduzzi 11 hours ago

                                                                                                                                                                    And that was fine in the early days, absolutely.

                                                                                                                                                                    We are not in the early days though, and in many other aspects PHP evolved greatly.

                                                                                                                                                                    • goykasi 10 hours ago

                                                                                                                                                                      What are the benefits? Code completion, AI agents, etc will handle it for you. No one's life is falling apart because the param ordering is more similar to C than a blog article complaining about it decade ago. Php devs have had up 30 years to learn the difference. Are C devs complaining about this?

                                                                                                                                                                      If we want to change the param order of str/array functions for php, I think we should start with fixing the C libraries. That seems like a better starting point. The impact will certainly be more beneficial to even more developers than just php.

                                                                                                                                                                      • gbalduzzi 8 hours ago

                                                                                                                                                                        Because it would be more predictable, easier to memorize, less verbose, easier to use for developers coming from other modern languages and more comfortable to work with.

                                                                                                                                                                        The fact that they are chaotic since 30 years ago is not a valid reason for keeping them chaotic right now.

                                                                                                                                                                        Also, I'm not even arguing they should change the existing functions, that would break all existing code for almost no reason.

                                                                                                                                                                        I think they should "simply" support methods on primitives, and implement the main ones in a chainable way:

                                                                                                                                                                        "test string"->trim()->upper()->limit(100);

                                                                                                                                                                        [0,1,2]->filter(fn ($n) => $n % 2 === 0)->map(fn($n) => $n * 2);

                                                                                                                                                                        I would love this so much

                                                                                                                                                                • gbalduzzi 11 hours ago

                                                                                                                                                                  `strlen`, `strncmp` and `strtolower` but `str_split` and `str_contains`.

                                                                                                                                                                  How it that consistent?

                                                                                                                                                              • defraudbah 16 hours ago

                                                                                                                                                                PHP is that weird beast that no one wants to praise and yet it works tremendously well for those who manage to tame it.

                                                                                                                                                                I would likely never touch it as there are too many languages to use and what I know is more than enough to do my job, but I am super excited to see languages like PHP that aren't mainstream in my bubble to keep evolving

                                                                                                                                                                • nolok 15 hours ago

                                                                                                                                                                  I'm not tempting you do to it or anything, but I want to say given your point of view, if one day you need a crude+ app and try to do it using laravel, you might be really surprised by what modern php actually is.

                                                                                                                                                                  There was a point were I thought the language and it ecosystem was going down the drain but then they recovered and modern php is 90% what do you want to do and don't worry about the how, it's easy.

                                                                                                                                                                  I don't use it much anymore, but every time I do all I see are possibilities.

                                                                                                                                                                  • defraudbah 14 hours ago

                                                                                                                                                                    what about deployment? I assume I need to scp files like Python or keep everything in a single giant PHP file? is that an option?

                                                                                                                                                                    • nolok 14 hours ago

                                                                                                                                                                      Deployment these days is essentially git pull && composer update

                                                                                                                                                                      Of course not if you use vm or serverless or whatever like this, but for a basic here is my crude app, that's what you do.

                                                                                                                                                                      Or if you want to go old school sure, just scp that directory, it still works like it did 30 years ago.

                                                                                                                                                                      • defraudbah 5 hours ago

                                                                                                                                                                        awesome, thank you

                                                                                                                                                                      • claar 12 hours ago

                                                                                                                                                                        Laravel Forge handles auto-deployment on push to master. Or if you want production zero downtime deployments, use Laravel Envoyer.

                                                                                                                                                                    • cess11 12 hours ago

                                                                                                                                                                      I'll gladly praise it. It's a very practical language with good tooling and excellent amounts of libraries and scripts available. Performance is decent, development speed for tools, toys and prototypes is extreme.

                                                                                                                                                                      The standard library has a lot of good stuff for calling API:s, handling JSON, shelling out, string juggling and HTML publishing on a socket. In every typical install you also have common database interfaces. I've done so much problem solving at breathtaking speed in single file PHP scripts and PsySH over the years.

                                                                                                                                                                      The threading story isn't or wasn't very good so typically I've done logic in PHP and then driven it from something like a Scheme, Picolisp or Elixir when I've needed it.

                                                                                                                                                                    • phplovesong 19 hours ago

                                                                                                                                                                      The stdlib is so inconsistent this will be a nightmare.

                                                                                                                                                                      Optionally with a better language you know what order params as passed (array_map / array_filter), but in PHP its an coin toss.

                                                                                                                                                                      This feels very bolted on and not suited for the stdlib at all.

                                                                                                                                                                      PHP devs should instead FIRST focus on full unicode support (no, the mb_real_uppercase wont do), and only then focus on a new namespaced stdlib with better design.

                                                                                                                                                                      • foul 17 hours ago

                                                                                                                                                                        >The stdlib is so inconsistent this will be a nightmare.

                                                                                                                                                                        I think that callables will end with being useless in this context and everyone will pipe closures to put that $x wherever the stdlib imposes.

                                                                                                                                                                        • Einenlum 18 hours ago

                                                                                                                                                                          This.

                                                                                                                                                                          We definitely need a better stdlib with appropriate data structures

                                                                                                                                                                          • allan_s 15 hours ago

                                                                                                                                                                            it's a chicken and the egg problem

                                                                                                                                                                            I think initiative like this drive a need for a more consistent, and even if slow, PHP has been deprecated/reworking its stdlib so I'm hopeful on this.

                                                                                                                                                                          • goykasi 9 hours ago

                                                                                                                                                                            Is array_map and array_filter the common argument? One works against a single element, whereas the other works against multiple. What would you suggest a better param order? Do you know that array_walk exists?

                                                                                                                                                                          • librasteve 19 hours ago

                                                                                                                                                                            raku has had feed operators like this since its inception

                                                                                                                                                                              # pipeline functional style
                                                                                                                                                                              (1..5)
                                                                                                                                                                                ==> map { $_ * 2 }
                                                                                                                                                                                ==> grep { $_ > 5 }
                                                                                                                                                                                ==> say();              # (6 8 10)
                                                                                                                                                                            
                                                                                                                                                                              # method chain OO style
                                                                                                                                                                              (1..5)
                                                                                                                                                                                .map( * * 2)
                                                                                                                                                                                .grep( * > 5)
                                                                                                                                                                                .say;                   # (6 8 10)
                                                                                                                                                                            
                                                                                                                                                                            uses ==> and <== for leftward

                                                                                                                                                                            true it is syntax sugar, but often the pipe feed is quite useful to make chaining very obvious

                                                                                                                                                                            https://docs.raku.org/language/operators#infix_==%3E

                                                                                                                                                                            • LorenDB 13 hours ago

                                                                                                                                                                              Reminds me of D's Uniform Function Call Syntax[0], which allows you to rewrite bar(foo(sort(myArray))) as myArray.sort().foo().bar(). The difference is that D allows extra function arguments, keeping the passed-in value as the first argument. So you could have myArray.sort().writeln("extra text"), for example.

                                                                                                                                                                              [0]: https://tour.dlang.org/tour/en/gems/uniform-function-call-sy...

                                                                                                                                                                              • mappu 17 hours ago

                                                                                                                                                                                Every single one of those steps buffers into a temporary variable - this isn't efficient like a bash pipe.

                                                                                                                                                                                • quietbritishjim 17 hours ago

                                                                                                                                                                                  Genuine question from a non-PHP user:

                                                                                                                                                                                  Does PHP support iterator-like objects? Like Python I mean, where mydict.values() produces values on demand, not immediately realised as a list. Or are all steps necessarily guaranteed to be fully realised into a complete list?

                                                                                                                                                                                  • severak_cz 17 hours ago
                                                                                                                                                                                    • quietbritishjim 13 hours ago

                                                                                                                                                                                      Interesting, but I suppose I was particularly interested if that's what's actually happening with the transformations in the example in the article. Are those making use of this protocol? The comment I originally replied to seems to imply they aren't.

                                                                                                                                                                                    • Timwi 16 hours ago

                                                                                                                                                                                      The section where the article mentions function composition implies that it doesn't. The article says that compositing the functions before passing them into map would be an optimization. I take that to mean that without the composition, each map fully processes an array passed to it from the previous map, and the first map fully reads the whole file in the example. If it were iterable, the function composition would make no difference compared to a pipeline of multiple maps.

                                                                                                                                                                                      Meanwhile, I'm confused as to why it sometimes says “map” and sometimes “array_map”. The latter is what I'm familiar with and I know that it operates on a whole array with no lazy evaluation. If “map” isn't just a shorthand and actually creates a lazy-evaluated iterable, then I'm confused as to why the function composition would make any difference.

                                                                                                                                                                                      • throw_m239339 16 hours ago

                                                                                                                                                                                        PHP does have generators and iterators yes, although I personally rarely use them directly.

                                                                                                                                                                                      • troupo 11 hours ago

                                                                                                                                                                                        That's how function calls work in every language. Unless it's streams.

                                                                                                                                                                                      • habibur 18 hours ago

                                                                                                                                                                                        I tried to emulate something similar with PHP at one point. But the problem with PHP was parameter order. Especially in functions like array_key_exists() the array element is the 2nd parameter, while pipe operator expects the object to work on be the 1st parameter, the array in these cases.

                                                                                                                                                                                        I believe they have solved this problem by now. Though no idea how.

                                                                                                                                                                                        • kijin 18 hours ago

                                                                                                                                                                                          The usual solution is to wrap it with a closure.

                                                                                                                                                                                              function($x) { return array_key_exists('needle', $x); }
                                                                                                                                                                                          
                                                                                                                                                                                          Or using the arrow function syntax:

                                                                                                                                                                                              fn($x) => array_key_exists('needle', $x)
                                                                                                                                                                                          
                                                                                                                                                                                          The same trick also helps when you need to use functions with mandatory extra parameters, functions with pass-by-value parameters, etc.
                                                                                                                                                                                      • adius 9 hours ago

                                                                                                                                                                                        PHP getting a pipe operator with ways to implement a Maybe Monad was definitely not on my 2025 bingo card.

                                                                                                                                                                                        But any changes making mainstream languages more functional are highly welcome! It’s just more ergonomic than imperative code.

                                                                                                                                                                                        • rogue7 15 hours ago

                                                                                                                                                                                          This looks neat. However since I read about Koka's dot selection [0], I keep thinking that this is an even neater syntax:

                                                                                                                                                                                          fun showit( s : string )

                                                                                                                                                                                            s.encode(3).count.println
                                                                                                                                                                                          
                                                                                                                                                                                          However, this is of course impossible to implement in most languages as the dot is already meaningful for something else.

                                                                                                                                                                                          [0] https://koka-lang.github.io/koka/doc/book.html#sec-dot

                                                                                                                                                                                          • btbytes 12 hours ago

                                                                                                                                                                                            It is called Uniform [Function] Call Syntax.

                                                                                                                                                                                            D has had this for decade(s): https://tour.dlang.org/tour/en/gems/uniform-function-call-sy...

                                                                                                                                                                                            Nim too has it: https://nim-by-example.github.io/oop/

                                                                                                                                                                                            • jprafael 15 hours ago

                                                                                                                                                                                              That syntax is very clean when it works. I think however the limitation of not being able to pipe arguments into 2nd, 3rd, ..., positions and keyword arguments, or variadic explosion like the syntax showcased in the article makes it less powerful.

                                                                                                                                                                                              Are there other syntax helpers in that language to overcome this?

                                                                                                                                                                                              • account42 14 hours ago

                                                                                                                                                                                                It still makes sense to have a clean syntax for the simple case. You can use currying (with or without first class language support) to handle more complex cases or just fall back to good old function composition or even loops.

                                                                                                                                                                                              • throw-the-towel 15 hours ago

                                                                                                                                                                                                I think this is called uniform function call syntax.

                                                                                                                                                                                              • zelphirkalt 16 hours ago

                                                                                                                                                                                                Hm. Looks like PHP actually got a modern feature there, and it is looking decent, not like the usual new PHP feature, that just looks worse than in other languages, where it has been standard. Consider me surprised, that they seem to have done a good job on this one. And they even dodged the bullet with making the right side callables, which avoids the trap of inventing new types of expressions and then not covering all cases.

                                                                                                                                                                                                • flufluflufluffy 5 hours ago

                                                                                                                                                                                                  It’s cool. Personally I probably won’t be using it though. I think a few temp variables or dedicated functions to do some computation that takes more than 2 or 3 iterated operations is better for readability and maintainability.

                                                                                                                                                                                                  • penguin_booze 13 hours ago

                                                                                                                                                                                                    I don't imagine it's widely known (which I completely understand): vimscript has an arrow operator with similar piping effect, a la foo->bar(baz)->qux() . See the doc: https://vimhelp.org/eval.txt.html#method.

                                                                                                                                                                                                    • ds_ 15 hours ago

                                                                                                                                                                                                      One of the many joys of working with Clojure https://clojure.org/guides/threading_macros

                                                                                                                                                                                                      • chuck8088 12 hours ago

                                                                                                                                                                                                        This article makes a great case WHY the pipe operator is useful, but why didn't they just rewrite those functions to support method chaining? ` $profit = [1, 4, 5] .loadSeveral() .filter(isOnSale()) .map(sellWidget()) .array_sum(); ` this has the side benefit of 'looking normal'

                                                                                                                                                                                                        • wsatb 12 hours ago

                                                                                                                                                                                                          Backwards compatibility. The language has done a pretty amazing job at adding features over the last 10 years without really breaking a lot of old code. I believe PHP still runs about 75% of the internet, so that's pretty huge.

                                                                                                                                                                                                          • moebrowne 12 hours ago

                                                                                                                                                                                                            The Python 2 to 3 upgrade is a example of how important backwards compatibility is

                                                                                                                                                                                                          • troupo 11 hours ago

                                                                                                                                                                                                            Because pipes work on all functions, not just object methods. So your business logic, validations etc. don't have to be methods of the built-in objects.

                                                                                                                                                                                                            And there's nothing abnormal about pipes

                                                                                                                                                                                                          • elric 13 hours ago

                                                                                                                                                                                                            Makes for a fun programming paradigm, similar to Java's streams-with-lambdas. Great for readability. Not too fond of the |> operator though, requires 4 different keypresses on my keyboard layout, not terribly ergonomic. But I understand that options were limited and it is sort of clear.

                                                                                                                                                                                                            • elif 11 hours ago

                                                                                                                                                                                                              I used php professionally for a decade and I still don't get why in the year 2025 we need to reinvent syntax that is virtually standard in every language

                                                                                                                                                                                                              • mhh__ 14 hours ago

                                                                                                                                                                                                                Every language should have this.

                                                                                                                                                                                                                Forget about transforming existing code, it makes new code much more reasonable (the urge to come up with OOPslop is much weaker when functions are trivial) — they're programming languages for a reason.

                                                                                                                                                                                                                • pknerd 16 hours ago

                                                                                                                                                                                                                  Am I the only one who found it ugly?

                                                                                                                                                                                                                  • dagi3d 10 hours ago

                                                                                                                                                                                                                    I wish they reconsider it again i ruby

                                                                                                                                                                                                                    • dev_l1x_be 16 hours ago

                                                                                                                                                                                                                      Rust is next? Jokes aside, pipe operators in programming languages have a interesting side effect of enabling railway oriented programming that I miss the most when not working in F#.

                                                                                                                                                                                                                      • realharo 11 hours ago

                                                                                                                                                                                                                        There is the `tap` crate (https://crates.io/crates/tap) which adds `tap`, `pipe` and their variants to everything.

                                                                                                                                                                                                                        • simonask 14 hours ago

                                                                                                                                                                                                                          The way function/trait resolution works in Rust, it's actually already quite idiomatic to code in this style (just using the dot operator). The standard library Iterator is a great example of this. :-)

                                                                                                                                                                                                                          I don't think there's any significant push for an even terser syntax at the moment.

                                                                                                                                                                                                                        • mg 13 hours ago

                                                                                                                                                                                                                          I'm confused about the rationale behind:

                                                                                                                                                                                                                              |> fn($x) => array_column($x, 'tags')
                                                                                                                                                                                                                          
                                                                                                                                                                                                                          Why is that inlined function necessary? Why not just

                                                                                                                                                                                                                              |> array_column(..., 'tags')
                                                                                                                                                                                                                          
                                                                                                                                                                                                                          ?

                                                                                                                                                                                                                          I mean, I understand that it is because the way this operator was designed. But why?

                                                                                                                                                                                                                        • cess11 18 hours ago

                                                                                                                                                                                                                          "A major limitation of the pipe operator is that all the callables in the chain must accept only one required parameter.

                                                                                                                                                                                                                          For built-in functions, if the function does not accept any parameters, it cannot be used in a chain. For user-land PHP functions, passing a parameter to a function that does not accept any parameters does not cause an error, and it is silently ignored.

                                                                                                                                                                                                                          With the pipe operator, the return value of the previous expression or the callable is always passed as the first parameter to the next callable. It is not possible to change the position of the parameter."

                                                                                                                                                                                                                          https://php.watch/versions/8.5/pipe-operator

                                                                                                                                                                                                                          In the light of these limitations I would not call the Elixir implementation "slightly fancier".

                                                                                                                                                                                                                          I'm not so sure I'll be upgrading my local PHP version just for this but it's nice that they are adding it, I'm sure there is a lot of library code that would look much better if rewritten into this style.

                                                                                                                                                                                                                          • ChocolateGod 18 hours ago

                                                                                                                                                                                                                            Why not just make types psuedo-objects?

                                                                                                                                                                                                                            $myString.trim().replace("w", "h");

                                                                                                                                                                                                                            Which has the advantage of also offering a clean alternative to the fragmented stdlib.

                                                                                                                                                                                                                            • williamdclt 15 hours ago

                                                                                                                                                                                                                              > Why not just make types psuedo-objects?

                                                                                                                                                                                                                              With this sort of "just" I could build Paris out of matchsticks

                                                                                                                                                                                                                              • reddalo 18 hours ago

                                                                                                                                                                                                                                I agree. But in PHP it would probably be like this:

                                                                                                                                                                                                                                $myString->trim()->replace("w", "h");

                                                                                                                                                                                                                                • troupo 18 hours ago

                                                                                                                                                                                                                                  Because pipes don't care about the type your function returns. And you don't need hundreds of methods on each type just in case. You just pipe the result of the previous function to the next one.

                                                                                                                                                                                                                                  And those functions can be business logic, or validation, or... Not just object methods

                                                                                                                                                                                                                                • account42 14 hours ago

                                                                                                                                                                                                                                  Because duplicating the stdlib is probably not a good idea.

                                                                                                                                                                                                                                • Mystery-Machine 11 hours ago

                                                                                                                                                                                                                                  PHP:

                                                                                                                                                                                                                                          $result = $arr
                                                                                                                                                                                                                                              |> fn($x) => array_column($x, 'tags') // Gets an array of arrays
                                                                                                                                                                                                                                              |> fn($x) => array_merge(...$x)       // Flatten into one big array
                                                                                                                                                                                                                                              |> array_unique(...)                  // Remove duplicates
                                                                                                                                                                                                                                              |> array_values(...)                  // Reindex the array.
                                                                                                                                                                                                                                          ; // <- wtf
                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                  Ruby:

                                                                                                                                                                                                                                      result = arr.uniq.flatten.map(&:tags)
                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                  I understand this is not pipe operator, but just look at that character difference across these two languages.

                                                                                                                                                                                                                                  // <- wtf

                                                                                                                                                                                                                                  This comment was my $0.02.

                                                                                                                                                                                                                                  • Alifatisk 10 hours ago

                                                                                                                                                                                                                                    Can't the pipe operator be easily mimicked in Ruby thanks to its flexibility?

                                                                                                                                                                                                                                    I'm thinking of something like this:

                                                                                                                                                                                                                                        class Object
                                                                                                                                                                                                                                          def |>(fn)
                                                                                                                                                                                                                                            fn.call(self)
                                                                                                                                                                                                                                          end
                                                                                                                                                                                                                                        end
                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                    which then can be in the following way:

                                                                                                                                                                                                                                        result = arr
                                                                                                                                                                                                                                          |> ->(a) { a.uniq }
                                                                                                                                                                                                                                          |> ->(a) { a.flatten }
                                                                                                                                                                                                                                          |> ->(a) { a.map(&:tags) }
                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                    Or if we just created an alias for then #then method:

                                                                                                                                                                                                                                        class Object
                                                                                                                                                                                                                                          alias_method :|>, :then
                                                                                                                                                                                                                                        end
                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                    then it can be used like in this way:

                                                                                                                                                                                                                                        arr
                                                                                                                                                                                                                                          |> :uniq.to_proc
                                                                                                                                                                                                                                          |> :flatten.to_proc
                                                                                                                                                                                                                                          |> ->(a) { a.map(&:tags) }
                                                                                                                                                                                                                                    • rafark 10 hours ago

                                                                                                                                                                                                                                      The great thing about this pipe operator is that it accepts any callable expression. I’m writing a library to make these array and string functions more expressive.

                                                                                                                                                                                                                                      For example, in php 8.5 you’ll be able to do:

                                                                                                                                                                                                                                      [1,1,2,3,2] |> unique

                                                                                                                                                                                                                                      And then define “unique” as a constant with a callback assigned to it, roughly like:

                                                                                                                                                                                                                                      const unique = static fn(array $array) : array => array_unique($array);

                                                                                                                                                                                                                                      Much better.

                                                                                                                                                                                                                                    • daneel_w 8 hours ago

                                                                                                                                                                                                                                      Putting the delimiter on a line of its own is a syntactical trick that helps bringing small additions down to a neater 1-line diff instead of a 2-line diff. You've probably run into it many times before in other contexts without thinking of it. Arrays/hashes, quoted multi-line strings etc.

                                                                                                                                                                                                                                      • moebrowne 10 hours ago

                                                                                                                                                                                                                                        The trailing semi-colon on a new line helps prevent Git conflicts and gives cleaner diffs.

                                                                                                                                                                                                                                        It's the same reason PHP allows trailing commas in all lists.

                                                                                                                                                                                                                                      • JaggerJo 18 hours ago

                                                                                                                                                                                                                                        Thanks F#!

                                                                                                                                                                                                                                        • jcmontx 12 hours ago

                                                                                                                                                                                                                                          Very nice, great F# feature, hope to see it in many other languages!

                                                                                                                                                                                                                                          • BiteCode_dev 16 hours ago

                                                                                                                                                                                                                                            It's lovely to see how PHP keeps growing. It's far from what it was when I used to code with it in V3. I really thought it would be lost in its bad design, but the core devs kept at it, and it is, indeed, a pretty decent language now.

                                                                                                                                                                                                                                            • cpursley 16 hours ago

                                                                                                                                                                                                                                              Your move, JavaScript.

                                                                                                                                                                                                                                              • scop 11 hours ago

                                                                                                                                                                                                                                                This is great! Hat tip to PHP. I first came across pipes in Elixir and have ever since missed it in every other language. Two observations:

                                                                                                                                                                                                                                                - pipes make you realize how much song and dance you do for something quite simple. Nesting, interstitial variables, etc all obscuring what is in effect and very orderly set of operations.

                                                                                                                                                                                                                                                - pipes really do have to be a first class operator of the language. I’ve tried using some pipe-like syntactic sugar in languages without pipes and while it does the job, a lot of elegance and simplicity is lost. It feels like you are using a roundabout thing and thus, in the end, doesn’t really achieve the same level of simplicity. Things can get very deranged if you are using a language in a way it wasn’t designed for and even though I love pipes I’ve seen “fake pipes” make things more complicated in languages without them.

                                                                                                                                                                                                                                                • someothherguyy 17 hours ago

                                                                                                                                                                                                                                                  composition would be much nicer than this, maybe soon

                                                                                                                                                                                                                                                • keyle 19 hours ago

                                                                                                                                                                                                                                                  C'mon Dart! Follow up please. Go is a lost cause...

                                                                                                                                                                                                                                                  • tayo42 19 hours ago

                                                                                                                                                                                                                                                    I feel like a kindergartener writing go. I wish another language got popular in the space go is used for.

                                                                                                                                                                                                                                                    • jillesvangurp 16 hours ago

                                                                                                                                                                                                                                                      Kotlin is shaping up slowly. It's kind of there with a native compiler that is getting better with each release and decent multiplatform libraries. It's a bit weak with support for native libraries and posix stuff. But that's a fixable issue; it just needs more people working on that.

                                                                                                                                                                                                                                                      For example ktor (one of the server frameworks) can actually work with Kotlin native but it's not that well supported. This is not using Graal or any of the JVM stuff at runtime (which of course is also a viable path but a lot more heavyweight). With Kotlin native, the Kotlin compiler compiles directly to native code and uses multiplatform libraries with native implementations. There is no Java standard library and none of the jvm libraries are used.

                                                                                                                                                                                                                                                      The same compiler is also powering IOS native with Compose multiplatform. On IOS libraries are a bit more comprehensive and it's starting to become a proper alternative to things like flutter and react native. It also has pretty decent objectc and swift integration (both ways) that they are currently working on improving.

                                                                                                                                                                                                                                                      In any case, it's pretty easy to write a command line thingy in Kotlin. Use Klikt or similar for command line argument parsing.

                                                                                                                                                                                                                                                      Jetbrains seems to be neglecting this a bit for some reason. It's a bit of a blind spot in my view. Their wasm support has similar issues. Works great in browsers (and supported with compose as well) but it's not a really obvious choice for serverless stuff or edge computing just yet; mainly because of the library support.

                                                                                                                                                                                                                                                      Swift is a bit more obvious but has the issue that Apple seems to think of it as a library for promoting vendor lockin on their OS rather than as a general purpose language. Both have quite a bit of potential to compete with Go for system programming tasks.

                                                                                                                                                                                                                                                  • ossusermivami 18 hours ago

                                                                                                                                                                                                                                                    i wish python had something liek that to be honest

                                                                                                                                                                                                                                                    • kh_hk 14 hours ago

                                                                                                                                                                                                                                                      one can dream but i wouldn't keep high hopes. I feel functional patterns are left as second class citizens in python.

                                                                                                                                                                                                                                                    • jadbox 11 hours ago

                                                                                                                                                                                                                                                      Now if only JS or Typescript can jump on this ship!

                                                                                                                                                                                                                                                      • major505 13 hours ago

                                                                                                                                                                                                                                                        So php now can do clojure like programing?

                                                                                                                                                                                                                                                        • DataDaemon 18 hours ago

                                                                                                                                                                                                                                                          This will be the year of PHP. People are tired of JS.

                                                                                                                                                                                                                                                          • Timwi 16 hours ago

                                                                                                                                                                                                                                                            I am indeed tired of JS; however, I'm not a fan of PHP either. I like the new pipe syntax as a concept, but when added to an already uncomfortable overall programming environment, it can only provide mild relief.

                                                                                                                                                                                                                                                            • hajile 8 hours ago

                                                                                                                                                                                                                                                              I'd rather write JS/TS than most of the other popular languages.

                                                                                                                                                                                                                                                              • rambambram 16 hours ago

                                                                                                                                                                                                                                                                You mean the fourth decade of PHP.

                                                                                                                                                                                                                                                                • beardyw 17 hours ago

                                                                                                                                                                                                                                                                  I admire your conviction.

                                                                                                                                                                                                                                                                  • oblio 14 hours ago

                                                                                                                                                                                                                                                                    I'm not a fan of it, but JavaScript will outlive me.

                                                                                                                                                                                                                                                                  • ioma8 17 hours ago

                                                                                                                                                                                                                                                                    The syntax is ugly as hell.

                                                                                                                                                                                                                                                                    • JohnKemeny 16 hours ago

                                                                                                                                                                                                                                                                      Thank you for your insight.

                                                                                                                                                                                                                                                                      • frankzander 16 hours ago

                                                                                                                                                                                                                                                                        Amen ... I mean PHP could have been such a good language if the syntax wouldn't be such a show stopper.

                                                                                                                                                                                                                                                                      • lihaciudaniel 14 hours ago

                                                                                                                                                                                                                                                                        Wow dead language adds a special letter wowooeoowowoowoo

                                                                                                                                                                                                                                                                        • zweifuss 13 hours ago

                                                                                                                                                                                                                                                                          It's so dead that 79.2% of all websites rely on PHP to some degree.

                                                                                                                                                                                                                                                                          https://kinsta.com/php-market-share/

                                                                                                                                                                                                                                                                          • dvtkrlbs 14 hours ago

                                                                                                                                                                                                                                                                            PHP is a dead language since when ?

                                                                                                                                                                                                                                                                          • lordofgibbons 18 hours ago

                                                                                                                                                                                                                                                                            Why doesn't PHP remove the horrid $ symbol for variables and the -> symbol for calling methods? I think those alone would do a lot more for its perception and adoption than adding the pipe operator.

                                                                                                                                                                                                                                                                            • phatskat 18 hours ago

                                                                                                                                                                                                                                                                              I actually don’t mind them, and I’ve been out of daily PHP work for a few years now. When I see people denote internal variables with _ or elements with $ in JS, it rubs me the wrong way, but in PHP the $ is kind of nice.

                                                                                                                                                                                                                                                                              I also prefer the look of ->, it’s _cool_

                                                                                                                                                                                                                                                                              • kijin 18 hours ago

                                                                                                                                                                                                                                                                                Other languages have all sorts of oversized arrows, like ==> and >>>.

                                                                                                                                                                                                                                                                                -> in PHP and C++ looks clean by comparison.

                                                                                                                                                                                                                                                                                I'll never forgive them for the brain fart they made of the namespace separator, though.

                                                                                                                                                                                                                                                                                • esskay 17 hours ago

                                                                                                                                                                                                                                                                                  What would the alternative for a namespace separator be? The backslashes work well with PSR-4 to give a logical visual of the expected directory structure.

                                                                                                                                                                                                                                                                                • LeonM 17 hours ago

                                                                                                                                                                                                                                                                                  > I'll never forgive them for the brain fart they made of the namespace separator, though.

                                                                                                                                                                                                                                                                                  You mean the backslash? What's wrong with that?

                                                                                                                                                                                                                                                                                  • account42 14 hours ago

                                                                                                                                                                                                                                                                                    To someone not already familiar with PHP it looks like you are trying to escape something.

                                                                                                                                                                                                                                                                                    • kijin 14 hours ago

                                                                                                                                                                                                                                                                                      The backslash is universally reserved as an escape character.

                                                                                                                                                                                                                                                                                      It was decided almost 20 years ago so I'm totally used to it and there's no point arguing about it anymore. But the decision to reuse the backslash as a namespace separator still causes inconvenience from time to time. For example, when you write PSR-4 configuration in composer.json, all the backslashes need to be doubled, including (and especially!) the trailing backslash.

                                                                                                                                                                                                                                                                                • jeroenhd 16 hours ago

                                                                                                                                                                                                                                                                                  Same reason C doesn't introduce classes and C++ doesn't remove pointers: it's a) part of the core language and b) extremely inconsequential for any serious developer.

                                                                                                                                                                                                                                                                                  I actually like the clarity these dollar signs add in a code base. Makes it easier to recognise (dynamic) functions, and makes it harder to accidentally shadow methods.

                                                                                                                                                                                                                                                                                  Other languages will let you do `const Math = {}` and nuke the entire math library, or write stuff like `int fopen = 0;` to make the fopen method call inaccessible in that scope. With PHP, you don't need to restrict your variable name to "something that hopefully won't conflict with an obscure method".

                                                                                                                                                                                                                                                                                  The -> is a leftover from an older programming language that I'd rather have replaced by a ., but not at the cost of breaking existing code (which it surely would).

                                                                                                                                                                                                                                                                                  • account42 14 hours ago

                                                                                                                                                                                                                                                                                    > The -> is a leftover from an older programming language that I'd rather have replaced by a ., but not at the cost of breaking existing code (which it surely would).

                                                                                                                                                                                                                                                                                    Isn't it because . was already used for string concatenation in PHP. I mean the -> syntax wasn't invented by PHP but it didn't just inherit it without thought either.

                                                                                                                                                                                                                                                                                    • int_19h 7 hours ago

                                                                                                                                                                                                                                                                                      Indeed. And the reason why PHP used . for string concatenation is because Perl did.

                                                                                                                                                                                                                                                                                    • asddubs 15 hours ago

                                                                                                                                                                                                                                                                                      I do also appreciate that php has an explicit string concat operator rather than overloading +. Though of course it could just use another symbol for that to get rid of -> if we're talking about time travel. As it stands, you can't really do $obj.method(), because method() could be a function returning a string as well, so it's ambiguous

                                                                                                                                                                                                                                                                                    • pkkm 3 hours ago

                                                                                                                                                                                                                                                                                      PHP has its significant flaws, but superficial syntactic differences aren't among them. In my experience, it takes two weeks to get used to pretty much any syntax.

                                                                                                                                                                                                                                                                                      • nolok 15 hours ago

                                                                                                                                                                                                                                                                                        Because back compat' is a very strong feature of the language, same reason "match" was created instead of replacing switch.

                                                                                                                                                                                                                                                                                        As a result, taking a php 5.2 script and moving it up to 8.5 is super easy, and taking a PHP 4 one is barely harder only longer (since it probably uses the horrors that were register_globals and co).

                                                                                                                                                                                                                                                                                        Ultimately, I prefer this than a fragmented ecosystem impossible to resolve.

                                                                                                                                                                                                                                                                                        • ahofmann 16 hours ago

                                                                                                                                                                                                                                                                                          I honestly don't understand this. The syntax is one of the most boring parts of a programming language. It is solved by the IDE (and now LLMs). I don't care about syntax, I care about what I can build. Since the beginning of time people argue about things like tabs vs. spaces, or the dollar sign and I honestly don't understand why that is. It just doesn't matter.

                                                                                                                                                                                                                                                                                          Just to be clear: consistency does very much matter. The mental load of reading totally different styles of code is awful and a waste of energy.

                                                                                                                                                                                                                                                                                          • Timwi 16 hours ago

                                                                                                                                                                                                                                                                                            Readability (and hence, maintainability) is definitely a factor in decisions like this. In the particular case of the pipe operator though, the article does mention something it lets you do that you couldn't do before: in a context where only an expression is allowed (such as match), you can now do things that previously would not have worked because it would have required temporary variables.

                                                                                                                                                                                                                                                                                          • guskel 9 hours ago

                                                                                                                                                                                                                                                                                            The $ symbol gave me RSI as a dev just starting out. I will never forgive PHP for that. Such an unergonomic syntax.

                                                                                                                                                                                                                                                                                            • throw_m239339 16 hours ago

                                                                                                                                                                                                                                                                                              > Why doesn't PHP remove the horrid $ symbol for variables and the -> symbol for calling methods? I think those alone would do a lot more for its perception and adoption than adding the pipe operator.

                                                                                                                                                                                                                                                                                              Because it simply can't do that in a retro-compatible way. -> isn't so bad, C/C++ uses that as well. as for $ I guess it came from Perl. The point is already used for string concatenation, where other languages would overload the + operator.

                                                                                                                                                                                                                                                                                            • xorcist 14 hours ago

                                                                                                                                                                                                                                                                                              "Essentially the same thing" as a shell pipe, except each function run sequentially in full, keeping output in a variable. So nothing like a shell pipe.

                                                                                                                                                                                                                                                                                              For short constructions '$out = sort(fn($in)' is really easier to read. For longer you can break them up in multiple lines.

                                                                                                                                                                                                                                                                                                $_ = fn_a($in)
                                                                                                                                                                                                                                                                                                $_ = fb_b($_)
                                                                                                                                                                                                                                                                                                $out = fn_c($_)
                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                              Is it really "cognitive overhead" to have the temporary variable explicit? Being explicit can be a virtue. Readability matters in a programming language. If nothing else I think Python taught us that.

                                                                                                                                                                                                                                                                                              I am skeptical to these types of sugar. Often what you really want is an iterator. The ability to hide that need carries clear risk.