我想写谓词,它可以计算所有遇到的数字:
count(1, [1,0,0,1,0], X).
X = 2.
Run Code Online (Sandbox Code Playgroud)
我试着把它写成:
count(_, [], 0).
count(Num, [H|T], X) :- count(Num, T, X1), Num = H, X is X1 + 1.
Run Code Online (Sandbox Code Playgroud)
为什么不工作呢?
为什么不工作呢?
Prolog是一种编程语言,通常可以直接回答这个问题.看看我如何从失败的查询开始尝试你的定义:
?- count(1, [1,0,0,1,0], X).
false.
?- count(1, Xs, X).
Xs = [],
X = 0 ;
Xs = [1],
X = 1 ;
Xs = [1, 1],
X = 2 ;
Xs = [1, 1, 1],
X = 3 ...
?- Xs = [_,_,_], count(1, Xs, X).
Xs = [1, 1, 1],
X = 3 ;
false.
Run Code Online (Sandbox Code Playgroud)
所以首先我意识到查询根本不起作用,然后我推广了查询.我用一个变量替换了大名单Xs
并说:Prolog,为我填补空白!而Prolog做到了这一点,并准确地向我们揭示了它将成功的案例.
实际上,它仅仅以1的列表成功.这很奇怪.您的定义太受限制 - 它正确计算列表中的1,其中只有1,但所有其他列表都被拒绝.@coder向您展示了如何扩展您的定义.
这是另一个library(reif)
用于
SICStus | SWI.或者,请参阅tfilter/3
.
count(X, Xs, N) :-
tfilter(=(X), Xs, Ys),
length(Ys, N).
Run Code Online (Sandbox Code Playgroud)
定义更符合其他定义的风格:
count(_, [], 0).
count(E, [X|Xs], N0) :-
if_(E = X, C = 1, C = 0),
count(E, Xs, N1),
N0 is N1+C.
Run Code Online (Sandbox Code Playgroud)
现在用于更一般的用途:
四元素列表如何看起来有3倍1?
| ?- length(L, 4), count(1, L, 3).
L = [1,1,1,_A],
dif(1,_A)
; L = [1,1,_A,1],
dif(1,_A)
; L = [1,_A,1,1],
dif(1,_A)
; L = [_A,1,1,1],
dif(1,_A)
; false.
Run Code Online (Sandbox Code Playgroud)
所以剩下的元素必须与之不同1
.
这是Prolog为我们提供的优良通用性.