开发者

Understanding an imperative list example in Ocaml

开发者 https://www.devze.com 2023-01-31 13:24 出处:网络
I am a newcomer to the ocaml. appreciate if anyone can help me understand the material presented on page 94 of the开发者_JAVA技巧 book

I am a newcomer to the ocaml. appreciate if anyone can help me understand the material presented on page 94 of the开发者_JAVA技巧 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"]}


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
0

精彩评论

暂无评论...
验证码 换一张
取 消