【发布时间】:2017-09-09 22:48:13
【问题描述】:
我正在尝试在递归记录类型的记录中递归搜索字段值。
我的记录类型是
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 的回答是对的,但我还想指出,您寻求的功能确实是单行的:
let rec check name tree = tree.name = name || List.exists (check name) tree.branches(名称缩短以适合评论) -
@AndreasRossberg 谢谢你,很高兴看到更多惯用的做事方式
标签: list recursion ocaml record