1
votes

I am new to Prolog and the problem I am dealing with is the following: Given a list of variables, I want to assign a value for each element of that list, and then check if a restriction containing some of those variables is true. This is an example of how I thought it should work:

predicate(L1, Restriction) :-
    foreach(member(Var,L1), Var = 1),
    Restriction.

But when I write in the console:

? - predicate([A,B,C], A==1).

or

? - predicate([A,B,C], B==1).

or

? - predicate([A,B,C], A==B).

they all return false.

Shouldn't A, B, and C be all equivalent to 1 after the foreach loop?

2
Do keep in mind that there isn't a concept of "assignment" in prolog. It uses "unification" instead. It's an important distinction. - Enigmativity

2 Answers

1
votes

Paulo explained well what the problem is (+1). Maybe you should correct your code like

predicate(L1, Restriction) :-
    maplist(=(1), L1),
    Restriction.

that yields the expected output

?- predicate([A,B,C], A==1).
A = B, B = C, C = 1.
1
votes

The problem is the way the foreach/2 predicate works. The first argument works as a generator and the second argument works as a test for each solution of the generator. But the predicate creates a conjunction where each element is a copy of the second argument. Because of this copying, the variables in the generator never get instantiated (as you're instantiating the copies). This semantics can be illustrated by the following query:

?- foreach(member(Var, [A,B,C]), Var = 1), var(A), var(B), var(C).
true.

As your restriction is the predicate/2 calls is an equality test and a variable is not equal to an integer, all the calls fail.

If your intention is to create a list of a given length with all elements equal to a given term, there are several ways of accomplishing it. For example, using only standard built-in predicates:

?- findall(1, between(1, 3, _), List).
List = [1, 1, 1].