试图理解OCaml中的这段代码

时间:2012-01-23 20:46:04

标签: function functional-programming ocaml

我试图了解这段代码正在做什么:

let rec size x =
    match x with
      [] -> 0
    | _::tail -> 1 + (size tail) ;;

我知道这个表达式计算列表的大小,但我不明白它在代码中的位置逐一减少了列表。例如,我认为它需要从[1; 2; 3]到[2; 3]到[3],但是在哪里或如何做到这一点?我不明白。

感谢。

5 个答案:

答案 0 :(得分:10)

OCaml中的列表是使用空列表([])和cons(::)构造函数递归构建的。所以[1; 2; 3]1::2::3::[]的句法糖。

通过使用模式x_::tail表示我们忽略列表的头部)并调用相同的函数{{1},在每个步骤中减少_来计算大小。在size上。当列表为空并且tail的模式成功时,该函数最终终止。

以下是如何计算[]的简短说明:

size [1; 2; 3]

作为旁注,您可以从图中看到,需要在堆栈中存储大量信息才能计算 size 1::2::3::[] ~> 1 + size 2::3::[] // match the case of _::tail ~> 1 + 1 + size 3::[] // match the case of _::tail ~> 1 + 1 + 1 + size [] // match the case of _::tail ~> 1 + 1 + 1 + 0 // match the case of [] ~> 3 。这意味着如果输入列表很长,你的函数可能会导致堆栈溢出错误,但这是另一个故事。

答案 1 :(得分:4)

根据this article,实际上您正在讨论的确切示例:

  

正如我们所看到的,列表可以是空的(列表的格式为[]),或者由第一个元素(其头部)和子列表(其尾部)组成。该列表的格式为h::t

如果列表匹配空列表,或者使用模式匹配来提取头部(第一项)和尾部(所有其他项),则提供的语句简单地给出0,然后使用递归来获得尾部的长度。

因此,_::tail缩小列表,1 + (size tail)计算大小。当然,|之前的位是递归的终止条件。

如果被视为:

,可能更容易理解(在我看来)
let rec size x = match x with
            []  ->  0
    |  _::tail  ->  1 + (size tail)
    ;;

(这实际上非常类似于链接页面中使用的格式,我只是稍微改了一下以排列->符号)。

答案 2 :(得分:4)

实际上,这段代码使用模式匹配的力量来计算列表的大小。

match表示您将尝试使x以下列模式之一进入。

第一个[]表示您的列表为空,因此其大小为0.而第二个_::tail表示您有一个元素(*),后跟列表的其余部分,所以基本上大小是1 + size(rest of the list)

(*)下划线表示您不关心此元素的值。

答案 3 :(得分:4)

只要您与列表匹配,就可以匹配head::tail形式的模式,其中head将获取第一个元素的值,tail将获得余数。

这个模式将匹配任何非空列表,因为尾部可以为空,但是头部必须存在。

第二,你在Ocaml中匹配的任何模式,如果你愿意,你可以用下划线替换一个变量来说“匹配这里的东西,但我不打算实际使用它,所以我不给它的名字是“。因此,在这个程序中,不是编写head::tail -> 1 + (size tail),而是编写_::tail -> 1 + (size tail),因为它们实际上并没有使用第一个元素,只是确保它存在。

答案 4 :(得分:1)

它使用模式匹配来提取列表的尾部(命名为tail),然后使用尾部调用自身。也许缺少的部分是模式匹配。