Prolog meta-predicates: applying a predicate to lists, passing a constant
Assume that you want a predicate that replaces Number1 with Number2 in a list.
Of course it is trivial to write a recursive function for that, like:replace(_,_,[],[]).
replace(N1,N2,[N1|T], [N2|NT]):-
replace(N1,N2,T,NT).
replace(N1,N2,[H|T],[H|NT]):-
replace(N1,N2,T,NT).
My question is if there is a way to do that with maplist/x (or similar meta-predicates).
One might use global variables to do that, like:replace(N1,N2,L1,L2):-
nb_setval(numbers,[N1,N2]),
maplist(replace_in,L1,L2).
replace_in(N1,N2):-
nb_getval(numbers,[N1,N2]).
replace_in(X,X).
Another idea is to create a list of the same numbers List_of_N1 and List_of_N2 and pass them to maplist/4.
None of them look attr开发者_运维百科active to me, any ideas?As an aside: With your given definition, consider for example the apparently unintended second solution in:
?- replace(1, 4, [1,2,3], Ls).
Ls = [4, 2, 3] ;
Ls = [1, 2, 3] ;
false.
As to the actual question, consider:
replace(A, B, X, Y) :- ( X == A -> Y = B ; Y = X ).
Example query:
?- maplist(replace(1,4), [1,2,3], Ls).
Ls = [4, 2, 3].
For logical-purity, I recommend a truly relational version which can be used in all directions:
replacement(A, B, A, B).
replacement(A, _, X, X) :- dif(A, X).
Example:
?- maplist(replacement(a,b), [X], Rs).
Rs = [b],
X = a ;
Rs = [X],
dif(X, a).
How about this:
replace(N1,N2,L1,L2):-
maplist(replace_in,[N1-N2-T|T], L1,L2).
replace_in(N1-N2-T, X, Y):-
(X=N1 -> Y=N2 ; Y=X),
(T=[N1-N2-L|L] ; T=[]).
精彩评论