Question

I am writing a Prolog predicate that takes arguments (A1, A2, L1, L2) and succeeds if all occurences of A1 within L1 have been changed to A2 in L2.

i.e.:

| ?- replace(a, b, [a], X).
X = [b]

Here's what I've written:

replace(Orig,_,[Other],[Other]) :- Other \== Orig.
replace(Orig,Repl,[Orig],[Repl]).
replace(Orig,Repl,[Other|T1],[Other|T2]) :- Other \== Orig, replace(Orig,Repl,T1,T2).
replace(Orig,Repl,[Orig|T1],[Repl|T2]) :- replace(Orig,Repl,T1,T2).

Now, this works, but seems a bit unelegant. Can there be a more elegant solution?

Thanks.

Was it helpful?

Solution 2

What about:

replace(A, B, X, Y) :- ( X == A -> Y = B ; Y = X ).

Example:

?- maplist(replace(1,x), [1,2,3], Ls).
Ls = [x, 2, 3].

It is easy to unfold the maplist/3 call into a recursive predicate if you prefer that.

OTHER TIPS

SICStus Prolog features dif/2 so you can define the relation in a pure manner like so:

replacement(A, B, X, Y) :-
   ( A = X, B = Y
   ; dif(A,X), X = Y
   ).

maplist_replacement([], [], _, _).
maplist_replacement([X|Xs], [Y|Ys], A, B) :-
   replacement(A, B, X, Y),
   maplist_replacement(Xs, Ys, A, B).
| ?- maplist_replacement([1,2,3],Ys, 1,x).
Ys = [x,2,3] ? ;
no
| ?- maplist_replacement([X,Y],[X,Y],A,B).
B = A,
X = A,
Y = A ? ;
B = A,
X = A,
prolog:dif__int(A,Y) ? ;
B = A,
Y = A,
prolog:dif__int(A,X) ? ;
prolog:dif__int(A,X),
prolog:dif__int(A,Y) ? ;
no

The last query corresponds to the question: What must A and B look like such that a two element list will remain the same? There are four answers:

  1. A, B, X, and Y are all the same.

  2. A, B, and X are the same, and Y is different.

  3. A, B, and Y are the same, and X is different.

  4. X and Y are both different to A.

In newer versions of SICStus, maplist/3 is in a library, however the definition is not entirely monotonic. For a definition of maplist/3 see Prolog map procedure that applies predicate to list elements.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top