2016-02-02 1 views
3

как я могу имитировать этот код в 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)); 
    } 
+0

Пожалуйста, объясните, что именно вы пытаетесь для того чтобы достигнуть, а также то, что вы уже пробовали. :) – Reflic

+0

И почему вы пытаетесь сделать императивное программирование на языке логического программирования? – Enigmativity

ответ

2

Вы можете легко определить мета-предикат forto/4. Пример, взятый из Logtalk библиотеки loop объекта:

:- 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 
    ). 

Примера Цель:

?- 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. 

Некоторых компиляторы Prolog также обеспечивает встроенную поддержку или библиотеку для «логических петель» с хорошей выразительной силой. Примеры (в алфавитном порядке) B-Prolog, ECLiPSe и SICStus Prolog. Для получения подробной информации обратитесь к документации этих систем. Если вам требуется переносное решение для большинства систем Prolog, проверьте документацию библиотеки Logtalk. Или просто возьмите приведенные выше примеры и определите свои собственные мета-предикаты.

5

вложенных циклов, в основном соединения между последовательностями, и большинство обработки списков в Прологе лучше всего выражается без индексации:

?- 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(..., ...)]. 

редактировать

Когда-то целые числа позволяют захватывать смысл простым способом , В качестве примера, мое решение для одного из более простых викторинов в Prolog.

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')). 

Запуск в SWI-Прологе:

?- 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. 
+1

Полное неуважение к людям, которые цепляются за компьютер, пытаясь избежать посещения холодильника! Но, возможно, это низкий уровень жира. Хороший пример :-) –

+0

без сахара, действительно :) – CapelliC

2

вы можете использовать этот предикат, используя SICStus-пролог для перекручивания переменных I,J до N и получить все из них в самом деле foo/2 нижеперечисленных последовательно;

Код

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

Результат

| ?- 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 
+0

Почему вызов предиката '= ../2' (aka univ) вместо просто' write (f (I, J)) '? –

+0

Кроме того, петли SICStus Prolog происходят из ECLiPSe. Таким образом, ваш пример должен также работать с ECLiPSe as-is. –

+0

@Paulo Moura Я думаю, что он может влиять на переменные I и J в фактах с помощью 'result.add (foo (L.get (i), L.get (j))' –