我试图计算一个元素出现在列表中的次数,到目前为止我已经提出了
rate(X,[H|T],N):-
X == H,
N is N+1,
rate(X,T,N).
rate(X,[_|T],N) :-
rate(X,T,N).
rate(_,[],N) :-
N is 0.
我找到了匹配的时间,没有匹配时以及到达列表末尾的时间。但是,当我测试我得到
43 ?- rate(4,[4,2,3,4,4,2],X).
ERROR: is/2: Arguments are not sufficiently instantiated
Exception: (6) frequency(4, [4, 2, 3, 4, 4, 2], _G393) ?
我错过了哪些论据?
答案 0 :(得分:4)
当且仅当X是数字时,您才能使用is/2
(如N is X
中所述)。如果X是自由变量,则不能使用is/2
。在您的第一个条款中,您有:N is N+1
。这很糟糕,因为N是一个自由变量(此时它没有值,N + 1也是如此)。
还有另一个错误。在:
rate(X,[_|T],N) :-
rate(X,T,N).
因为你只在X不是列表中的第一个元素时使用它,你应该检查这是真的!这是代码:
count(_, [], 0) :- !. /* empty list, base case */
count(X, [X|T], N) :- /* if X is in the head of the list */
count(X, T, N2), /* count on the tail (let this N2) */
N is N2 + 1. /* and N is N2 + 1 */
count(X, [Y|T], N) :-
X \= Y, /* if X is not in the head */
count(X, T, N). /* just count the rest */
答案 1 :(得分:2)
你需要使你的条款互相排斥,第二个条款将在第一个条款的任何地方成功。
关于你的错误,它是关于信息的流动。您需要在第一个子句中交换行,如下所示:
rate(X,[H|T],N):-
X == H,
rate(X,T,N1),
N is N1+1.
此更改将使您的谓词不尾递归。要进行尾递归,它需要传递 down 调用链中的信息,而不是像现在一样将其接收回来:
rate(X,[H|T],N):-
X == H,
N1 is N+1,
rate(X,T,N1).
现在您看到此处未收到最终值,但指定初始值。当我们达到基本情况时,我们得到了结果:
rate(X, [], N).
此处N
是结果。怎么回来?当我们到达底部时,使用附加参数(一个未实例化的变量)与此结果统一:
rate(X, [], N, V) :- V is N.
现在recursive子句必须适应这个变量,沿着不变向下传递给调用链。
答案 2 :(得分:1)
如果您喜欢功能风格,可以使用SWI Prolog编写:
:- use_module(library(lambda)).
rate(X,L,N) :-
foldl(\Y^V0^V1^((X = Y->V1 is V0+1; V1 = V0)), L, 0, N).