我正在尝试理解累加器,所以我希望这个实现包含它们。 我已经想过如何搜索一个简单的列表。 这会计算给定元素的出现次数:
find(Element,[],A,A).
find(Element, [H|Tail], A, N) :- Element = H, A1 is A + 1,
find(Element, Tail, A1, N).
find(Element, [H|Tail], A, N) :- find(Element, Tail, A, N).
现在我怎样才能让它适用于嵌套列表呢?
答案 0 :(得分:1)
您应该只是向匹配器添加另一个项目,以便如果H
也是一个列表,则首先计算出现次数:
find(Element,[],A,A).
find(Element, [Element|Tail], A, N) :-
!,
A1 is A + 1,
find(Element, Tail, A1, N).
find(Element,[[H|T]|Tail],A,N) :-
!,
find(Element,[H|T],A,R),
find(Element,Tail,R,N).
find(Element, [H|Tail], A, N) :-
find(Element, Tail, A, N).
通过在列表递归之前放置Element
(第二个子句)的相等性,您还可以搜索列表中的列表。换句话说:
find([1,2],[[1,2],[3],4,[1,2]])
将返回2
。
您使用剪切(!
)来阻止Prolog回溯。
提示:如果可能的话,不会在正文(
Element = H
)中统一。只需在头部重用相同的变量(find(Element,[Element|Tail],A,N)
)。许多Prolog编译器能够比第一种情况更好地优化后者。
提示:使用削减。您可以更频繁地使用剪切来防止Prolog产生非确定性。例如,如果您计算
5
中[5,1,2,5]
的出现次数,则可以提出2
,1
和0
,因为您从未在最后一条中指明H
不等于至Element
。通过在前一个条款中放置一个剪辑,Prolog解释器将永远不会回溯这个。