什么是数据中的<cycle>?

时间:2017-06-05 11:18:30

标签: ocaml evaluation

(我使用OCaml版本4.02.3)

我定义了一个类型self

# type self = Self of self;;
type self = Self of self 

及其实例s

# let rec s = Self s;;
val s : self = Self <cycle>

OCaml is a strict language开始,我预计定义s会陷入无限递归。但是翻译说s有一个值,它是Self <cycle>

我还将一个函数应用于s

# let f (s: self) = 1;;
val f : self -> int = <fun> 
# f s;;
- : int = 1 

在函数应用程序之前似乎没有评估s(就像在非严格语言中一样)。

OCaml如何处理s等循环数据? Self <cycle>是正常形式吗?

1 个答案:

答案 0 :(得分:4)

OCaml确实是一种渴望的语言,但s是一个完全有效且完全评估的术语,恰好包含一个循环。例如,此代码产生预期结果:

let f (Self Self x) = x
f s == s;; 

更确切地说,具有n个参数的构造函数的内存表示被加框并读取如下:

⋅—————————————————————————————————————————————⋅
| header | field[0] | field[1] | ⋯ | fiekd[n] |
⋅—————————————————————————————————————————————⋅

标头包含元数据,而field[k]是OCaml值,即整数或指针。在s的情况下,Self只有一个参数,因此只有一个字段field[0]。然后field[0]的值只是指向块开始的指针。因此,术语s在OCaml中完全可以表示。

此外,顶级打印机能够检测到这种循环并打印<cycle>以避免在打印s的值时陷入无限递归。在这里,<cycle>,如<abstr><fun>,只代表顶级打印机无法打印的一种值。

但请注意,在许多情况下,循环值将触发无限递归,例如f s = s其中(=)是结构相等 而不是物理的(i.e. (==))触发这种递归,另一个例子是

let rec ones = 1 :: ones;; (* prints [1;<cycle>] *)
let twos = List.map ((+) 1) ones;; (* falls in an infinite recursion *)