Как увидеть все ответы в SWI-Prolog без нажатия пробела? - PullRequest
0 голосов
/ 18 января 2019

Простой пример:

?- between(1,10,X).
X = 1 ;
X = 2 ;
X = 3 ;
X = 4 ;
X = 5 ;
X = 6 ;
X = 7 ;
X = 8 ;
X = 9 ;
X = 10.

Когда это делается с помощью SWI-Prolog с использованием REPL, чтобы увидеть следующий ответ, необходимо нажать пробел.

Как можно отобразить все результаты на экране, не нажимая пробел?


Примечание по схожему вопросу.

Если вы пришли к этому вопросу в результате поиска, и ваша реальная проблема -

Я использую SWI-Prolog и пытаюсь напечатать список, но если список имеет более 9 предметов - это выглядит так -

[1, 15, 8, 22, 5, 19, 12, 25, 3|...] 

есть ли способ показать весь список?

Тогда посмотрите эти вопросы и ответы:

SWI-Prolog - показать длинный список
SWI-Пролог, как показать весь ответ (список)?

Ответы [ 3 ]

0 голосов
/ 18 января 2019

Кодовый шаблон (Goal, false ; true) известен как отказоустойчивый цикл .

Вы также можете написать bagof( _, Goal, _). Goal может выполнять некоторую печать, которая будет появляться постепенно или порциями, если выходные данные буферизируются. Обязательно экранируйте все свободные переменные в Goal (как A^B^C^Goal).

Вы можете запустить его как файл исходного кода Prolog в командной строке или командной строке и перенаправить его вывод в команду оболочки "more".

Или вы можете просто выполнить свой запрос по приглашению Пролога и постоянно держать нажатой клавишу ;.

0 голосов
/ 18 января 2019

Учитывая (несколько) недавнее добавление библиотеки ( solution_sequence ) и, в частности, call_nth / 2, сегодня вы можете написать

?- call_nth((between(1,4,X), writeln(X)), 100).
1
2
3
4
false.

конечно, когда интересуются только первые 100 ответов. Немного контроля:

?- call_nth((between(1,4,X), writeln(X)), 2).
1
2
X = 2.

До вызова call_nth / 2 я использовал forall / 2:

?- forall(between(1,4,X), writeln(X)).
1
2
3
4
true.

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

учитывая, что call_nth и forall являются двоичными предикатами, немного синтаксического сахара может немного сократить REPL: в ~ / .swiplrc add

:- op(100, xfx, (?*)).
Gen ?* Test :- forall(Gen, Test).

:- op(1100, xfx, (?+)).
Run ?+ Count :- call_nth(Run, Count).

затем перезапустите swipl, и теперь

?- between(1,4,X) ?* (S is X*X, writeln(square_of(X):S)).
square_of(1):1
square_of(2):4
square_of(3):9
square_of(4):16
true.

?- between(1,4,X), write(X), nl ?+ 2.
1
2
X = 2.

Обратите внимание на различные приоритеты (100 против 1100) и влияние на мини DSL.

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

Расширение uDSL с помощью красивого шаблона WillNess:

:- op(1100, fx, (*)).
(* Goal) :- (Goal, false ; true).

, а затем

?- * between(1,3,N), write(N), nl.
1
2
3
true.
0 голосов
/ 18 января 2019

Решение " hackish " заключается в добавлении print(X), nl, fail к вызову. Здесь print(X) может, конечно, напечатать любую соответствующую информацию. Например between(1,10,X), print(X), nl, fail.

Это работает, поскольку print/1 [swi-doc] - это просто еще один предикат, который печатает переданный ему термин. nl/0 [swi-doc] напечатает символ новой строки, а fail/0 [swi-doc] всегда терпит неудачу .

Таким образом, мы позволяем Прологу предлагать решения, распечатывать их, печатать новую строку, и fail «активирует» механизм возврата, который будет стремиться найти другое решение, которое снова печатается и дает сбой.

В конце концов все решения печатаются, и, следовательно, вызов не выполняется. Таким образом, это дает:

?- between(1,10,X), print(X), nl, fail.
1
2
3
4
5
6
7
8
9
10
false.
...