(我使用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>
Since OCaml 是一种严格的语言 https://ocaml.org/learn/description.html#Evaluationregime,我期望定义s
就会陷入无限递归。但翻译说s
有一个值,它是Self <cycle>
.
我还应用了一个函数s
.
# let f (s: self) = 1;;
val f : self -> int = <fun>
# f s;;
- : int = 1
它似乎s
在函数应用之前不进行评估(就像在非严格语言中一样)。
OCaml 如何处理循环数据,例如s
? Self <cycle>
是正规形式吗?
OCaml 确实是一种渴望的语言,但是s
是一个完全有效且经过充分评估的术语,恰好包含一个循环。例如,此代码产生预期结果:
let f (Self Self x) = x
f s == s;;
更准确地说,具有 at n 个参数的构造函数的内存表示形式被装箱并按如下方式读取:
⋅—————————————————————————————————————————————⋅
| header | field[0] | field[1] | ⋯ | fiekd[n] |
⋅—————————————————————————————————————————————⋅
标头包含元数据,而field[k]
是一个 OCaml 值,即整数或指针。如果是s
, Self
只有一个参数,因此只有一个字段field[0]
。的价值field[0]
那么只是指向块开头的指针。期限s
因此在 OCaml 中可以完美地表示。
此外,顶级打印机能够检测这种循环并打印<cycle>
以避免在打印值时陷入无限递归s
. Here, <cycle>
, like <abstr>
or <fun>
,仅代表顶层打印机无法打印的一种值。
但请注意,循环值在许多情况下会触发无限递归,例如f s = s
where (=)
是结构平等
而不是物理上的(i.e. (==))
触发这样的递归,另一个例子是
let rec ones = 1 :: ones;; (* prints [1;<cycle>] *)
let twos = List.map ((+) 1) ones;; (* falls in an infinite recursion *)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)