我正在阅读Harper的SML简介,对参考单元格有点困惑。在p。 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
“执行这些绑定后,x绑定到3,y绑定到5,z绑定到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
?
谢谢, bclayman
答案 0 :(得分:5)
val t = r
未将t
设置为3.它将t
设置为与r
相同的参考单元格。
因此,当您执行t := 5
时,您将t
和r
的内容都设置为5,因为两者都包含相同的参考单元格。
至于您的其他问题,t := 5
是函数:= : 'a ref * 'a -> unit
的函数调用。因此,t := 5
是一个计算结果为()
的表达式。
val _ = t := 5
只会丢弃()
并将其转换为声明而不是表达式。
答案 1 :(得分:3)
val t = r
为r创建别名。它们都指向商店中的相同位置。因此,t := 5
具有改变 r 所指的存储器位置的内容的副作用(因为t和r指的是相同的位置)。因此
val y = !s + !t
设定y = 0 + 5 = 5.
你是正确的val _ = t := 5
基本上与t := 5
相同,尽管前者抑制了REPL中的输出(通过丢弃赋值表达式的值)。