简体   繁体   English

OCaml,引用和树的意外行为

[英]OCaml, unexpected behavior with refs and trees

I was trying to assign a number to each element of a tree. 我试图为树的每个元素分配一个数字。 I thought using refs would make the task easier, but I encountered a strange behavior : the numbers assigned were not unique and no clear pattern emerged. 我以为使用refs会使任务更容易,但是我遇到了一个奇怪的行为:分配的数字不是唯一的,并且没有清晰的图案出现。 I managed to fix the bug (adding the let unboxed = !second_ref in line) but I do not understand what happened. 我设法修复了该错误( let unboxed = !second_ref in添加let unboxed = !second_ref in ),但我不知道发生了什么。

The first tree in the output console just makes sure the print_tree function outputs what it should. 输出控制台中的第一棵树仅确保print_tree函数输出其应有的内容。

However, the output expected for the second print should be exactly the same one as the third tree. 但是,第二张打印的预期输出应与第三棵树的输出完全相同。 What am I missing ? 我想念什么?

type ('a, 'b) tree =
  | Node of 'a * ('a, 'b) tree * ('a, 'b) tree
  | Leaf of 'b

let print_tree tree string_of_node string_of_leaf  =
  let rec print indent tree =
    match tree with
    | Leaf (l) -> print_string (indent^" -> "^string_of_leaf(l)^"\n")
    | Node (n, left, right) ->
      Printf.printf "%s-----------\n" indent;
      print (indent ^ "|         ") left;
      Printf.printf "%s%s\n" indent (string_of_node(n));
      print (indent ^ "|         ") right;
      Printf.printf "%s-----------\n" indent
  in print "" tree 

let myTree = Node(1,Node(2,Leaf(3),Leaf(4)),Node(5,Leaf(6),Leaf(7))) ;;

let first_ref = ref 0 ;;
let rec bug tree = 
  first_ref := !first_ref+ 1;
  match tree with
  |Leaf(a) -> Leaf(!first_ref)
  |Node(n,l,r) -> Node(!first_ref, bug l, bug r) ;;

let second_ref = ref 0 ;;
let rec bug_fixed tree = 
  second_ref := !second_ref + 1;
  let unboxed = !second_ref in
  match tree with
  |Leaf(a) -> Leaf(unboxed)
  |Node(n,l,r) -> Node(unboxed, bug_fixed l, bug_fixed r) ;;


let bug_tree = bug myTree ;;
let bug_fixed_tree = bug_fixed myTree ;;

print_tree myTree string_of_int string_of_int ;
print_tree bug_tree string_of_int string_of_int ;
print_tree bug_fixed_tree string_of_int string_of_int ;

The output is the following : 输出如下:

-----------
|         -----------
|         |          -> 3
|         2
|         |          -> 4
|         -----------
1
|         -----------
|         |          -> 6
|         5
|         |          -> 7
|         -----------
-----------
-----------
|         -----------
|         |          -> 7
|         7
|         |          -> 6
|         -----------
7
|         -----------
|         |          -> 4
|         4
|         |          -> 3
|         -----------
-----------
-----------
|         -----------
|         |          -> 7
|         5
|         |          -> 6
|         -----------
1
|         -----------
|         |          -> 4
|         2
|         |          -> 3
|         -----------
-----------

In your bug function, there's this problematic expression: 在您的bug功能中,存在以下问题:

Node(!first_ref, bug l, bug r)

Its behaviour depends on the order of evaluation of the arguments: bug l and bug r increment first_ref , so the value that is passed may not be what you want. 它的行为取决于对参数求值的顺序: bug lbug r递增first_ref ,因此传递的值可能不是您想要的。

You can force the order by doing for example: 您可以通过执行以下命令来强制下单:

let v = !first ref in
let new_l = bug l in
let new_r = bug r in
Node (v, new_l, new_r)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM