我现在正在学习OCaml,我想出了这段代码.
let rec tree_to_list acc = function
| Leaf x -> x::acc
| Node (t1,t2) -> tree_to_list (tree_to_list acc t2) t1
Run Code Online (Sandbox Code Playgroud)
据我所知,这个功能与此功能相同
let rec tree_to_list2 acc t = match t with
| Leaf x -> x::acc
| Node (t1, t2) -> tree_to_list t1 (tree_to_list2 acc t2)
Run Code Online (Sandbox Code Playgroud)
但是,我不理解第一个函数背后的语法.我发现关键字功能令人困惑.它应该只采用一个参数,例如:
function x -> x + 2
Run Code Online (Sandbox Code Playgroud)
有人可以帮我理解第一个函数的语法,以及两个函数的评估方式是否存在差异.提前致谢.
OCaml中的函数是通过给出参数的模式来定义的.简单变量名称的常见情况(如acc第一个函数中)只是一种匹配所有值的特定模式.
因此,查看它的一种方法是fun定义一个具有任意数量参数的函数,每个参数可以由一个模式给出.另一方面,function定义一个具有一个参数的函数,该函数可以由任意数量的模式给出.
# let dot = fun (a, b) (c, d) -> a *. c +. b *. d
val dot : float * float -> float * float -> float = <fun>
# let geti = function None -> 0 | Some i -> i;;
val geti : int option -> int = <fun>
Run Code Online (Sandbox Code Playgroud)
fun实质上,该形式可以被吸收到a的左侧,let以给出更简洁的符号.
那是,
let f = fun p1 p2 -> ...
Run Code Online (Sandbox Code Playgroud)
可写成
let f p1 p2 = ...
Run Code Online (Sandbox Code Playgroud)
例如:
let dot (a, b) (c, d) = a *. c +. b *. d
Run Code Online (Sandbox Code Playgroud)
您的第一个功能是使用两者的组合(简洁fun和function右侧).
据我了解,此功能与此功能相同
您是正确的,因为这两个代码片段的评估结果相同。
有人可以帮我理解第一个函数的语法吗
由于@JeffreyScofield 似乎很好地回答了这部分,我将专注于第二部分。
如果两个函数的评估方式有任何不同
tl;dr 没有区别,生产的组件实际上是相同的。我们将使用一个简单的 Fibonacci 示例来显示使用match with和function符号发出的程序集。
let rec fib n = match n with
| 0 -> 0
| 1 -> 1
| i -> fib (i - 1) + fib (i - 2)
Run Code Online (Sandbox Code Playgroud)
和
let rec fib = function
| 0 -> 0
| 1 -> 1
| i -> fib (i - 1) + fib (i - 2)
Run Code Online (Sandbox Code Playgroud)
两者都产生
fib:
subq $24, %rsp
.L102:
cmpq $1, %rax
je .L100
cmpq $3, %rax
je .L101
movq %rax, 0(%rsp)
addq $-4, %rax
call fib
.L103:
movq %rax, 8(%rsp)
movq 0(%rsp), %rax
addq $-2, %rax
call fib
.L104:
movq 8(%rsp), %rbx
addq %rbx, %rax
decq %rax
addq $24, %rsp
ret
.L101:
movq $3, %rax
addq $24, %rsp
ret
.L100:
movq $1, %rax
addq $24, %rsp
ret
Run Code Online (Sandbox Code Playgroud)
注意:我故意删除了 .aligns 等。
要验证这些生成相同程序集的声明(因此评估相同),您可以简单地将每个函数放在一个文件中,然后运行
$ ocamlopt -S fib-with-match.ml
$ ocamlopt -S fib-with-function.ml
Run Code Online (Sandbox Code Playgroud)
当你diff两个时,你应该看到它没有区别地返回:
$ diff fib-with-match.s fib-with-function.s
$
Run Code Online (Sandbox Code Playgroud)
match在 OCaml 中拥有仅包含表达式的函数是很常见的,正如@JeffreyScofield 所说,function有一个可用于模式匹配的参数。因此,它是有效的语法糖。
来源: