何时使用管道 |> 与参数

When to use piping |> versus arguments

在 Reason(和 OCaml)中,有一种使用 |> 运算符传递参数的非传统方式。什么时候应该使用它的约定是什么?我目前到处都在使用它,只是因为我觉得它太新奇了。

使用|>(正向管道)有助于显示执行顺序

例如,如果你想执行函数f,那么g像这样:

g(f(x))

这样更容易查看执行顺序(例如,f,然后是 g):

x |> f |> g

OCamlF# 等编程语言经常用于将数据从一种形式转换为另一种形式,因此 |> 可以用这种方式来展示数据是如何转换的。

let sqr = x => x * x;

[1,2,3]
|> List.map (x => x + 1)
|> List.map (sqr);

反向应用算子(|>)可以简单定义为

let (|>) x f = f x

这个中缀运算符接受一个值 x 和一个函数 f 并将后者应用于第一个 (f x)。乍一看这似乎没什么用,但如果使用得当,该运算符会非常强大,因为 Ocaml 中的函数是 curried.

例如,假设我们有一个函数 wackymath: int -> int -> int -> int

let wackymath a b c = a + b - c

wackymath的类型是int -> int -> int -> int。这是因为在函数领域(特别是 lambda 演算),任何函数一次只适用于一个参数。因此,在括号的帮助下,wackymath 的应用顺序如下所示:

(((wackymath a) b) c)

参数替换可以使这一点更清楚。

let f1 = wackymath 10;; (* 10 + b - c *)
let f2 = f1 19;;        (* 10 + 19 - c *)  
f2 4;;                  (* 10 + 19 - 4 = 25 *)

这可以用 |> 运算符表示:

4 |> (19 |> (10 |> wackymath));;

现在明白为什么叫reverse应用算子了吧。括号在那里是因为 |> 是左关联的。说 |> 有助于避免括号在所有情况下都不完全准确。

通常,运算符在您想要组合一系列顺序函数应用程序的情况下很有用

[1; 2; 3; 4; 5]
|> List.map (fun x -> x * 2)
|> List.filter (fun x -> x < 3)
|> fun l -> match l with
   | [] -> 0
   | l' -> l' |> List.fold_left ~init:0 ~f:(fun a b -> a + b)
;;