【问题标题】:Understanding an imperative list example in Ocaml了解 Ocaml 中的命令式列表示例
【发布时间】:2010-12-22 05:11:24
【问题描述】:

我是 ocaml 的新手。 如果有人能帮助我理解,不胜感激 本书第 94 页提供的材料 “使用客观 caml 开发应用程序”。

难以理解以下段落的意思:

只是(itl l)的评估发生在之前 (ihd l) 的评估,因此在 imap 的最后一次迭代中,l 引用的列表 在我们检查它的头部之前变成了空列表。列表示例如下 即使我们没有得到任何结果也肯定是空的

imap (function x ! x) 示例返回

Uncaught exception: Failure("hd")

而不是

- : string ilist = {c=["one"; "two"; "three"]}

我认为

else icons (f (ihd l)) (imap f (itl l))`

会变成icons("one") ( ( icons("two") ( ( icon("three")([]) ) ) ) 并返回

- : string ilist = {c=["one"; "two"; "three"]}

【问题讨论】:

    标签: ocaml


    【解决方案1】:

    我在书中的示例中,列表已以命令式样式实现。函数itl 改变了列表——也就是说,它通过删除第一个元素来改变列表。在调用itl 之后,第一个元素基本上永远消失了。

    棘手的部分是icons 的参数在语句中的执行顺序:

    else icons (f (ihd l)) (imap f (itl l))
    

    在 OCaml 规范中没有指定顺序。上次我检查 INRIA 编译器时,首先排序了最后一个参数,所以 (imap f (itl l))before (f (ihd l)) 之前执行。这意味着在实际调用ihd 时,itl 已被调用足够多次以删除l 的所有元素。

    例如,让我们看一下倒数第二个递归调用 - l 就是 ["three"]。您认为这会导致:

    icons (f "three") (imap f [])
    

    但是,让我们看看如果我们先调用 itl 会发生什么:

    (* l = ["three"] *)
    let tail = (itl l) in (* tail = [], l = [] *)
    let head = (ihd l) in (* l = [], ihd raises an exception *)
    icons head (imap f tail)
    

    例如,尝试运行以下代码:

    let f x y z = x + y + z
    f (print_int 1; 1) (print_int 2; 2) (print_int 3; 3)
    

    在我的机器上 (OCaml 3.12) 我得到这个输出:

    321- : int = 6
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-17
      • 2015-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多