2015-07-19 22 views
5

Ich lese Harpers Intro zu SML und bin ein wenig verwirrt auf Referenzzellen. Auf P. 114, er das folgende Beispiel gibt:Standard-ML: Verwirrung über Referenzzellen

val r = ref 0 
val s = ref 0 
val _ = r := 3 
val x = !s + !r 
val t = r 
val _ = t := 5 
val y = !s + !r 
val z = !t !r 

„Nach der Ausführung dieser Bindungen, x bis 3 gebunden ist, wird y bis 5 gebunden ist, und Z gebunden ist, bis 10.“

Hier ist meine Spur seines Code:

val r = ref 0 //allocates storage for r and sets to 0 
val s = ref 0 //allocates storage for s and sets to 0 
val _ = r := 3 //sets r = 3 
val x = !s + !r //sets x = 0 + 3 = 3 
val t = r //sets t = 3 
val _ = t := 5 //sets t = 5 
val y = !s + !r //sets y = 0 + 3 = 3 
val z = !t !r //sets z = 5 + 3 = 8 

My x korrekt ist (3), aber meine y und z beide falsch (mein y 3 statt 5 und meine z 5 statt 10).

Wohin gehe ich hier falsch?

Auch warum ist val _ = t := 5 anstelle von einfach t := 5 erforderlich?

Danke, bclayman

Antwort

5

val t = r setzt t nicht auf 3. Es setzt t als die gleiche Referenzzelle, die r ist. Wenn Sie t := 5 tun, setzen Sie also den Inhalt von t und r auf 5, da beide dieselbe Referenzzelle enthalten. Für Ihre andere Frage ist t := 5 ein Funktionsaufruf der Funktion := : 'a ref * 'a -> unit. Daher ist t := 5 ein Ausdruck, der () auswertet.

val _ = t := 5 wirft einfach die () weg und verwandelt es in eine Deklaration statt in einen Ausdruck.

+0

Also wenn ich val t = r, und dann t: = 5, ändert sich das auch r? Das scheint sehr seltsam zu sein ... wenn ich r auf 5 ändere, würde ich erwarten, dass ich auch auf 5 umstelle. Aber nicht umgekehrt :( – bclayman

+3

* Weder * t noch r ändern sich, wenn der Ausdruck 't: = 5' ausgewertet wird. Beide bleiben Referenzen auf eine bestimmte Stelle im Speicher. Die Auswertung dieses Ausdrucks hat den Nebeneffekt, den Inhalt davon zu ändern Natürlich verweist r jetzt auf diesen neuen Wert - aber nicht, weil r selbst verändert wurde. Eine Analogie: Wenn ich auf einen Hund deute und auf genau denselben Hund ziele, sage ich diesem Hund, er solle "sitzen" "(und es tut), Sie würden auf einen sitzenden Hund zeigen - aber nicht, weil ich Sie irgendwie geändert habe. –

3

val t = r macht t ein alias für r. Sie beziehen sich beide auf den gleichen Ort im Laden. Somit hat t := 5 den Nebeneffekt, den Inhalt des Speicherplatzes zu ändern, auf den sich auch r bezieht (da t und r sich auf den gleichen Platz beziehen). Daher

val y = !s + !t 

Sätze y = 0 + 5 = 5.

Sie sind richtig, dass val _ = t := 5 ist grundsätzlich die gleiche wie t := 5, obwohl das erstere Ausgangsunterdrückt in dem REPL (durch den Wert des Zuweisungsausdruck Verwerfen).