尝试在 OCaml 中创建一个全局变量

Trying to create a global variable in OCaml

let generateNextAssignList (assignList : (string * bool) list) : (string * bool) list * bool = 
  let carry = ref true in
  let flag = ref true in
  let inc_bools head =
    let (var, boolean) = head in 
    if (boolean = false && !flag = true) then
      (flag := false; carry := false; (var, Bool.not boolean))
    else if (boolean = true && !flag = true) then
      (var, Bool.not boolean)
    else
      (var, boolean) in
  (List.rev (List.map inc_bools (List.rev assignList)), !carry);;

generateNextAssignList [("a", true); ("a", true); ("a", false)];;

我希望 !carry 在所有情况下都是 false,除非传递给函数的列表是 [],或者列表中每个元组中的 bool 是 true。到目前为止,当我使用该函数时,它工作正常,但 !carry 始终是 true,但在函数内部正确更新。有没有办法把它变成一个全局变量来解决这个问题?

问题是 !carry

中的元组的第一个元素之前求值
List.rev (List.map inc_bools (List.rev assignList)), !carry

如果你需要强制执行副作用的顺序,最好添加一个明确的 let:

  let result = List.rev (List.map inc_bools (List.rev assignList)) in
  result, !carry

(请注意,您的实现与规范之间存在差距:如果 assignList 中的 false 值左侧有一个值,则进位为真。)

但最好将算法一分为二来避免引用:

  • 首先将反转列表拆分为第一个假值
  • 根据第一个假值左边的元素个数计算进位
  • 创建结果列表:
let generateNextAssignList assignList =
  let rec reverse_until_first_false rev = function
    | [] -> rev, []
    | (v, false) :: q -> (v,true) :: rev, q
    | (v, true) :: q -> reverse_until_first_false ((v, false) :: rev) q
  in
  let rev, rest = reverse_until_first_false [] (List.rev assignList) in
  let carry = match rest with [] -> true | _ -> false in
  let result = List.rev_append rest rev in
  result, carry