I have simplified my code down to;
findall(T,(T > 0, T < 50),List).
Why would this fail with given error.
Here is your code simplified even further:
?- T > 0.
ERROR: >/2: Arguments are not sufficiently instantiated
The "classical" comparison operations like <
and >
need all their arguments to be fully instantiated to ground terms; in particular, they cannot be unbound variables. (The same is true for the term on the right-hand-side of the is/2
operator.)
You can not use these operators as generators. Here is one illustration of a possible reason why:
?- T = 1, T > 0.
T = 1.
?- T = 0.1, T > 0.
T = 0.1.
?- T = 0.01, T > 0.
T = 0.01.
?- T = 0.001, T > 0.
T = 0.001.
The >
operator works for several different types of numbers, including floating-point numbers. If we wanted it to be a logically reasonable generator, it would have to be able to generate all the floating-point numbers it accepts in the example above. That would almost certainly not be what you want.
There are a few ways to get what you want. As you presumably want integers only, you can use the between/3
predicate provided by many Prolog systems (including SWI):
?- between(1, 49, T).
T = 1 ;
T = 2 ;
T = 3 ;
T = 4 .
?- findall(T, between(1, 49, T), List).
List = [1, 2, 3, 4, 5, 6, 7, 8, 9|...].
Another possibility is to use a constraint programming library. Here is one example session with SWI-Prolog's clpfd
library:
?- use_module(library(clpfd)).
true.
?- T #> 0, T #< 50.
T in 1..49.
Note that here, using #>
and #<
from the clpfd
library instead of <
and >
, we can actually specify these constraints even on an unbound variable. These constraints are remembered for later use, but they do not enumerate actual values for T
. You can use them in arithmetic and comparisons, and the system will sometimes reason things out correctly even though it doesn't enumerate concrete values! For example:
?- T #> 0, T #< 50, X #= T - 50, X #> 50.
false.
To get actual values, you call a specific predicate that enumerates them:
?- T #> 0, T #< 50, indomain(T).
T = 1 ;
T = 2 ;
T = 3 ;
T = 4 .
All this gives another possible solution for your problem:
?- findall(T, (T #> 0, T #< 50, indomain(T)), List).
List = [1, 2, 3, 4, 5, 6, 7, 8, 9|...].
T
never gets a value. There are easier ways to get a list of ints. – Tomas By