Functional programming @@和|>;OCaml中的运算符优先级
我试图理解两个OCaml操作符:Functional programming @@和|>;OCaml中的运算符优先级,functional-programming,ocaml,Functional Programming,Ocaml,我试图理解两个OCaml操作符:@和|> 我知道x |>f只是f(x),但它为什么存在呢?我不明白为什么。与@相同,正如我所理解的,这只是正常的函数应用程序 例如: match get_ipv4_hlen_version buf |> version with | 0x40 -> Ok buf | n -> Error (Printf.sprintf "IPv4 presented with a packet that claims a differe
@
和|>
我知道x |>f
只是f(x)
,但它为什么存在呢?我不明白为什么。与@
相同,正如我所理解的,这只是正常的函数应用程序
例如:
match get_ipv4_hlen_version buf |> version with
| 0x40 -> Ok buf
| n -> Error (Printf.sprintf "IPv4 presented with a packet that claims a different IP version: %x" n)
为什么不直接编写get\u ipv4\u hlen\u version buf
那怎么办
let options_len = nearest_4 @@ Cstruct.len t.options
为什么不let options\u len=最近的\u 4 Cstruct.lent.options
?
我想这与优先权有关,我从哈斯克尔那里回忆起一些事情,但我不知道哈斯克尔,我只是在某个地方读过
我怎么知道事情的先后顺序
如果需要更多的上下文,这两个代码来自只有当您有多个嵌套函数应用程序时,
的符号值才会出现。许多人发现:
x |> f a |> g b c |> h d
f x @@ g a b @@ h c d
比这更容易阅读:
h d (g b c (f a x))
f x ((g a b) (h c d))
因为不再需要在心理上匹配括号,而且操作是按从左到右的顺序进行的(这对于英语和其他从左到右的语言的读者来说是很自然的)
如果您熟悉Unix命令行,那么将
操作符与Unix管道操作符
类似可能会有所帮助
像@
这样的低优先级函数应用运算符也有助于避免括号(以及括号的心理匹配)。许多人发现:
x |> f a |> g b c |> h d
f x @@ g a b @@ h c d
比这更容易阅读:
h d (g b c (f a x))
f x ((g a b) (h c d))
您对@的示例是错误的。这个
let options_len = nearest_4 @@ Cstruct.len t.options
相当于:
let options_len = nearest_4 (Cstruct.len t.options)
和你写的不一样
运算符的优先级由其第一个字符决定。这又由OCaml手册中的表定义
(当然,您需要非常仔细地阅读表格前面的文本,以查看优先级规则。)
更新
完全披露:我从不在自己的代码中使用
|>
或@
。我对几个括号没有问题,我通常使用let
将一个大表达式分解成更小的部分。只有在有多个嵌套函数应用程序时才会显示
的符号值。许多人发现:
x |> f a |> g b c |> h d
f x @@ g a b @@ h c d
比这更容易阅读:
h d (g b c (f a x))
f x ((g a b) (h c d))
因为不再需要在心理上匹配括号,而且操作是按从左到右的顺序进行的(这对于英语和其他从左到右的语言的读者来说是很自然的)
如果您熟悉Unix命令行,那么将
操作符与Unix管道操作符
类似可能会有所帮助
像@
这样的低优先级函数应用运算符也有助于避免括号(以及括号的心理匹配)。许多人发现:
x |> f a |> g b c |> h d
f x @@ g a b @@ h c d
比这更容易阅读:
h d (g b c (f a x))
f x ((g a b) (h c d))
您对@的示例是错误的。这个
let options_len = nearest_4 @@ Cstruct.len t.options
相当于:
let options_len = nearest_4 (Cstruct.len t.options)
和你写的不一样
运算符的优先级由其第一个字符决定。这又由OCaml手册中的表定义
(当然,您需要非常仔细地阅读表格前面的文本,以查看优先级规则。)
更新
完全披露:我从不在自己的代码中使用
|>
或@
。我对几个括号没有问题,我通常使用let
将一个大表达式分解成更小的部分。操作符|>
非常方便。它相当于壳体中的管道。它允许您编写如下代码:
let make_string n =
Array.init n float_of_int
|> Array.map (fun x -> x -. 0.5 *. (float_of_int (n-1)))
|> Array.map (fun x -> Printf.sprintf "-- %10.6f --" x)
|> Array.to_list
|> String.concat "\n"
in
make_string 5
(* Output:
-- -2.000000 --
-- -1.000000 --
-- 0.000000 --
-- 1.000000 --
-- 2.000000 --
*)
在本例中,以|>
开头的每一行都会获取上一次转换的输出,因此我们可以看到数据转换的流程,就像在Bash中编写类似
ls | grep txt | sort | uniq
@
操作符是“向后管道”。它允许删除会降低代码可读性的括号。例如,我们想制作一系列矩阵积,比如C=a.B.C.D。你想让代码与数学公式保持一致,所以你想以相同的顺序编写它。如果mm A B
对A和B进行矩阵乘法,那么我们可以编写
let mat_C =
mm mat_A @@ mm mat_B @@ mm mat_C mat_D
而不是
let mat_C =
mm mat_A (mm mat_B (mm mat_C mat_D))
|>
操作符非常方便。它相当于壳体中的管道。它允许您编写如下代码:
let make_string n =
Array.init n float_of_int
|> Array.map (fun x -> x -. 0.5 *. (float_of_int (n-1)))
|> Array.map (fun x -> Printf.sprintf "-- %10.6f --" x)
|> Array.to_list
|> String.concat "\n"
in
make_string 5
(* Output:
-- -2.000000 --
-- -1.000000 --
-- 0.000000 --
-- 1.000000 --
-- 2.000000 --
*)
在本例中,以|>
开头的每一行都会获取上一次转换的输出,因此我们可以看到数据转换的流程,就像在Bash中编写类似
ls | grep txt | sort | uniq
@
操作符是“向后管道”。它允许删除会降低代码可读性的括号。例如,我们想制作一系列矩阵积,比如C=a.B.C.D。你想让代码与数学公式保持一致,所以你想以相同的顺序编写它。如果mm A B
对A和B进行矩阵乘法,那么我们可以编写
let mat_C =
mm mat_A @@ mm mat_B @@ mm mat_C mat_D
而不是
let mat_C =
mm mat_A (mm mat_B (mm mat_C mat_D))
这回答了你的问题吗?这回答了你的问题吗?“fx@@gab@@hcd”和你说的“fx((gab)(hcd))一样吗?它不是和‘fx(gab(hcd))一样吗?所以,也许它不那么容易阅读。好吧,你说得有道理!我测试了我的例子,所以我认为它是正确的。我相信这一点仍然有效(可能对于更简单的表达式)。而且,
fx((gab)(hcd))
和fx(gab(hcd))
是同一个表达式,这些参数是不必要的:-)@PatJ第一个不部分适用于g
?不像第二个?如果说a
和c
有副作用,这可能会有不同。@ghilesZ因为函数参数的求值顺序是未指定的,并且由于ocaml的自动部分应用,我转而认为,就语言而言,带有附加括号的版本和带有