问题
I am starting on learning Prolog. This program tries to get all occurrences of a given element:
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).
But here is the error:
?- 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
回答1:
In addition to what others wrote, consider using the dif/2 constraint:
occurrences(_, [], []).
occurrences(X, [X|Ls], [X|Rest]) :-
occurrences(X, Ls, Rest).
occurrences(X, [L|Ls], Rest) :-
dif(X, L),
occurrences(X, Ls, Rest).
You can now use the predicate in all directions, for example:
?- 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.
The last solution means that the list of occurrences is empty if X is different from both a
and b
.
回答2:
you're already been advised by Rubens about your mistake. I'll just add a style note: often in Prolog it's preferred to directly code the pattern in head arguments:
occurences(_, [], []).
occurences(X, [X|T], [X|TMP]) :-
occurences(X,T,TMP), !.
occurences(X, [_|T], Res) :-
occurences(X,T,Res).
I corrected the second clause 'output' from [X,TMP]
to [X|TMP]
, and note the cut: without it the procedure yields more results than required:
?- occurences(a,[a,b,c,a],Res).
Res = [a, a] ;
Res = [a] ;
Res = [a] ;
Res = [] ;
false.
with the cut:
?- occurences(a,[a,b,c,a],Res).
Res = [a, a].
edit @false spoiled a nasty bug: here a correction, using the if/then/else construct
occurences(_, [], []).
occurences(X, [Y|T], Os) :-
( X = Y
-> Os = [X|R]
; Os = R
),
occurences(X,T,R).
回答3:
Consider:
occurrences(_, [], []) :- !.
occurrences(X, [Y|L], R) :-
X \== Y, !,
occurrences(X, L, R).
occurrences(X, [Y|L], [Y|R]) :-
occurrences(X, L, R).
Testing:
?- 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.
来源:https://stackoverflow.com/questions/13662139/program-to-find-every-list-of-x-in-prolog