【问题标题】:Reference to a reference in SML引用 SML 中的引用
【发布时间】:2018-06-13 01:00:47
【问题描述】:

我正在研究 SML 中的参考文献。

我写了以下代码:

let
    val f = (fn (s) => s := ref((!(!s)) + 2))
    val x = ref (5)
    val y = ref x
in
    (f y ; !x)
end;

我正在尝试访问val it = 7 : int,尽管我的程序打印了val it = 5 : int。我不明白为什么。我确定问题出在f 函数中,但不明白为什么。

我正在尝试做的事情:f 函数应该将参数y 更新为ref(ref(7)),因此x 可能是ref(7)。但由于某种原因它不起作用。有什么问题?

【问题讨论】:

    标签: reference sml


    【解决方案1】:

    更新 y 以指向新的 ref 不会更新 x。在调用 f 期间创建了一个新引用,我们称之为 z。在通话之前我们有:

    x -> 5
    y -> x
    

    其中-> 是“指向”。调用后是:

    x -> 5
    y -> z
    z -> 7
    

    编辑:实际更新 x 的一种可能方法是定义 f 如下:

    val f = fn r => !r := 7
    

    当调用 f y 时,这会将 指向的引用更新为 y,即 x。但这是否是“正确”的解决方案取决于您实际想要实现的目标。

    【讨论】:

    • 你是不是在暗示无法进行程序打印val it = 7 : int
    • 嗯,有很多方法可以让它产生 7,这取决于你想要达到什么。查看我的更新。
    【解决方案2】:

    正如 Andreas Rossberg 所建议的那样,val f = fn r => !r := 7 可能是将 int ref refint 更新为 7 的一种方法。但您可以写而不是 7任何事物。相反,如果您想将间接指向的 int 增加 2,则您的尝试和 Andreas 的建议之间的混合可能是

    fun f r = !r := !(!r) + 2
    

    这里,!r := ... 的意思是“取消引用 r 以获取它指向的 int ref,并更新该 int ref 使其指向 @987654326 @”,!(!r) + 2 表示“取消引用 r 两次以获取它间接指向的 int,并添加两个。”此时,您还没有更改r 指向的内容(就像您对s := ref ... 所做的那样),您正在使用它间接使用双重取消引用!(!r) 指向的值。

    对此的测试程序可能是:

    val x = ref 5
    val y = ref x
    fun f r = !r := !(!r) + 2
    
    fun debug str =
        print ( str ^ ": x points to " ^ Int.toString (!x) ^ " and "
              ^ "y points indirectly to " ^ Int.toString (!(!y)) ^ ".\n" )
    
    val _ = debug "before"
    val _ = f y
    val _ = debug "after"
    

    运行这个测试程序产生:

    before: x points to 5 and y points indirectly to 5.
    after: x points to 7 and y points indirectly to 7.
    

    【讨论】:

      猜你喜欢
      • 2017-10-25
      • 1970-01-01
      • 1970-01-01
      • 2018-03-19
      • 1970-01-01
      • 2020-08-06
      • 2020-08-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多