Ссылка на ссылку в SML - PullRequest
       8

Ссылка на ссылку в SML

0 голосов
/ 06 июня 2018

Я изучал ссылки в 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).но по какой-то причине это не работает.В чем проблема?

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

Как предполагает Андреас Россберг, val f = fn r => !r := 7 может быть одним из способов обновления int int ref ref до 7. Но вместо 7 вы можете написать что угодно.Если вместо этого вы хотите увеличить в два раза значение int , на которое косвенно указывает гибрид, между вашей попыткой и предложением Андреаса может быть

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

Здесь !r := ... означает«разыменование r для получения int ref , на которое он указывает, и обновление этого int ref так, чтобы оно вместо этого указывало на ...», а !(!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.
0 голосов
/ 06 июня 2018

Обновление y для указания новой ссылки не обновляет x.Во время вызова f создается новая ссылка, назовем ее z.Перед звонком у нас есть:

x -> 5
y -> x

, где -> - это «указывает на».После вызова это:

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

Редактировать: Одним из возможных способов обновления x является определение f следующим образом:

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

При вызове fy обновляется ссылка указал у, который равен х.Но является ли это «правильным» решением, зависит от того, чего вы на самом деле хотите достичь.

...