Right, and I was addressing the concern of performance by pointing out that in cases that you do have non-trivial partially-applied functions you can simply give a name to the partially-applied version. (The identity monad helps you mark where you have performance implications for partial application.) Most of the time, I wager, the function you are working with does not behave that way.
If you want to do the performance comparison for non-staged partial application, the result is contrary to what you are suggesting (|>
is faster than %>
):
open! Core
open Core_bench
let (%>) f g x = g (f x)
let f x y = x + String.length y
let g x y = x * y
let pipeline_composed = f 1 %> g 2
let pipeline_eta_expanded x = x |> f 1 |> g 2
let () =
let composed = Test.create ~name:"composed" (fun () -> pipeline_composed "hello") in
let eta_expanded = Test.create ~name:"eta expanded" (fun () -> pipeline_eta_expanded "hello") in
Bench.make_command [ composed; eta_expanded ]
|> Command.run
;;
With the output:
Estimated testing time 20s (2 benchmarks x 10s). Change using -quota SECS.
Name Time/Run Percentage
-------------- ---------- ------------
composed 6.79ns 100.00%
eta expanded 2.55ns 37.55%
(at least on my machine, a 1.4GHz Macbook Air running OCaml 4.05.0, no flambda)
I’m not going to hazard any speculation about why the performance of the two pipelines are so different in the first place, since I’m certainly not qualified to, but that’s the result I got, FWIW. YMMV.
Sorry my initial post wasn’t clear about what point I was addressing. I should have included an example or something.