理解 Ocaml 中的命令式列表示例

发布于 2024-10-08 20:55:34 字数 705 浏览 0 评论 0原文

我是 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("二") ( ( 图标("三")([]) ) ) ) 并返回

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

I am a newcomer to the ocaml.
appreciate if anyone can help me understand
the material presented on page 94 of the book
"developing applications with objective caml".

having trouble to grasp the meaning of the following paragraph:

Just that the evaluation of (itl l) has taken place before the
evaluation of (ihd l), so that on the last iteration of imap, the list referenced by l
became the empty list before we examined its head. The list example is henceforth
definitely empty even though we have not obtained any result

The imap (function x ! x) example returns

Uncaught exception: Failure("hd")

instead of

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

I would think that the

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

would become icons("one") ( ( icons("two") ( ( icon("three")([]) ) ) )
and return

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

树深时见影 2024-10-15 20:55:34

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

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

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

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

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

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

I the example in the book, the list has been implemented in an imperative style. The function itl mutates the list - that is it changes the list by removing the first element. After the call to itl, the first element is essentially gone forever.

The tricky part is the order in which arguments to icons are executed in the statement:

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

In the OCaml spec the order isn't specified. Last time I checked the INRIA compiler ordered the last argument first, so (imap f (itl l)) is executed before (f (ihd l)). What this means is that by the time ihd is actually called, itl has been called enough times to remove all the elements of l.

As an example, let's look at the penultimate recursive call - l is just ["three"]. You think that this would result in:

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

However let's look at what happens if we call itl first:

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

As an example, try running this code:

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

On my machine (OCaml 3.12) I get this output:

321- : int = 6
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文