1
votes

I'm trying to trigger backtracking on a goal but in a dynamic way, if it's possible. To better exemplify my issue let's say we have the following PROLOG code:

num(1).
num(2).
num(3).
num(4).
num(5).

Then I head to SWI-Prolog and call: num(X). This triggers backtracking looking for all solutions, by typing ; .

What I would like is to remove those facts (num(1),num(2), etc) and replace that code with something thata generates those facts dynamically. Is there any way in which I can achieve this? Someting of the sorts,maybe?

num(X):- for X in 1..5

that yields the same solutions as the code above?

As far as I know, the findall predicate returns a list, which is not what I'm looking for. I would like to backtrack through all answers and look through them using ; in the console.

2
I don't think it is a duplicate. As far as I know, findall returns a list. I want to backtrack through a set of solutions using ; in the console. Hope I explained myself well. - Ryncops
How about typing member(X,[1,2,3,4,5]). at the console. - Tomas By
@TomasBy Fabulous, thank you so much! That's it! - Ryncops
@Scott: Is this really a duplicate? - false

2 Answers

2
votes

Yes there is, and you were already very close!

:- use_module(library(clpfd)).

num(X) :-
   X in 1..5.

?- num(X).
   X in 1..5.

?- num(X), X #>3.
   X in 4..5.

?- num(X), labeling([], [X]).
   X = 1
;  X = 2
;  X = 3
;  X = 4
;  X = 5.
0
votes

SWI-Prolog has the (non-ISO) predicate between/3 for that:

num(X) :- between(1, 5, X).

You can implement the predicate (for other Prologs and for further tweaking) like this:

between2(A, A, A) :- !.  % green cut
between2(A, B, A) :- A < B.
between2(A, B, C) :-
    A < B,
    A1 is A + 1,
    between2(A1, B, C).

The signature for both between/3 and between2/3 is (+From,+To,?X). It means that the From and To must be bound and X can be either bound or not. Also note that From and To must be integers such that From <= To. (Oh, and these integers must be written using Arabic numerals with an optional plus or minus sign before. And using ASCII. Is something non-obvious still missed? And the integers must not be too large or too small, although SWI-Prolog is usually compiled with unbounded integer support, so both between(1, 100000000000000000000000000000000000000000000, X) and between2(1, 100000000000000000000000000000000000000000000, X) usually work.)