我想在递归记录类型的记录中递归搜索字段值。搜索递归记录类型OCaml
我的记录类型是
type node = {node_name:string; node_branch:node list}
首先,我想只是遍历树像这种类型的变量:
let tree = {node_name="trunk"; node_branch=[{node_name="branch1L:1"; node_branch=[{node_name="branch2L:1"; node_branch=[]};
{node_name="foo_node"; node_branch=[]};];};
{node_name="branch1L:2"; node_branch=[]}];}
in
let target = "foo_node" in
print_newline();
search_tree_for_name target tree;
的想法是,它是一种像这样:
trunk
__________|_________
| |
branch1L:1 branch1L:2
______|_______
| |
branch2:1 foo_node
所以我正在寻找一个字段值为node_name = foo_node
的记录。我走过的方式,只是为了证明我的逻辑是:
let rec search_tree_for_name target_name in_tree =
if in_tree.node_name = target_name then
(* First check the node_name *)
Format.printf "[%s] Target node_name found\n" in_tree.node_name
else
(* Then evaluate the branches *)
begin
match in_tree.node_branch with
| [] ->
Format.printf "[%s] Branches: 0; End of branch\n" in_tree.node_name
| head :: tail ->
Format.printf "[%s] Branches: %i\n" in_tree.node_name (List.length in_tree.node_branch);
search_tree_for_name target_name head;
List.iter (search_tree_for_name target_name) tail;
end
这会打印出:
[trunk] Branches: 2
[branch1L:1] Branches: 2
[branch2L:1] Branches: 0; End of branch
[foo_node] Target node_name found
[branch1L:2] Branches: 0; End of branch
现在,我真正想要的是只是看一个实例存在,其中node_name
是我在找什么,所以我只想返回一个布尔值。
我试过了(我创建只是用于测试的新功能):
let rec check_tree_for_name target_name in_tree =
if in_tree.node_name = target_name then
begin
(* First check the node_name *)
Format.printf "[%s] Target node_name found\n" in_tree.node_name;
true
end
else
(* Then evaluate the branches *)
begin
match in_tree.node_branch with
| [] ->
Format.printf "[%s] Branches: 0; End of branch\n" in_tree.node_name;
false
| head :: tail ->
Format.printf "[%s] Branches: %i\n" in_tree.node_name (List.length in_tree.node_branch);
check_tree_for_name target_name head;
List.iter (check_tree_for_name target_name) tail;
end
我让我的函数如下错误我传递给List.iter
:
Error: This expression has type node -> bool
but an expression was expected of type node -> unit
Type bool is not compatible with type unit
然后我将最后一个模式匹配块更改为
| head :: tail ->
Format.printf "[%s] Branches: %i\n" in_tree.node_name (List.length in_tree.node_branch);
if check_tree_for_name target_name head then true
else List.iter (check_tree_for_name target_name) tail;
因此if条件检查函数调用的返回值以及传递它的种类。现在我有一个更少的错误,但我仍然有同样的错误。
我的理解是,List.iter
会传递传递列表的每个元素作为传递给List.iter
的函数的最后一个参数。所以这应该遍历我传递给它的列表中的元素,并且唯一的出路是如果node_name
字段与我正在查找的字段匹配,或者它是空列表。
我在两个实现之间看到的主要区别是第一个继续进行,直到所有节点都被评估,第二个实现继续下去,直到找到我要找的东西。
任何建议,将不胜感激,如果可能的话,一个简短的解释,我哪里出错或至少强调我要去哪里错了(我觉得我拿起很多功能编程概念,但仍然有一些这是逃避我)。
Lhooq的答案是正确的,但我也想指出,你所寻求的功能实际上是一个单行:'让rec检查名称树= tree.name = name || List.exists(检查名称)tree.branches'(名称缩短以适合评论) –
@AndreasRossberg谢谢你,很高兴看到更多地方做事 – Jesse