我是ocaml的新手。 感谢任何人都可以帮助我理解 本书第94页上的材料 “以客观的方式开发应用程序”。
无法掌握以下段落的含义:
只是
(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"]}
答案 0 :(得分:4)
我在书中的例子中,列表已经以命令式的方式实现。函数itl
改变列表 - 即通过删除第一个元素来更改列表。在调用itl
之后,第一个元素基本上就永远消失了。
棘手的部分是icons
的参数在语句中执行的顺序:
else icons (f (ihd l)) (imap f (itl l))
在OCaml规范中未指定顺序。上次我检查INRIA编译器首先命令最后一个参数,所以(imap f (itl l))
在 (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