How can I replace a list with another list that contain the variable to be replaced. for example
rep([x, d, e, z, x, z, p], [x=z, z=x, d=c], R).
R = [z, c, e, x, z, x, p]
the x to z and z doesn't change after it has been replaced.
so far I did only the one without the list
rep([], _, []).
rep(L1, H1=H2, L2) :-
rep(L1, H1, H2, L2).
rep([],_,_,[]).
rep([H|T], X1, X2, [X2|L]) :-
H=X1,
rep(T,X1,X2,L),
!.
rep([H|T],X1,X2,[H|L]) :-
rep(T,X1,X2,L).
An approach that turns connectives or predicates into truth functionals, i.e. for a connective or predicate XX of arity n, the attempt is to make a predicate XX_t of arity n+1, with the last argument from the domain {true,false}, there are severe limitations if this approach is based on the ISO standard.
One typical limitation is that these predicates cannot so easily cut away branches of (;)/2. The normal cut (!) would also affect the surrounding of (;)/2 since (;)/2 is cut transparent.
What would be needed is a local cut (sys_local_cut), which can affect cut transparent predicates locally. So I guess this is the blind spot of all this look see I have a XX_t predicate, but it leaves to many choice points.
The problem is that local cut (sys_local_cut) is not in the ISO standard. But I guess if the developers of XX_t connnectiveswould have such means that would reach the same choice point behaviour as the original XX connnectives.
Bye
Let's improve this answer by moving the "recursive part" into meta-predicate
find_first_in_t/4
:To fill in the "missing bits and pieces", we define
key_pair_t/3
:Based on
find_first_in_t/4
andkey_pair_t/3
, we can writeassoc_key_mapped/3
like this:So, does the OP's use-case still work?
Building on
find_first_in_t/4
I find your code rather confused. For one thing, you have
rep/3
andrep/4
, but none of them have a list in the second position where you're passing the list of variable bindings.H1=H2
cannot possibly match a list, and that's the onlyrep/3
clause that examines the second argument. If this is a class assignment, it looks like you're a little bit behind and I'd suggest you spend some time on the previous material.The solution is simpler than you'd think:
We're using
member/2
to find a "variable binding" in the list (in quotes because these are atoms and not true Prolog variables). If it's in the list, Y is the replacement, otherwise we keep using X. And you see this has the desired effect:This could be made somewhat more efficient using "or" directly (and save us a choice point):
See:
If you use SWI-Prolog, with module lambda.pl found there : http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl you can write :
You should attempt to keep the code simpler than possible:
Of course, note the idiomatic way (thru memberchk/2) to check for a variable value.
Still yet a more idiomatic way to do: transforming lists it's a basic building block in several languages, and Prolog is no exception:
Here's how you could proceed using
if_/3
and(=)/3
.First, we try to find a single
Key
in a list of pairsK-V
. An extra argument reifies search success.Next, we need to handle "not found" cases:
Last, we put it all together using the meta-predicate
maplist/3
: