Pipe First
BuckleScript has a special |.
(or ->
for Reason) pipe syntax for dealing with various situations. This operator has many uses.
Pipelining
The pipe takes the item on the left and put it as the first argument of the item on the right. Great for building pipelines of data processing:
a
|. foo b
|. bar
a
->foo(b)
->bar
is equal to
bar(foo a b)
bar(foo(a, b))
JS Method Chaining
JavaScript's APIs are often attached to objects, and often chainable, like so:
const result = [1, 2, 3].map(a => a + 1).filter(a => a % 2 === 0);
asyncRequest().setWaitDuration(4000).send();
Assuming we don't need the chaining behavior above, we'd bind to each case this using bs.send
from the previous section:
external map : 'a array -> ('a -> 'b) -> 'b array = "map" [@@bs.send]
external filter : 'a array -> ('a -> 'b) -> 'b array = "filter" [@@bs.send]
type request
external asyncRequest: unit -> request = "asyncRequest"
external setWaitDuration: request -> int -> request = "setWaitDuration" [@@bs.send]
external send: request -> unit = "send" [@@bs.send]
[@bs.send] external map : (array('a), 'a => 'b) => array('b) = "map";
[@bs.send] external filter : (array('a), 'a => 'b) => array('b) = "filter";
type request;
external asyncRequest: unit => request = "asyncRequest";
[@bs.send] external setWaitDuration: (request, int) => request = "setWaitDuration";
[@bs.send] external send: request => unit = "send";
You'd use them like this:
let result = filter (map [|1; 2; 3|] (fun a -> a + 1)) (fun a -> a mod 2 = 0)
let () = send(setWaitDuration (asyncRequest()) 4000)
let result = filter(map([|1, 2, 3|], a => a + 1), a => a mod 2 == 0);
send(setWaitDuration(asyncRequest(), 4000));
This looks much worse than the JS counterpart! Now we need to read the actual logic "inside-out". We also cannot use the |>
operator here, since the object comes first in the binding. But |.
and ->
work!
let result = [|1; 2; 3|]
|. map(fun a -> a + 1)
|. filter(fun a -> a mod 2 == 0)
let () = asyncRequest () |. setWaitDuration 400 |. send
let result = [|1, 2, 3|]
->map(a => a + 1)
->filter(a => a mod 2 === 0);
asyncRequest()->setWaitDuration(400)->send;
Pipe Into Variants
This works:
let result = name |. preprocess |. Some
let result = name->preprocess->Some
We turn this into:
let result = Some(preprocess(name))
let result = Some(preprocess(name))