Reputation: 354
I am new to prolog, and I have built the following sample function:
bar(Fruit) :-
Fruit = fruit(apple, X),
A is abs(X) + 0,
between(0,10,A).
foo(L) :-
findall(X, bar(fruit(apple, X)), L).
Calling foo(L)
gives the error : ERROR: is/2: Arguments are not sufficiently instantiated
.
Now, I've read around multiple threads in which the recurring solution is to use clpfd
where A #= abs(X) + 0
. However, when using that solution I do not necessarily get the list I want :
L = [0, _G9407, _G9410, _G9413, _G9416, _G9419, _G9422, _G9425, _G9428|...],
clpfd:in(_G9407, -1\/1),
clpfd:in(_G9410, -2\/2),
clpfd:in(_G9413, -3\/3),
clpfd:in(_G9416, -4\/4),
clpfd:in(_G9419, -5\/5),
clpfd:in(_G9422, -6\/6),
clpfd:in(_G9425, -7\/7),
clpfd:in(_G9428, -8\/8),
clpfd:in(_G9431, -9\/9),
clpfd:in(_G9434, -10\/10).
Especially when using a more complex function it becomes very hard to read as well.. The output I was expecting is essentially a clear and simple list : [-10...10]
. Is there any alternative to this without clpfd? I have also learned through the process that I get the similar errors using logical operators such as <, >, >=, =<
which pushes me to use between
. I am coming from an OOP background, and I have a hard time grasping what the logical flaw is..
Thanks for the help,
Upvotes: 1
Views: 192
Reputation: 1394
Prolog is mostly relational in the sense that you can often calculate in both directions, but not with maths. is/2
requires that the RHS is a value (no uninstantiated variables). And you cannot use abs(X)
to get both +X and -X, which is what you seem to expect. + 0
is not useful, but I guess you have just simplified from something else.
This works:
bar(Fruit) :-
Fruit = fruit(apple, X),
between(0,5,A),
( X = A ; X is -A ).
giving
?- foo(L).
L = [0, 0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5].
But it sounds like you may want to use CLP(FD) for what you want to do.
Upvotes: 1