Программа, чтобы найти каждый список X в Прологе

Я начинаю изучать Пролог. Эта программа пытается получить все вхождения данного элемента:

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

3 ответа

Решение

В дополнение к тому, что написали другие, рассмотрите возможность использования ограничения 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,

Рубенс уже проинформировал вас о вашей ошибке. Я просто добавлю примечание по стилю: часто в Прологе предпочтительно напрямую кодировать шаблон в аргументах 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 испортил неприятную ошибку: здесь исправление, используя конструкцию if/then/else

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

Рассматривать:

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.
Другие вопросы по тегам