问题
I am trying to write a simple prolog program which should replace an atom by another atom. The program can take complex functor as an input and would replace all the atoms by another atoms.
e.g. In the below term, I want to replace atom a by ax only where I encounter a leaf (i.e. not a functor name).
replace(put(a,table,aside(a(dont,replace),a)),X).
which should produce output,
X = put(ax,table,aside(a(dont,replace),ax));
false.
In the above output, replaced a with ax everywhere except the functor name. In a way all the leaves are replaced. But not internal nodes.
I have tried following,
replace([],[]).
replace([H | T], [H1 | T1]):-
(
atom(H), (H == a) %If it's an atom and equal to a, then replace H1 with ax.
-> H1 = ax, replace(T, T1) %and recursively follow the same for T.
; H1 = H, T1 = T, replace(T, T1) %else keep things as it is and recurse.
).
replace(L, R):-
functor(L, F1, A1), %if it's a functor then don't do anything, just follow
functor(R, F1, A1), %for the args of the functor.
L =.. [F1 | Args1],
R =.. [F1 | Args2],
replace(Args1, Args2),!.
Problem 1. I receive shallow output for the same input
replace(put(a,table,aside(ad,a,toe)),X).
X = put(ax,table,aside(ad,a,toe)).
Problem 2. My predicate would fail when arity of the functor changes. For example,
replace(put(a,table,aside(a(dont,replace),a)),X).
Undefined predicate: substit/2
I realize my approach might not be the best one. Can someone please help me either fix the issues or suggest a new approach.
Thanks.
回答1:
can be done more generally in simpler way
replace(X,Y,X,Y) :- !.
replace(X,Y,S,R) :-
S =.. [F|As], maplist(replace(X,Y),As,Rs), R =.. [F|Rs], !.
replace(_,_,U,U).
similarly, your code should be simplified a lot
replace([],[]).
replace([H | T], [H1 | T1]):-
( H == a
-> H1 = ax
; replace(H, H1)
),
replace(T, T1).
replace(L, R):-
L =.. [F1 | Args1],
replace(Args1, Args2),
R =.. [F1 | Args2].
now
?- replace(put(a,table,aside(a(dont,replace),a)),X).
X = put(ax, table, aside(a(dont, replace), ax))
?- replace(put(a,table,aside(a(dont,replace),a)),X).
X = put(ax, table, aside(a(dont, replace), ax))
来源:https://stackoverflow.com/questions/20021844/prolog-replace-an-atom-by-other-atom-in-compound-terms