Ocaml 如何遍历列表而不丢失元素
所以我有一个函数:Ocaml 如何遍历列表而不丢失元素,ocaml,Ocaml,所以我有一个函数: let rec add_rules start rules prod = match rules with | [] -> prod | nonterm::lst -> if ((fst nonterm) = start) then add_rules start (List.remove_assoc (fst non
let rec add_rules start rules prod =
match rules with
| [] -> prod
| nonterm::lst -> if ((fst nonterm) = start)
then add_rules start (List.remove_assoc
(fst nonterm) rules) (nonterm::prod)
else if (check_sym (fst nonterm) prod)
then add_rules start (List.remove_assoc
(fst nonterm) rules) (nonterm::prod)
else add_rules start lst prod
它需要一个名为start
的元素,一个名为rules
的成对列表,其中(x,[y])
和x
是一个元素,y
是一个列表,还有一个空列表prod
我基本上希望它遍历对列表(规则
),并将某些元素添加到空列表prod
,而不需要对该函数的细节做太多的详细说明
问题:在前两个if/else if语句中,我的代码成功删除了与(fst nonterm)
对应的对,并将整个原始列表(减去(fst nonterm)
)传递回递归函数。然而,在最后一条else语句中,我通过调用原始规则
列表的尾部递归遍历列表,将其传递给函数,因此无法再次访问这些头部
有什么办法可以避免吗?或者有没有什么方法可以让我在每次都不去掉头部的情况下遍历列表
提前谢谢你 是的,您需要为此引入一个额外的参数,正如@coredump所建议的那样。
因此,您将得到一个累加器
prod
,它将包含您正在构建的结果,一个要处理的规则队列,该队列的大小随着递归的每一步而减小(在您的版本中当前命名为rules
),以及将包含所有规则的rules
(对您显式删除的规则进行模化).是的,您需要为此引入一个额外的参数,正如@coredump所建议的那样。
因此,您将得到一个累加器
prod
,它将包含您正在构建的结果,一个要处理的规则队列,该队列的大小随着递归的每一步而减小(在您的版本中当前命名为rules
),以及将包含所有规则的rules
(对您显式删除的规则进行模化).这看起来不像Lisp,而是某种ML变体。添加参数?您的问题不清楚。首先,根据定义,“整个原始列表减去fst nonterm
”不包含nonterm
,即列表的头部:即使在前两种情况下,您也会将列表的尾部传递给递归调用(充其量,假设规则中没有重复项)。其次,遍历列表基本上意味着获取列表的尾部,直到得到空列表为止。正如所建议的,可以向add_rules
添加一个额外的参数,该参数将在连续调用中保持不变,但您应该进一步解释一下您想要使用add_rules
的上下文,您为什么还要访问头部?递归函数的目的是将大问题分解为小问题。另外,我非常确定使用List.fold
将帮助您使代码更易于阅读和编写。(List.remove\u assoc(fst nonterm)规则)
与lst
相同,因此在所有3种情况下,您都将相同的代码传递给递归。这看起来不像Lisp,而是某种ML变体。添加一个参数?您的问题不清楚。首先,根据定义,“整个原始列表减去fst nonterm
”不包含nonterm
,即列表的头部:即使在前两种情况下,您也会将列表的尾部传递给递归调用(充其量,假设规则中没有重复项)。其次,遍历列表基本上意味着获取列表的尾部,直到得到空列表为止。正如所建议的,可以向add_rules
添加一个额外的参数,该参数将在连续调用中保持不变,但您应该进一步解释一下您想要使用add_rules
的上下文,您为什么还要访问头部?递归函数的目的是将大问题分解为小问题。另外,我非常确定使用List.fold
将帮助您使代码更易于阅读和编写。(List.remove\u assoc(fst nonterm)规则)
与lst
相同,因此在所有3种情况下,您都将相同的规则传递给递归。