?- ку6( 5, Y).
Y = 125
?-  куб( 12, Z).
Z = 1728
Для получения каждого результата нам придется набирать соответствующую цель. Давайте теперь изменим эту программу так, чтобы процедура куб сама читала соответствующие данные. Теперь программа будет сама читать данные и выводить их кубы до тех пор, пока не будет прочитан атом стоп:
куб :-
 read( X),
 обработать( X).
обработать( стоп) :- !.
обработать( N) :-
 С is N * N * N,
 write( С),
 куб.
Это был пример программы, декларативный смысл которой трудно сформулировать. В то же время ее процедурный смысл совершенно ясен: чтобы вычислить куб, сначала нужно считать X, а затем его обработать; если X = стоп, то все сделано, иначе вывести X³ и рекурсивно запустить процедуру куб для обработки остальных чисел.
С помощью этой новой процедуры таблица кубов чисел может быть получена таким образом:
?- куб.
2.
8
5.
125
12.
1728
стоп.
yes
Числа 2, 5 и 12 были введены пользователем с терминала, остальные числа были выведены программой. Заметьте, что после каждого числа, введенного пользователем, должна стоять точка, которая сигнализирует о конце терма.
Может показаться, что приведённую процедуру куб можно упростить. Однако следующая попытка такого упрощения является ошибочной:
куб :-
 read( стоп), !.
куб :-
 read( N),
 С is N * N * N,
 write( С),
 куб.
Причина, по которой эта процедура работает неправильно, станет очевидной, если проследить, какие действия она выполняет с входным аргументом, скажем с числом 5. Цель read( стоп) потерпит неудачу при чтении этого числа, и оно будет потеряно навсегда. Следующая цель read введет следующий терм. С другой стороны может случиться, что сигнал стоп будет считан целью read( N), что приведет к попытке перемножить нечисловую информацию.
Процедура куб ведет диалог между пользователем и программой. В таких случаях обычно желательно, чтобы программа перед тем, как читать с терминала новые данные, дала сигнал пользователю о том, что она готова к приему информации, а также, возможно, и о том, какого вида информация ожидается. Это делается обычно путем выдачи 'приглашения' перед чтением. Нашу процедуру куб можно для этого изменить, например, так:
куб :-
 write( 'Следующее число, пожалуйста:'),
 read( X),
 обработать( X).
обработать( стоп) :- !.
обработать( N) :-
 С is N * N * N,
 write( 'Куб'), write( N), write( 'равен'),
 write( С), nl,
 куб.
Разговор с новой версией мог бы быть, например, таким:
?- куб.
Следующее число, пожалуйста: 5.
Куб 5 равен 125
Следующее число, пожалуйста: 12.
Куб 12 равен 1728
Следующее число, пожалуйста: стоп.
yes
В некоторых реализациях для того, чтобы приглашение появилось на экране перед чтением, необходимо выдать дополнительный запрос (такой, скажем, как ttyflush) после записи.
В последующих разделах мы увидим некоторые типичные примеры операций, в которых участвуют чтение и запись.
6.2.2. Вывод списков
Кроме стандартного прологовского формата для списков существуют несколько других естественных форм их внешнего представления, которые в некоторых ситуациях являются более предпочтительными. Следующая процедура
вывспис( L)
выводит список L так, что каждый его элемент занимает отдельную строку:
вывспис( []).
вывспис( [X | L) :-
 write( X), nl,
 вывспис( L).
Если у нас есть список списков, то одной из естественных форм его выводе является такая, при которой все элементы каждого списка записываются на отдельной строке. Для этого мы определим

 
                