Elm has pipe operator like Elixir does. I read on reddit that OCaml and F# also have pipe operators.
I’m curious if it was Elixir which introduced the pipe operator and other languages copied it, or it was some other language which introduced the idea of pipe operator?
Many will likely argue that piping is even older, as it was widely used in shell scripts before that.
I would assume this is one of those things where depending on how pedantic you are you can attribute this to any number of languages along the way.
As @david_ex says, piping things was in Unix pretty much from the beginning. In terms of languages, lots of them have analogs. Clojure, for example, has ->
which threads a value through a series of forms, and so on. With regards to the Lisps it’s almost impossible to know what macros were floating around out there. I don’t think piping macros were ever part of a scheme standard.
Considering the ease with which you can do it, I’m sure lots of projects have defined some funky operator in Haskell as follows:
(|>) = flip ($)
The question in the end probably boils down to whether or not the symbols themselves are the important part or if this pertains to the concept itself.
The Haskell community has pretty much settled on &
as the operator for this function. This has been exported by Lens
for many years, and the modern prelude replacements such as Protolude and RIO export it as well.
I would assume this predates lens
by many years. It’s a fairly obvious tool and being that it’s so trivial to define it’s even throwaway utility module level stuff.
FYI:
I seem to recall that multiple sources claim that José borrowed it from F#.
@josevalim your two cents are needed.
Almost sure we got it from F# but somebody pointed early on that it existed in ML before that. Note: at the very beginning the pipe operator was written as />
.
I’ve been using pipes for a while now and it still feels slightly uncomfortable, finger-wise. And yet for some reason I’d still prefer |> over />, despite finding the latter easier to type…
FYI:
In OCaml (and derivatives like F#) |>
pipes into the last argument of the function (something that is often glossed over as many demonstration examples only play with single argument functions).
Interestingly BuckleScript introduced “fast pipe” |.
(or ->
in reasonml) in version 3.1 (2018-May-21).
This was primarily motivated to smooth over interop with JavaScript object methods. bs.send
is typically used to transform BuckleScript’s f(x,a,b)
to JS x.f(a,b)
- in line with the common “object first” signature convention.
However since |>
pipes to the last argument, bs.send.pipe
was an alternate directive (attribute) that transformed f(a,b,x)
to x.f(a,b)
. Unfortunately that created a situation where you had to either choose an “object first” or “pipe last” signature for any one JS object method - or create both with separate names, one for “regular” use and another for pipelining. (Keeping in mind that BuckleScript typically prefers compile time transformations over runtime ones for performance reasons - so runtime reordering of arguments wasn’t considered optimal in the long run).
To alleviate that issue interop is going to standardize on bs.send
and |.
is going to be the standard way to pipe into functions that are JS object methods under the hood.
According to Mr. Armstrong, the pipe operator is basically an eager version of Prolog DCGs.
In fact this is literally true, they both compile to instructions for the EVM (Erlang Virtual Machine) – actually nobody call this the EVM They just say the “Beam” VM but I thing we should start calling this the EVM to distinguish it for the JVM.
Oh hey, I knew I got EVM
from somewhere! I must have read this a while back. ^.^