Все реализации , представленные до сих пор в других ответах, логически несостоятельны при использовании с неосновными терминами. Рассмотрим оригинальный запрос и небольшой вариант:
?- replace(3,three,[1,2,3],Xs).
Xs = [1,2,three] ; % OK: correct
false
?- A=3, replace(A,B,[1,2,3],Xs). % OK: correct
Xs = [1,2,B], A = 3 ;
false
Это работает! Давайте зададим несколько очень похожих запросов:
?- replace(A,B,[1,2,3],Xs). % FAIL: should succeed more than once...
Xs = [B,2,3], A = 1 ; % ... but the other solutions are missing
false
?- replace(A,B,[1,2,3],Xs), A=3. % FAIL: this query _should_ succeed ...
false % ... it does not!
Что происходит? Положите вину на мета-логических встроенных (!)/0
и (\=)/2
, которые очень сложны в использовании правильно и часто делает код хрупким, нечистым и логически необоснованным.
Для сохранения логической обоснованности , придерживайтесь логической чистоты и воздержитесь от мета-логических «особенностей», когда это возможно! К счастью, большинство реализаций Пролога поддерживают dif/2
как логическую альтернативу (\=)/2
. Давайте использовать это:
% code by @svick, modified to use dif/2 instead of (\=)/2
replaceP(_, _, [], []).
replaceP(O, R, [O|T], [R|T2]) :- replaceP(O, R, T, T2).
replaceP(O, R, [H|T], [H|T2]) :- dif(H,O), replaceP(O, R, T, T2).
Давайте снова запустим вышеуказанные запросы, на этот раз с улучшенным replaceP/4
:
?- replaceP(3,three,[1,2,3],Xs).
Xs = [1,2,three] ; % OK: correct, like before
false
?- replaceP(A,B,[1,2,3],Xs). % OK: four solutions, not just one
Xs = [B,2,3], A = 1 ;
Xs = [1,B,3], A = 2 ;
Xs = [1,2,B], A = 3 ;
Xs = [1,2,3], dif(A,1),dif(A,2),dif(A,3) ;
false
?- replaceP(A,B,[1,2,3],Xs), A=3. % OK (succeeds now)
Xs = [1,2,B], A = 3 ;
false
?- A=3, replaceP(A,B,[1,2,3],Xs). % OK (same as before)
Xs = [1,2,B], A = 3 ;
false