为什么这个引用在没有被分配新值的情况下发生了变化?

Why this reference changed without been assigned new value?

我正在使用 ocaml 4.10.0 并且有一个定义如下的函数:

type t = (string * bool) list

let test (t:t) : bool * (string * bool) list =
  match t with
  | [] -> (true,[])
  | (s,b)::[] -> (true,t)
  | _ ->
     let rb = ref true in
     let rl = ref t in
     let rec func (t':t) : unit = 
        match t' with
        | [] -> ()
        | (s,b)::tl -> 
           List.iter(
              fun (s',b') -> 
                 if ((s=s') && (b<>b')) then 
                    rb := false;
                    rl := [(s,b);(s',b')]
           ) tl;
           if (!rb<>false) then func tl;
     in func t; 
     (!rb,!rl)

如果没有不一致的 (string * bool) 对,此函数应测试 (string * bool) 和 return(true,原始列表)的列表,否则(false,不一致的对)。

例如:

test [("a",true);("b",false);("a",true)] should return (true,[("a",true);("b",false);("a",true)])

test [("a",false);("b",false);("a",true)] should return (false,[("a",false);("a",true)])

然而我现在的功能有一部分是错误的,这将return:

test [("a",true);("b",false);("a",true)] returns (true,[("b",false);("a",true)])

test [("a",false);("b",false);("a",true)] returns (false,[("a",false);("a",true)])

我不明白为什么 rl 会在未调用 if 语句时发生变化。

你有这个:

if ((s=s') && (b<>b')) then 
   rb := false;
   rl := [(s,b);(s',b')]

但是你的缩进有误导性。 then 只控制一个后面的表达式。也就是说这里的第三行一直执行

您可以使用 begin/end(或括号)将两个表达式分组到 then:

if ((s=s') && (b<>b')) then
   begin
   rb := false;
   rl := [(s,b);(s',b')]
   end

这就是一些人建议您使用自动缩进代码的系统的原因。这样你就不太可能以误导性缩进结束。