What's the difference between -> (skinny arrow operator) and |> (triangle operator)?


I’ve seen this triangle operator |> in some code examples, but couldn’t find any information about it in the reason docs. There’s only -> described as a fast pipe.

I’ve made a primitive demo, to find out what the difference was, but results turned out the same: Link for the demo


To avoid confusion, fast pipe is now called pipe first: https://reasonml.github.io/docs/en/fast-pipe (yeah I know, the url still says otherwise).
And it means the first parameter of the function is the one handled by the first pipe operator -> whereas |> pipes the last parameter of the function.

As you only use one-parameter-functions in your example, it really makes no difference. I adapted it a bit with the separator as a second parameter: Link



Thanks fham, now it’s clear.

Still very weird, why there’s no mention in docs about |> operator, is it intentional? or is it part of ocaml and it’s assumed that you should read it in ocaml docs?


I got no answer why it isn’t mentioned in the current ReasonML docs, I am still a beginner myself, but I do think I have read about it in the ReasonML documentation a time ago, may it have been removed?

It is called the reverse-application operator, you can read about it in the API-documentation on Pervasives and in the functions section of Rauschmayer’s guide on ReasonML.


@notgiorgi I think the omission is not really intentional, it’s just that they want to encourage usage of Belt over the standard library, and the |> operator does not work well with Belt functions.

Btw, in ReasonTown they call |> the pizza operator, which for me is easier to remember than reverse-application operator. There is also the |., or golf club operator, which has been deprecated in favor of -> but can still appear in .ml files.


it’s just that they want to encourage usage of Belt over the standard library

What’s Belt?

This comes up: https://bucklescript.github.io/bucklescript/api/Belt.html

A stdlib shipped with BuckleScript

If I’m understanding this correctly:

Bucklescript/Reason both used JS implementation of oCaml stdlib before, then Belt was introduced to make stdlib more js-friendly. |> operator was part of oCaml stdlib, while -> is more Belt thing, so now it’s more commonly used.


It still doesn’t support native compilation though, so if you need that then don’t use any part of it or you’ll be stuck.


It is not intentional, I just know that people are busy and everything takes time :smile: I wrote the first documentation for the fast-pipe out of need because it didn’t exist in the reasonml documentation! :smiley:

I know if you want to add it they would be so happy!


It’s a ppx and someone packaged it as a opam package https://github.com/IwanKaramazow/FastPipe


Was speaking of Belt, not PipeFirst. ^.^


Right, the same thing for Belt as well. it’s idiomatic OCaml (the implementation, not public API) so you can extract it into a package. An example of doing that is here https://github.com/jaredly/reason-language-server/tree/master/belt . Someone should package it for OPAM though


It seems like “pipe-first” can be used with an underscore placeholder to pipe a value into any missing parameter? It doesn’t have to be the first parameter. I’m I reading that right from the docs?


Right. Placeholders were introduced specifically as a syntax sugar for not having to write out a full lambda abstraction, e.g. instead of x => f(1, x, 2) you can write f(1, _, 2).


At the moment the three operators work ( “|>” , “|.” , “->”). For me the pizza and the golf operator looks better… What is the reason for this syntax (->) ? Also the use of the vertical bar is consistent with Unix pipes and “->” has a different meaning in Ocaml.


-> is the new, shiny syntax for |.


|. is the BuckleScript operator, -> is the same operator in ReasonML. I’m guessing they used it because it was available and makes sense aesthetically. Like, chaining a series of calls like foo->bar->baz(quux) looks like property or function accesses in other languages and translates nicely into baz(bar(foo), quux). It effectively adds Uniform Function Call Syntax to Reason.


I’ll add a link to a little blog post I wrote on the topic, in case that helps clear things up further: