I'm reading Harper's Intro to SML and am a bit confused on reference cells. On p. 114, he gives the following example:
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
"After execution of these bindings, x is bound to 3, y is bound to 5, and z is bound to 10."
Here's my trace of his 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 is correct (3), but my y and z are both wrong (my y is 3 instead of 5 and my z is 5 instead of 10).
Where am I going wrong here?
Also, why is val _ = t := 5
necessary instead of simply t := 5
?
Thanks, bclayman
val t = r
does not set t
to 3. It sets t
to be the same reference cell that r
is.
Thus, when you do t := 5
, you set both the contents of t
and r
to 5, since both contain the same reference cell.
As for your other question, t := 5
is a function call of the function := : 'a ref * 'a -> unit
. Thus, t := 5
is an expression that evaluates to ()
.
val _ = t := 5
simply throws away the ()
and turns it into a declaration rather than an expression.
val t = r
makes t an alias for r. They both refer to the same location in the store. Thus t := 5
has the side effect of changing the contents of the memory location that r refers to as well (since t and r refer to the same place). Hence
val y = !s + !t
sets y = 0 + 5 = 5.
You are correct that val _ = t := 5
is basically the same as t := 5
, though the former suppresses output in the REPL (by discarding the value of the assignment expression).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With