Ответ 1
-
Решение:
member(X, [Y|T]) :- X = Y; member(X, T).
-
Демонстрация:
?- member(a, []). fail. ?- member(a, [a]). true ; fail. ?- member(a, [b]). fail. ?- member(a, [1, 2, 3, a, 5, 6, a]). true ; true ; fail.
-
Как это работает:
- Мы ищем появление первого аргумента
X
во втором аргументе[Y|T]
. - Второй аргумент считается списком.
Y
соответствует своей голове,T
соответствует хвосту. - В результате предикат терпит неудачу для пустого списка (как и должно быть).
- Если
X = Y
(т.е.X
можно объединить сY
), то мы нашлиX
в списке. В противном случае (;
) мы проверяем, находится лиX
в хвосте.
- Мы ищем появление первого аргумента
-
Примечания:
- Благодаря скромному кофе, указав, что использование
=
(унификация) дает более гибкий код, чем использование==
(тестирование для равенства). -
Этот код также можно использовать для перечисления элементов данного списка:
?- member(X, [a, b]). X = a ; X = b ; fail.
-
И его можно использовать для "перечисления" всех списков, содержащих данный элемент:
?- member(a, X). X = [a|_G246] ; X = [_G245, a|_G249] ; X = [_G245, _G248, a|_G252] ; ...
-
Замена
=
на==
в приведенном выше коде делает его намного менее гибким: он немедленно завершится с ошибкойmember(X, [a])
и вызовет переполнение стека наmember(a, X)
(проверено с помощью SWI-Prolog версии 5.6 0,57).
- Благодаря скромному кофе, указав, что использование