【问题标题】:When to use piping |> versus arguments何时使用管道 |> 与参数
【发布时间】:2018-04-17 06:47:51
【问题描述】:

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

【问题讨论】:

  • 如果它类似于 Clojure 的线程宏 ->(将一个表达式的结果作为下一个表达式的第一个参数传递,并沿所有表达式继续),当你有需要进行转换数据的长链/调用管道。我到处都使用这样的宏,因为它们摆脱了嵌套调用并提高了可读性。
  • @Carcigenicate 换句话说,我应该一直使用它们,除非它肯定会损害可读性?
  • 从 Clojure 的角度来看,是的。每当我必须通过 >= 2 转换“线程化”一个参数时,我都会使用线程宏,除非我有理由相信它可能会损害可读性,或者由于参数顺序不匹配而不可行。它们使您以后可以更轻松地将零件添加到“管道”中,并且正如答案所指出的那样,可以带来更好的阅读顺序。在 Clojure 中,它是一个宏,因此甚至没有运行时成本。我不确定它在 OCaml 中是如何工作的。

标签: ocaml conventions reason


【解决方案1】:

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

例如,如果你想执行函数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);

【讨论】:

  • 什么时候不应该使用它?
  • 这取决于样式和代码可读性。我看不出x |> ff(x) 好,还是OCaml/F#f x 好,所以我永远不会那样使用它。
【解决方案2】:

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

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)
;;

【讨论】:

    猜你喜欢
    • 2020-01-09
    • 1970-01-01
    • 1970-01-01
    • 2012-03-30
    • 2017-05-28
    • 2021-02-02
    • 1970-01-01
    • 1970-01-01
    • 2021-06-13
    相关资源
    最近更新 更多