mohammad
mohammad

Reputation: 490

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));
    }

Upvotes: 3

Views: 2814

Answers (3)

Ans Piter
Ans Piter

Reputation: 573

you can use this predicate using SICStus-prolog for looping variables I,J until N and get all of them inside fact foo/2 mentioned below successively ;

Code

loop(N) :- for(I,0,N),param(N) do
               for(J,0,N),param(I) do 
                      write(foo(I,J)),nl.

Result

| ?- loop(2).
foo(0,0)
foo(0,1)
foo(0,2)
foo(1,0)
foo(1,1)
foo(1,2)
foo(2,0)
foo(2,1)
foo(2,2)
yes

Upvotes: 1

CapelliC
CapelliC

Reputation: 60034

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.

Upvotes: 6

Paulo Moura
Paulo Moura

Reputation: 18683

You can define a forto/4 meta-predicate easily. An example, taken from the Logtalk library loop object:

:- meta_predicate(forto(*, *, *, 0)).
forto(Count, FirstExp, LastExp, Goal) :-
    First is FirstExp,
    Last is LastExp,
    forto_aux(Count, First, Last, 1, Goal).

:- meta_predicate(forto_aux(*, *, *, *, 0)).
forto_aux(Count, First, Last, Increment, Goal) :-
    (   First =< Last ->
        \+ \+ (Count = First, call(Goal)),
        Next is First + Increment,
        forto_aux(Count, Next, Last, Increment, Goal)
    ;   true
    ).

Example goal:

?- loop::forto(I, 1, 2, loop::forto(J, 1, 3, (write(I-J), nl))).
1-1
1-2
1-3
2-1
2-2
2-3
true.

Some Prolog compilers also provide built-in or library support for "logical loops" with good expressive power. Examples are (in alphabetic order) B-Prolog, ECLiPSe, and SICStus Prolog. Check the documentation of those systems for details. If you need a portable solution across most Prolog systems, check Logtalk's library documentation. Or simply take the above examples and define your own loop meta-predicates.

Upvotes: 1

Related Questions