2017-06-05 2 views
4

(ich benutze OCaml Version 4.02.3)Was ist <cycle> in Daten?

ich einen Typ definiert self

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

und seine Instanz s

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

Seit OCaml is a strict language, ich s erwartet die Definition in Endlosschleife fallen . Aber der Dolmetscher sagte s hat einen Wert und es ist Self <cycle>.

Ich habe auch eine Funktion auf s angewendet.

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

Es scheint s vor der Funktionsanwendung nicht ausgewertet wird (wie in nicht-strengen Sprache).

Wie OCaml mit zyklischen Daten wie s umgehen? Self <cycle> ist eine normale Form?

Antwort

4

OCaml ist in der Tat eine eifrige Sprache, aber s ist ein perfekt gültiger und vollständig ausgewerteter Begriff, der zufällig einen Zyklus enthält. Zum Beispiel ergibt dieser Code das erwartete Ergebnis:

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

genauer gesagt, der Speicherdarstellung von Konstrukteuren mit zumin n Argumente sind eingerahmt und wie folgt lauten:

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

Der Header enthält Metadaten während field[k] ist ein OCaml-Wert, dh entweder eine Ganzzahl oder ein Zeiger. Im Fall von s hat Self nur ein Argument und damit nur ein Feld field[0]. Der Wert von field[0] ist dann einfach ein Zeiger auf den Anfang des Blocks. Der Begriff s ist somit in OCaml perfekt darstellbar.

Darüber hinaus kann der Toplevel-Drucker diese Art von Zyklen erkennen und ein <cycle> drucken, um zu vermeiden, in eine unendliche Rekursion zu fallen, wenn der Wert von gedruckt wird. Hier stellt <cycle>, wie <abstr> oder <fun>, nur eine Art von Wert dar, den der Toplevel-Drucker nicht drucken kann.

Beachten Sie jedoch, wird dieser zyklische Wert unendliche Rekursion in vielen Situationen auslösen, zum Beispiel f s = s wo (=) die strukturelle Gleichheit ist und nicht die physischen (i.e. (==)) löst solche Rekursion, wäre ein weiteres Beispiel seine

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

ist ein Feature in v4.0.2 eingeführt? Mit [Try OCaml] (https://try.ocamlpro.com/) (v4.0.1) kann 's' nicht definiert werden. – letrec

+2

Das Drucken von ist nur eine Eigenschaft des Toplevel-Druckers, der in 4.02 tatsächlich eingeführt wurde (vgl. Https://caml.inria.fr/mantis/view.php?id=6228). Jedoch können zyklische Werte seit OCaml 1.0 definiert werden (siehe http://caml.inria.fr/pub/docs/manual-ocaml-4.04/extn.html#sec217); Dennoch ist es möglich, dass Try Ocaml mit solchen Werten Schwierigkeiten hat. – octachron