Reputation: 751
I am new into the world of Prolog, and I would like to write a rule that return all the elements in a specific range.
I intend to do something like
Ex:
foo(X, Low, High) :- X > Low, X < High.
And when I type foo(X, 2, 5), it should return 3, and then 4.
It seems that my approach is wrong, and I would like to know which is the correct way to do it.
Upvotes: 4
Views: 4757
Reputation: 74277
You could also do this (pretty much a reimplementatio of between/3:
range( X , Y , Z ) :-
integer(X) ,
integer(Y) ,
range1(X,Y,Z)
.
range1( X , X , X ) . % X equals Y
range1( X , Y , X ) :- X < Y .
range1( X , Y , Z ) :- X < Y , X1 is X+1 , range( X1 , Y , Z ) .
range1( X , Y , X ) :- X > Y .
range1( X , Y , Z ) :- X > Y , X1 is X-1 , range( X1 , Y , Z ) .
Upvotes: 1
Reputation: 5675
Using SWI-Prolog and library(clpfd)
, you can write
:- use_module(library(clpfd)).
foo(X,Low,High) :-
X #> Low,
X #< High,
label([X]).
Upvotes: 2
Reputation: 5858
the easy answer: between/3
:
?- between(3,4,X).
X = 3 ;
X = 4.
implementing the exact behaviour is kinda trivial this way.
the reason that your approach doesn't work is the definition of </2
: both arguments should be instantiated. so, if you want to implement it without using between/3
you should do something like svick's suggestion.
Upvotes: 6
Reputation: 244837
When written like that, Prolog doesn't know what kind of numbers do you want (and whether you even want numbers).
One way to implement this would be:
range(X, L, H) :- X is L + 1, X < H.
range(X, L, H) :- L1 is L + 1, L1 < H, range(X, L1, H).
Upvotes: 7