标准 ML:对参考细胞的困惑

Standard ML: Confusion about Reference Cells

我正在阅读 Harper 的 SML 简介,对参考单元有点困惑。在第114,他举了下面的例子:

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."

这是我对他的代码的跟踪:

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

我的 x 是正确的 (3),但我的 y 和 z 都是错误的(我的 y 是 3 而不是 5,我的 z 是 5 而不是 10)。

我哪里错了?

此外,为什么需要 val _ = t := 5 而不是简单的 t := 5

谢谢, 克莱曼

val t = r 使 t 成为 r 的 别名 。它们都指的是商店中的相同位置。因此 t := 5 具有改变 r 所指的内存位置内容的副作用(因为 t 和 r 指的是同一个地方)。因此

val y = !s + !t

设置 y = 0 + 5 = 5。

你是对的 val _ = t := 5t := 5 基本相同,尽管前者抑制了 REPL 中的输出(通过丢弃赋值表达式的值)。

val t = r 不会将 t 设置为 3。它将 t 设置为与 r 相同的参考单元格。

因此,当您执行 t := 5 时,您将 tr 的内容都设置为 5,因为它们包含相同的引用单元格。

关于你的另一个问题,t := 5是函数:= : 'a ref * 'a -> unit的函数调用。因此,t := 5 是一个计算结果为 ().

的表达式

val _ = t := 5 简单地丢弃了 () 并将其变成声明而不是表达式。