Search code examples
prolognested-loops

how can simulate nested loop in prolog?


how can i simulate this code in Prolog?

// L = an existing list ; 
// function foo(var X, var Y)
result = new List();
for(int i=0;i<L.length;i++)
    for(int j=0;j<L.length;j++){
        result.add(foo(L.get(i), L.get(j));
    }

Solution

  • nested loops are basically joins between sequences, and most of lists processing in Prolog is best expressed without indexing:

    ?- L=[a,b,c], findall(foo(X,Y), (member(X,L),member(Y,L)), R).
    L = [a, b, c],
    R = [foo(a, a), foo(a, b), foo(a, c), foo(b, a), foo(b, b), foo(b, c), foo(c, a), foo(c, b), foo(..., ...)].
    

    edit

    Sometime integers allow to capture the meaning in a simple way. As an example, my solution for one of the easier of Prolog context quizzes.

    icecream(N) :-
        loop(N, top(N)),
        left, loop(N+1, center), nl,
        loop(N+1, bottom(N)).
    
    :- meta_predicate loop(+, 1).
    
    loop(XH, PR) :-
        H is XH,
        forall(between(1, H, I), call(PR, I)).
    
    top(N, I) :-
        left, spc(N-I+1), pop,
        (   I > 1
        ->  pop,
            spc(2*(I-2)),
            pcl
        ;   true
        ),
        pcl, nl.
    
    bottom(N, I) :-
        left, spc(I-1), put(\), spc(2*(N-I+1)), put(/), nl.
    
    center(_) :- put(/), put(\).
    
    left :- spc(4).
    pop :- put(0'().
    pcl :- put(0')).
    spc(Ex) :- V is Ex, forall(between(1, V, _), put(0' )).
    

    Running in SWI-Prolog:

    ?- icecream(3).
           ()
          (())
         ((  ))
        /\/\/\/\
        \      /
         \    /
          \  /
           \/
    true.
    
    
    ?- forall(loop(3,[X]>>loop(2,{X}/[Y]>>writeln(X-Y))),true).
    1-1
    1-2
    2-1
    2-2
    3-1
    3-2
    true.