Does it matter if you use fast pipe or normal chain operator if there is only one argument?

I saw people asking about trying to give preference to fast pipe when updating libraries or creating new APIs, but, the way I usually do pipe is by piping it through partially applied functions where only one last argument is missing.
So, if only one argument is missing I think it does not matter if you use |> or ->, so why is people so worried about this? I even have codebases where I accidentally used both and no change on the behavior happened.

note for one argument, -> is still faster than |> in some edge cases, since the first is resolved in syntax level.

so why is people so worried about this?

It’s great that you don’t worry about it

2 Likes

If it is as I described, no I don’t worry about it at all.
So -> is more often translated to 0 cost calls than |>, that’s good to know

1 Like

IIUC, there’s no partial application involved when you use the fast pipe. a->foo(b,c) is just sugar for foo(a,b,c), whereas with c |> foo(a,b)you first partially applyfootoa&b, getting a new function that you then apply to c`. Of course, in some cases, the ReScript compiler may optimize that distinction away.

As for your question, the strongest argument I’ve read for the slow pipe goes like this: slow pipe means your functions are supposed to be data-last, and that means partial application is concise: Js.String.get(0) is shorter and less noisy than s => Js.String2.get(s, 3). Sure, with pipes, you can go a |> Js.String2.get(_, 3), but if you want something to pass to a higher-order function, the difference is more noticeable:

open Belt;
arr
->Array.get(3)
->Option.map(Js.String.get(3))
// vs
arr
->Array.get(3)
->Option.map(s => Js.String2(s, 3))

Sure, it’s still not such a big difference, but it’s pure noise and FP programmers are usually noise intolerant :slight_smile:

One way to make partial application easier is to make all arguments but one labeled. This is the road that Jane Street Base ended up taking, and this is what Tablecloth was (?) trying to bring to ReasonML. But this is not the approach endorsed by the ReScript team, AFAIR, because it brings its own bit of noise.

PS. Speaking of Js.String, to make usage like "cow" |> Js.String.concat("bell") work as expected, the devs had to make the signature rather confusing. Js.String2 doesn’t have this problem, so you may see where the devs are coming from with the data-first approach.

Overall, I don’t think either of the approaches is perfect—or, conversely, very bad. I think we should just trust the ReScript team that they know what they’re doing and that fast pipe is better in the long run.

5 Likes