2015-10-21 32 views
1

我目前正在学习OCaml,我想到了这段代码。函数关键字的区别以及在OCaml中的匹配

let rec tree_to_list acc = function 
    | Leaf x -> x::acc 
    | Node (t1,t2) -> tree_to_list (tree_to_list acc t2) t1 

据我理解这个功能做了同样的比这个

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) 

不过,我不明白的第一个函数后面的语法。我发现关键字功能令人困惑。它应该是一个参数只如:

function x -> x + 2 

可能有人请帮助我理解第一个函数的语法,如果任何在这两者的功能是如何评估方面的差异。提前致谢。

+0

是的,有点令人困惑,我们有3个函数定义语法,并在参数绑定方面模式匹配 - 是的,你可以模式匹配左等号。 –

+0

Colin G.D.在OCaml中有一篇关于函数式编程的简介(www.france-universite-numerique-mooc.fr)。它仍然是开放的。他本周开始(由Xavier Leroy介绍)。 –

+0

嗨@ V.Michel我知道这个mooc,我的老师是背后的老师,不过谢谢你。 –

回答

2

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> 

fun形式可以在本质上被吸收到一个let的左手侧,以提供更简洁的表示法。

即,

let f = fun p1 p2 -> ... 

可以写成

let f p1 p2 = ... 

因此,例如:

let dot (a, b) (c, d) = a *. c +. b *. d 

你的第一函数使用两个(一简要fun的组合和右边的function)。

0

第一个函数只是不明确地命名它的参数。 你可以做同样的,增加了2功能:

let f = (+) 2;; 

这将增加2至任何数量和ARG没有明确命名。

3

据我理解这个功能确实比这个

你是在正确的两段代码进行评估一样一样的。

可能有人请帮助我理解第一功能

的语法@JeffreyScofield似乎已经非常漂亮地回答了这个部分,我将重点放在第二部分。

如果在两者的功能如何被评估

对TL方面的任何差异; dr为没有差别和所产生的组件实际上是相同的。我们将使用一个简单的斐波那契示例来显示使用match withfunction表示法发射的组件。

let rec fib n = match n with 
| 0 -> 0 
| 1 -> 1 
| i -> fib (i - 1) + fib (i - 2) 

let rec fib = function 
| 0 -> 0 
| 1 -> 1 
| i -> fib (i - 1) + fib (i - 2) 

都产生

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 

注:我故意除去.align S和这样。

要验证要求,这些产生相同的组件(并因此评估相同的),则可以简单地把各功能在一个文件中,然后运行

$ ocamlopt -S fib-with-match.ml 
$ ocamlopt -S fib-with-function.ml 

diff两个,则应该看到它与无差异返回:

$ diff fib-with-match.s fib-with-function.s 
$ 

这是非常常见的有仅包含OCaml中match表情功能,从而@JeffreyScofield说,function具有可用于模式MA参数tching。因此,它是有效的语法糖。

来源:

1

我的方式来解释OCaml中的函数定义:

这些等价的:

let name p1 p2 ... pn = expr 
let name = function p1 -> function p2 -> ... -> function pn -> expr 
let name = fun p1 p2 ... pn -> expr 

如何备忘录RIZE它:

  • 首先是语法糖,

  • 第二个是它真正的内部呢,

  • 三是从传统的CAML。

现在function只有一个参数,但它常常被这样的 - 这些都是等同,你在P3匹配:

let f1 p1 p2 p3 = match p3 with 
| [] -> expr 
| ... 

let f2 p1 p2 = function 
    | [] -> expr 
    | ... 

你看到的第二个版本可以节省一些源字符,消除视觉混乱。或者更多:不需要将值绑定到p3而不使用p3变量,因为模式匹配是最好的绑定构造。