Search code examples
prolog

Is it possible to increment/count from 0 to n without an accumulator with SWI-Prolog?


I am trying to count from 0 to N, one value returned at a time, rather than a list like with numlist/3. I believe it is possible to use recursion with two predicate statements, but I have gotten caught up on coming up with a stop condition which works in the manner I am looking for:

iterate(0,_).
iterate(X,N) :- iterate(Y,N), Y < N, X is Y + 1.

With my current understanding, the first predicate will always return 0 as the first value when calling iterate(X,N), and the second will iterate through recursive calls giving the next value.

The issue I have run into is that it correctly counts up to N, but then reaches the stack limit. I think that this is due to making the recursive call at the beginning of the predicate and checking on the return result afterwards.

The main disconnect seems to be my understanding of how Prolog deals with predicates. From what I have read, it seemed that Prolog handles the second call as follows:

iterate(Y,N) ⋀ (Y < N) ⋀ (X is Y + 1)

I thought that this would mean that when Y < N returns false, the recursive call would stop, which is not the case. At this point, I have tried a couple variations of the recursive call location in the predicate, always with the final value of X being declared at the end as it seems like that's where the value declaration must go.

I have also seen that ISO-Prolog has (;)/2 (if-then-else), but have not found anything similar which may be helpful in SWI-Prolog that could apply to this case.

Am I wrong in thinking that this is possible to do this with two predicate statements in SWI-Prolog?

Edit: I intend on doing this without an accumulator for added challenge.


Solution

  • I ended up figuring out a way to count from 0 to n without an accumulator by tweaking my initial code snippet. While David Tonhofer solved the problem stated, I would like to post my solution that solves my added challenge goal.

    iterate(0,_).
    iterate(X,N) :- iterate(Y,N), (Y < N -> X is Y + 1; !).
    

    This snipped of code allows iterate(X,N) to be called, with N being a real number and X a variable, and have X iterate through every value from 0 to N inclusively. This allows for testing every integer value from 0 to N against equations and find solutions.

    It will return the values below when iterate(X,N) is called:

    ?- iterate(X,10).
    X = 0 ;
    X = 1 ;
    X = 2 ;
    X = 3 ;
    X = 4 ;
    X = 5 ;
    X = 6 ;
    X = 7 ;
    X = 8 ;
    X = 9 ;
    X = 10 ;
    true.