Which language first introduced the pipe operator?

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?

4 Likes

Many will likely argue that piping is even older, as it was widely used in shell scripts before that.

4 Likes

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.

4 Likes

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.

2 Likes

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.

2 Likes

FYI:

I seem to recall that multiple sources claim that José borrowed it from F#.

3 Likes

@josevalim your two cents are needed. :slight_smile:

1 Like

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 />.

8 Likes

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…

1 Like

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.

6 Likes

According to Mr. Armstrong, the pipe operator is basically an eager version of Prolog DCGs.

2 Likes

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. ^.^

2 Likes