Ответ 1
Используйте if_/3
и (=)/3
(a.k.a. equal_truth/3
), как определено @false в этом ответе!
Итак, вот новый, логически чистый find/3
:
find(E0,E1,[X|Xs]) :-
member_next_prev_list(E0,E1,X,Xs).
member_next_prev_list(E0,E1,X0,[X1|Xs]) :-
if_(X0=E0, X1=E1, member_next_prev_list(E0,E1,X1,Xs)).
Пусть запускаются запросы, упомянутые OP/другими ответами/некоторыми комментариями:
?- find(a,X,[a,a,b]). X = a. % succeeds deterministically ?- find(a,X,[a,Y,b]). X = Y. % succeeds deterministically ?- find(a,b,[a,a,b]). false. % fails ?- find(a,X,[a,a,b,c]). X = a. % succeeds deterministically ?- find(b,X,[a,a,b,c]). X = c. % succeeds deterministically
Теперь что-то a little более общее:
?- find(X,Y,[a,a,b,c]). X = a, Y = a ; X = b, Y = c ; false.
Как насчет наиболее общего запроса? Поскольку код чистый, мы получаем логически звук:
?- find(X,Y,List).
List = [ X,Y|_Z] ;
List = [_A, X,Y|_Z], dif(_A,X) ;
List = [_A,_B, X,Y|_Z], dif(_A,X), dif(_B,X) ;
List = [_A,_B,_C, X,Y|_Z], dif(_A,X), dif(_B,X), dif(_C,X) ;
List = [_A,_B,_C,_D,X,Y|_Z], dif(_A,X), dif(_B,X), dif(_C,X), dif(_D,X) ...
Редактировать 2015-05-06
Здесь более краткий вариант, который невообразимо называется findB/3
:
findB(E0,E1,[X0,X1|Xs]) :- if_(X0=E0, X1=E1, findB(E0,E1,[X1|Xs])).
Подобно find/3
, findB/3
эффективен в том смысле, что не оставляет ненужных точек выбора позади, но имеет более высокую память.
findC/3
пытается уменьшить использование памяти, подняв общее выражение [X1|Xs]
:
findC(E0,E1,[X0|XXs]) :- XXs = [X1|_], if_(X0=E0, X1=E1, findC(E0,E1,XXs)).