Reputation: 53
I am trying to write a predicate that returns 1 if a variable X
and a predicate f(X)
are both elements of an input list L
, and 0 if at least one of them is missing.
This is what the predicate is supposed to do:
?- f_in_list([X, f(X)], Val).
should return Val = 1
?- f_in_list([X, f(Y), Z], Val).
should return Val = 0, as X and Y are different variables.
I have written this simple code:
f_in_list(L, 1) :-
member(X, L),
member(f(X), L),
!.
f_in_list(_, 0).
My problem is that Prolog is always trying to unify the input variables, so it returns X = f(X)
and X = f(Y)
, respectively.
I tried to use dif(X, f(X))
in order to circumvent this issue, but even that did not work. Val
will always be 1 if the list contains at least two elements.
Is there a way to convert the variables to atoms or strings, so Prolog cannot unify the variables? Or even better, is there a way to prevent the unification of variables with the same name?
Upvotes: 5
Views: 354
Reputation: 12972
As referred by @lurker you should consider using ==/2
since it succeeds only if the two terms are already identical without further unification.
Her is my implementation:
f_in_list(L, 1) :-
member(X, L),
member(f(Y), L),
X == Y ,!.
f_in_list(_, 0).
Example:
?- f_in_list([X, f(X)], Val).
Val = 1.
?- f_in_list([X, f(Y), Z], Val).
Val = 0.
Upvotes: 2
Reputation: 58274
This could be an good use of ==/2
. This operator does not unify but it checks if its arguments are the same. Here is a little bit of ==/2
behavior:
2 ?- X == X
| .
true.
3 ?- X == Y.
false.
4 ?- X = Y, Z = Y, X == Z, write('yes'), nl.
yes
X = Y, Y = Z.
5 ?- X = Y, Z = W, X == Z.
false.
6 ?-
We can use this to create a non-unifying nu_member/2
predicate:
nu_member(X, [Y|_]) :- X == Y.
nu_member(X, [_|T]) :- nu_member(X, T).
And we an use this in f_in_list/2
:
f_in_list(L, 1) :-
member(X, L),
nu_member(f(X), L),
!.
f_in_list(_, 0).
Which results in:
2 ?- f_in_list([X,f(X), Z], B).
B = 1.
3 ?- f_in_list([X,f(Y), Z], B).
B = 0.
4 ?- f_in_list([X,f(Y), f(Z)], B).
B = 0.
5 ?- f_in_list([X,f(Y), f(Z),Z], B).
B = 1.
Upvotes: 1