Используя предикаты readи phh,как они были определены выше, мы можем написать программу для печати краткого содержания исторических событий, хранящихся в базе данных, с помощью фактов с предикатом событие.Эта программа имеет вид:
обращение:-
phh(['Какая',дата,вас,'интересует?'!),read(D),coбытиe(D,S),pph(S).
Мы определили предикат обращение,не имеющий аргументов. Когда мы обращаемся к системе с вопросом
?- обращение.
Пролог напечатает
Какая дата вас интересует?
и будет ждать ответа. Предположим, что мы ввели с клавиатуры
1523.
Обратите внимание на то, что после 1523 необходимо ввести точку, так как этого требует предикат read.И, как обычно, мы должны нажать клавишу RETURN, чтобы сообщить ЭВМ, что мы закончили ввод строки текста. После этого Пролог ответит
Кристиан II покинул Данию
Обратите внимание, что в первой строке тела правила обращениеиспользуется предикат phh,хотя в этом случае печатается не краткое содержание исторического события. Это просто показывает, что phhвполне подходит для печати произвольного списка атомов независимо от того, откуда он взялся.
Наименьшей единицей данных, которая может участвовать в операциях ввода-вывода, является литера. Мы уже знаем, что литеры интерпретируются как небольшие целые числа в соответствии с кодом ASCII. В Прологе имеется несколько встроенных предикатов для ввода и вывода литер.
Если переменная Xимеет в качестве значения некоторую литеру (ее код ASCII), то эта литера будет напечатана при обработке целевого утверждения put(X).Предикат putвсегда выполняется и не может быть пересогласован (это приводит к неудаче). В качестве «побочного эффекта» putпечатает литеру на дисплее терминала. Например, мы можем напечатать слово helloдовольно необычным способом:
?- put(104),put(101),put(108),put(108),put(111).
hello
Результатом такой конъюнкции целей является печать Прологом литер h, е, l, l, онепосредственно под вопросом, как показано выше. Мы уже видели, что имеется возможность начать печать текста с начала следующей строки, использовав для этого предикат без аргументов nl. В действительности nl «печатает» некоторые управляющие литеры, что вызывает перевод курсора на дисплее терминала на начало следующей строки. Вопрос
?- put(104),put(105),nl,put(116),put(104),put(101),put(114), put(1O1).
вызвал бы следующую печать:
hi
there
Другой предикат, с которым мы уже познакомились, - это tab(X),печатающий Xпробелов (ASCII код равен 32). Разумеется, переменной Xдолжно быть присвоено целое число. Отметим, что предикат tab(X)мог бы быть определен так:
tab(0):- !.
tab(N):- put(32), M is N-1, tab(M).
Теперь мы можем определить предикат, который мы назовем печать_строки. Если значением переменной Xявляется список кодов литер (строка), то целевое утверждение печать_строкинапечатает этот список (строку), используя putдля печати каждого элемента списка. Как и во всех подобных программах, граничным условием является появление пустого списка. Это условие мы и используем для завершения рекурсии. При непустом списке с помощью putпечатается голова списка, а затем используем печать_строки– хвост списка:
печать_строки([]).
печать_строки([Н|Т]):- put(H), печать_строки(Т).
?- печать_строки(«Чарлз V отрекся от престола в Брюсселе»).
Чарлз V отрекся от престола в Брюсселе
Если мы решили представлять краткое содержание исторических событий как строки литер, а не как списки атомов, то такого определения вполне достаточно, чтобы печатать строки из базы данных для предиката событие.
Для ввода литер, набираемых на клавиатуре терминала, могут быть использованы предикаты get0(X)и get(X). Эти предикаты всегда согласуются с базой данных, если их аргументы неконкре-тизированы, а попытка повторного согласования всегда неудачна. При обработке целей, включающих эти предикаты, ЭВМ ожидает до тех пор, пока пользователь не наберет на клавиатуре какую-либо литеру. Указанные предикаты немного различаются тем, что get0(X)присвоит Xлюбую набранную на клавиатуре литеру независимо от ее вида. Напротив, get(X)пропустит все управляющие литеры и присвоит Xв качестве значения первую печатаемую литеру. Как отмечалось в гл. 2, печатаемая литера – это литера, которая визуализируется на дисплее терминала.
Читать дальше