Recursion 在Prolog中查找每个X列表的程序

Recursion 在Prolog中查找每个X列表的程序,recursion,prolog,runtime-error,prolog-dif,Recursion,Prolog,Runtime Error,Prolog Dif,我开始学习序言。此程序尝试获取给定元素的所有引用: occurences(_, [], Res):- Res is []. occurences(X, [X|T], Res):- occurences(X,T,TMP), Res is [X,TMP]. occurences(X, [_|T], Res):- occurences(X,T,Res). 但这里有一个错误: ?- occurences(a,[a,b,c,a],Res). ERROR: is/2: Arithmeti

我开始学习序言。此程序尝试获取给定元素的所有引用:

occurences(_, [], Res):- Res is [].
occurences(X, [X|T], Res):- 
    occurences(X,T,TMP),
    Res is [X,TMP].
occurences(X, [_|T], Res):- occurences(X,T,Res).
但这里有一个错误:

?- occurences(a,[a,b,c,a],Res).
ERROR: is/2: Arithmetic: `[]/0' is not a function
^  Exception: (11) _G525 is [] ? creep
   Exception: (10) occurences(a, [], _G524) ? creep
   Exception: (9) occurences(a, [a], _G524) ? creep
   Exception: (8) occurences(a, [c, a], _G524) ? creep
   Exception: (7) occurences(a, [b, c, a], _G524) ? creep
   Exception: (6) occurences(a, [a, b, c, a], _G400) ? creep

鲁本斯已经告诉你你的错误了。我只想添加一个样式注释:在Prolog中,通常倾向于在head参数中直接编写模式:

occurences(_, [], []).
occurences(X, [X|T], [X|TMP]) :- 
    occurences(X,T,TMP), !.
occurences(X, [_|T], Res) :-
    occurences(X,T,Res).
我将第二条“输出”从
[X,TMP]
改为
[X | TMP]
,并注意到了一个问题:没有它,程序产生的结果比要求的多:

?- occurences(a,[a,b,c,a],Res).
Res = [a, a] ;
Res = [a] ;
Res = [a] ;
Res = [] ;
false.
随着削减:

?- occurences(a,[a,b,c,a],Res).
Res = [a, a].
edit@false破坏了一个讨厌的bug:这里是一个修正,使用if/then/else结构

occurences(_, [], []).
occurences(X, [Y|T], Os) :-
    (   X = Y
    ->  Os = [X|R]
    ;   Os = R
    ),
    occurences(X,T,R).

除了别人写的以外,考虑使用DIF/2约束:

occurrences(_, [], []).
occurrences(X, [X|Ls], [X|Rest]) :-
        occurrences(X, Ls, Rest).
occurrences(X, [L|Ls], Rest) :-
        dif(X, L),
        occurrences(X, Ls, Rest).
现在可以在所有方向上使用谓词,例如:

?- occurrences(X, [a,a,b], Os).
X = a,
Os = [a, a] ;
X = b,
Os = [b] ;
Os = [],
dif(X, b),
dif(X, a),
dif(X, a) ;
false.
最后一种解决方案是,如果X与
a
b
不同,则出现的列表为空。请考虑:

occurrences(_, [], []) :- !.
occurrences(X, [Y|L], R) :-
    X \== Y, !,
    occurrences(X, L, R).
occurrences(X, [Y|L], [Y|R]) :-
    occurrences(X, L, R).
测试:

?- occurrences(a,[a,b,a,c],O).
O = [a, a].

?- occurrences(a,[a,X,a,c],O).
O = [a, a].

?- occurrences(a,[a,X,a,c],[a]).
false.

?- occurrences(a,[a,X,a,c],[a,a]).
true.

+1:在保持其声明性属性的同时,使其尽可能确定的最佳方法是什么?请参考您的程序错误地成功执行
事件(a[a,b,c,a],[a])。
因此您的程序对于第三个参数不稳定。这是一个很好的例子,说明了如何不设置剪切。您的定义缺少一个模式声明或任何东西来说明它何时起作用,何时不起作用。例如,对于
事件(E,Xs,Ys)
您的定义不完整。哇,我不知道OP需要一个!除此之外,人们如何知道你的定义何时可靠,何时不可靠?