【问题标题】:Trying to understand this block of code in OCaml试图理解 OCaml 中的这段代码
【发布时间】:2012-02-17 04:42:18
【问题描述】:

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

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

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

谢谢。

【问题讨论】:

    标签: function functional-programming ocaml


    【解决方案1】:

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

    大小是通过在每一步中使用模式_::tail_ 表示我们忽略列表的头部)减少x 并在tail 上调用相同的函数size 来计算的。当列表为空且[] 的模式成功时,函数最终终止。

    下面是如何计算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
    

    作为旁注,您可以从图中看到需要将大量信息存储在堆栈中以计算size。这意味着如果输入列表很长,您的函数可能会导致堆栈溢出错误,但这是另一回事。

    【讨论】:

    • 从技术上讲,:: 是一个构造函数,而不是一个运算符——这就是为什么你可以对它进行模式匹配,这与 @ 不同
    【解决方案2】:

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

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

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

    所以,_::tail 减少了列表,1 + (size tail) 计算了大小。 | 之前的位当然是递归的终止条件。

    如果被视为:(在我看来)可能更容易理解:

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

    (这实际上与链接页面中使用的格式非常相似,我只是稍作更改以对齐-> 符号)。

    【讨论】:

      【解决方案3】:

      任何时候你匹配一个列表,你都可以匹配head::tail 形式的模式,其中head 将获得第一个元素的值,tail 将获得余数。此模式将匹配任何非空列表,因为 tail 可以为空,但 head 必须存在。

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

      【讨论】:

        【解决方案4】:

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

        match 表示您将尝试让x 输入以下模式之一。

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

        (*) 下划线表示你不关心这个元素的值。

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            猜你喜欢
            • 2019-08-30
            • 2019-02-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-04-11
            • 1970-01-01
            • 1970-01-01
            • 2020-11-04
            相关资源
            最近更新 更多