То, что у вас есть, действительно является «правильной» реализацией. Стандартное имя для предиката, который составляет member/2
, и доступно (под этим именем) в любом Прологе, и его нужно легко найти, как только вы узнаете его имя.
Некоторые примечания к сведению. Во-первых, с классическим определением (это именно так, как в «Искусство Пролог» Стерлинг и Шапиро, р 58, и идентичны с вашими.):
member_classic(X, [X|Xs]).
member_classic(X, [Y|Ys]) :-
member_classic(X, Ys).
Если вы пытаетесь скомпилировать это, вы получите одиночные ошибки. Это связано с тем, что вы указали переменные, которые появляются только один раз в своей области: Xs
в первом разделе и Y
во втором. Это в стороне, вот что делает программа:
?- member_classic(c, [a,b,c,x]).
true ;
false.
?- member_classic(c, [c]).
true ;
false.
?- member_classic(X, [a,b,c]).
X = a ;
X = b ;
X = c ;
false.
Другими словами, с этим определением, Пролог оставит позади точки выбора, даже если совершенно очевидно, что не может быть дальнейшие решения (потому что в конец списка). Один из способов избежать этого - использовать технику, называемую «запаздыванием», как показано на рисунке SWI-Prolog library implementation of member/2
.
И еще одно: с вашей текущей постановки задачи, может быть, что это считается нежелательным поведением:
?- member_classic(a, [a,a,a]).
true ;
true ;
true ;
false.
Существует еще один предикат обычно называется member_check/2
или memberchk/2
, который делает точно, что вы написали, а именно, успех или неудачу ровно один раз:
?- memberchk(a, [a,a,a]).
true.
?- memberchk(a, [x,y,z]).
false.
это, однако, следующее поведение, когда первый аргумент является переменной, которая migh т быть нежелательно:
?- memberchk(X, [a,b,c]).
X = a. % no more solutions!
Есть допустимые варианты использования как member/2
и memberchk/2
ИМХО (но достаточно интересно, некоторые люди могли бы утверждать обратное).
Спасибо :) Ваши комментарии очень полезны. – python