Search code examples
prologincrementbacktrackingswi-prolog

Incrementing value on backtrack


how can I do increment on backtracking ... so that goal(S) receives incremented number .. every time it fails on the next run I want to get the next number

S1 is S + 1,goal(S1)

does not work, because :

?- S=0, S1 is S+1.
S = 0,
S1 = 1.

?- S=0,between(1,3,_), S1 is S+1.
S = 0,
S1 = 1 ;
S = 0,
S1 = 1 ;
S = 0,
S1 = 1.

this work

%%counting
baz(..,C) :- .... arg(...), Y is X + 1, nb_setarg(...), goal(Y), ...

foo(..C) :- ....baz(....,C)..., foo(...C).


%%counter
blah :- ....foo(....,counter(0))...

this is not working, i think cause the recursive foo() would force baz() to initialize counter(0)... but i'm good with @sligo solution above

baz(..) :- C = counter(0), ....  arg(...), Y is X + 1, nb_setarg(...), goal(Y), ...
foo(..) :- ....baz(....)..., foo(...).

Solution

  • Use non-backtrackable destructive assignment predicate nb_setarg/3:

    ?- C = counter(0), between(1, 3, _), arg(1, C, X), Y is X + 1, nb_setarg(1, C, Y).
    C = counter(1),
    X = 0,
    Y = 1 ;
    C = counter(2),
    X = 1,
    Y = 2 ;
    C = counter(3),
    X = 2,
    Y = 3.
    

    Alternatives:

    foo(C) :-
        between(1, inf, C), 
        goal(C),
        !.
    
    baz(C) :-
        C = counter(0),
        repeat,
            arg(1, C, X),
            Y is X + 1,
            nb_setarg(1, C, Y),
            goal(Y),
            !.
    
    goal(X) :-
        X > 9.
    

    Examples:

    ?- foo(C).
    C = 10.
    
    ?- baz(C).
    C = counter(10).