Search code examples
sicstus-prologeclipse-clp

what is the difference between count /3 and for/3 in prolog?


What is the difference between count/3 and for/3 in prolog ? and how to use for-loop with decrementation -1 like (for(I,9,0,-1))?

  • for example :

    Dec=-2, Min_bound=0, Max_bound=9
    Result => 9,7,5,3,1


Solution

  • What is the difference between count/3 and for/3 in Prolog (ECLiPSe/SICStus)?

    The difference is in the "mode", i.e. whether the Max argument is used as input (+) or output (-).

    • The template for(-I,+Min,+Max) is used for controlling the number of loop iterations. The value of Max must be known at the time you start the loop, i.e. it can be a number

      ?- ( for(I,1,3) do writeln(I) ).
      1
      2
      3
      

      or it can be an expression with instantiated variables

      ?- Next=4, ( for(I,1,Next-1) do writeln(I) ).
      1
      2
      3
      

      The termination condition is I >= Max.

    • The template count(-I,+From,-To) is used to count the number of iterations. At the time you start the loop, To would normally be an uninstantiated variable, which, at the end of the loop, is unified with the number of loop iterations. In such a setting, the number of iterations must be controlled by something else, e.g. the length of a list, as in this example:

      ?- ( foreach(X,[a,b,c]),count(I,1,N) do writeln(I-X) ).
      1 - a
      2 - b
      3 - c
      
      N = 3
      Yes (0.01s cpu)
      
    • Because Prolog of course allows you to use a value instead of an uninstantiated variable, you can use the template count(-I,+From,+To), but you should be aware that the termination condition is I=To, not I>=To.

    The do-loop construct, to which the for/3 and count/3 iterators belong, is an attempt to provide compact notation for the common case of iterative recursion, and to do so in a way reminiscent of procedural loop notation. The unique properties of logical variables and the generally bi-directional nature of Prolog lead to some interesting features, e.g. using the foreach/2 iterator you can use the same loop code to either traverse an existing list or to construct a new list. In the present case of iteration over numbers, this symmetry sadly isn't achieved, hence the two different iterators that you ask about.

    How to use for-loop with decrementation

    Nothing special, really:

        ?- ( for(I,9,0,-2) do writeln(I) ).
        9
        7
        5
        3
        1
        Yes (0.00s cpu)
    

    or, for collecting the results in a list:

        ?- ( for(I,9,0,-2),foreach(I,Is) do true ).
        Is = [9, 7, 5, 3, 1]
        Yes (0.00s cpu)
    

    Edit: It has been pointed out that the above does not work in SICStus (4.3.2), because the for/4 iterator is not supported. You can still do such loops using the general-purpose fromto/4 iterator, but you have to do some arithmetic yourself, e.g.

    ?- ( fromto(9,I,I1,-1) do I1 is I-2, writeln(I) ).
    9
    7
    5
    3
    1
    Yes (0.01s cpu)
    

    For the general case, this gets a bit tricky, so that you may actually get clearer code using a recursive solution...