В чем разница между количеством /3 и /3 в прологе?

В чем разница между количеством /3 и /3 в прологе? а как использовать цикл for с декрементом -1 вроде (для (I, 9,0, -1))?

  • например:

    Dec = -2, Min_bound = 0, Max_bound = 9
    Результат => 9,7,5,3,1

2 ответа

Решение

В чем разница между количеством /3 и /3 в Прологе (ECLiPSe/SICStus)?

Разница заключается в "режиме", то есть используется ли аргумент Max в качестве входных данных (+) или выходных (-).

  • Шаблон для (-I,+Min,+Max) используется для управления количеством итераций цикла. Значение Max должно быть известно во время запуска цикла, т. Е. Оно может быть числом

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

    или это может быть выражение с созданными переменными

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

    Условие завершения: I >= Макс.

  • Количество шаблонов (-I,+From,-To) используется для подсчета количества итераций. В то время, когда вы запускаете цикл, To обычно будет неопределенной переменной, которая в конце цикла объединяется с числом итераций цикла. В такой настройке количество итераций должно контролироваться чем-то другим, например, длиной списка, как в этом примере:

    ?- ( 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)
    
  • Поскольку Пролог, конечно, позволяет вам использовать значение вместо необоснованной переменной, вы можете использовать количество шаблонов (-I, + From, + To), но вы должны знать, что условие завершения - I = To, а не I >= К

Конструкция do-loop, к которой относятся итераторы for/3 и count/3, является попыткой обеспечить компактную запись для общего случая итеративной рекурсии и сделать это способом, напоминающим нотацию процедурного цикла. Уникальные свойства логических переменных и в целом двунаправленный характер Prolog приводят к некоторым интересным особенностям, например, используя итератор foreach/2, вы можете использовать один и тот же код цикла для обхода существующего списка или для создания нового списка. В данном случае итерации по числам эта симметрия, к сожалению, не достигается, поэтому вам нужны два разных итератора.

Как использовать цикл for с декрементацией

Ничего особенного, правда:

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

или, для сбора результатов в списке:

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

Редактировать: было отмечено, что вышеупомянутое не работает в SICStus (4.3.2), потому что итератор for/4 не поддерживается. Вы все еще можете делать такие циклы, используя универсальный итератор fromto/4, но вы должны сделать некоторую арифметику самостоятельно, например

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

В общем случае это немного сложно, так что вы можете получить более понятный код, используя рекурсивное решение...

Во-первых, ваш вопрос о do-loop, управляющей конструкции, которая встречается в некоторых системах. Текущая реализация в SICStus имеет довольно хаотичное поведение - особенно count:

| ?- for(I,5,1), foreach(I,List) do true.
List = [] ? ;
no
| ?- count(I,5,1), foreach(I,List) do true.
**LOOPS**

В документации не ясно об этом цикле. Но из того, что я думаю, count всегда будет считать вверх и ожидает, что Max ценность законна; а если нет, то он зацикливается.

В любом случае, в do-циклах слишком много таких "функций", которые все еще не исправлены на протяжении многих лет, поэтому вам может понадобиться сначала изучить Prolog без do-циклов. В частности, рассмотрим конструкции высшего порядка, такие как maplist/2.. вместо.

Другие вопросы по тегам