Ocaml refs 不保留其价值

Ocaml refs not retaining its value

(* junk.ml *)
let flag = ref false

let get_flag = !flag

let play_cards card =
    Printf.printf "%s-clause\n" (if card >= 27 && card <= 39 then "true" else "false");
    (flag := if card >= 27 && card <= 39 then true else !flag);
    Printf.printf "check: %B  " get_flag;

在 utop 中,我导入了 junk.ml 并收到了这个输出

val flag : bool ref = {contents = false} val get_flag : bool = false val play_cards : int -> unit = <fun>

我调用了 play_cards 30;; 并收到了这个输出:

true-clause
check: true - : unit = ()

然而,当我调用 get_flag 时,我收到了 false。我想知道在编写这段代码时是否存在我误解的使用引用的概念。

您的变量 get_flag 在定义时是 !flag 值的不可变名称。你不应该期望它的价值会改变; OCaml 变量具有不可变的值。

(某些值,如 flag,是本身可变的事物的不可变名称。换句话说,flag 始终是同一引用的名称,但值存储在引用中,!flag,可以更改。)

您的评论表明您希望 get_flag 在不同时间具有不同的值。获得此结果的一种方法是将其定义为函数:

let get_flag () = !flag

现在您可以调用该函数,并且在每次调用时 returns 调用时 flag 的值。

# let flag = ref false 
  let get_flag () = !flag;;
val flag : bool ref = {contents = false}
val get_flag : unit -> bool = <fun>
# get_flag ();;
- : bool = false
# flag := true;;
- : unit = ()
# get_flag ();;
- : bool = true

如图所示,您的代码没有意义,hearts_brokenget_hearts_broken 从未定义。但是,如果您在其他地方进行了这些定义,那么您会看到您所看到的结果也就不足为奇了,因为 play_cards 实际上并没有像您假设的那样修改 flag

我猜你在某个时候将 hearts_broken 重命名为 flag,但忘了修复 play_cards?而这碰巧不会导致错误,因为你没有重新启动顶层,所以旧的定义仍然存在?