2017-06-05 22 views
4

(I使用OCaml的版本4.02.3)什麼是<cycle>的數據?

予定義的類型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>是一種正常的形式?

回答

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 *) 
+0

是v4.0.2中引入的功能?使用[Try OCaml](https://try.ocamlpro.com/)(v4.0.1)'s'不能被定義。 – letrec

+2

的打印只是頂級打印機的一個功能,確實在4.02版中引入(參見https://caml.inria.fr/mantis/view.php?id=6228)。但是,自OCaml 1.0開始可以定義循環值(請參閱http://caml.inria.fr/pub/docs/manual-ocaml-4.04/extn.html#sec217);儘管如此,嘗試Ocaml可能會對這些值有一些困難。 – octachron