logo
Программа ГЭ_спец_2012 ответы light

Функционалы: функциональное значение функции, способы композиции функций, функции более высокого порядка.

При функциональном стиле программирования ответ на каждый из таких вопросов может быть дан в виде отдельной функции, причем роль каждой функции в схеме реализации отображения четко фиксирована. Схема реализации отображения может быть представлена в виде определения, формальными параметрами которого являются обозначения функций, выполняющих эти роли. Такое определение называется <функционал>. Более точно, функционал может оперировать функциями в качестве аргументов или результатов.

Функционалы - это функции, которые используют в качестве аргументов или результатов другие функции. При построении функционалов переменные могут играть роль имен функций, определения которых находятся во внешних формулах, использующих функционалы.

Параметром функционала может быть любая вспомогательная функция.

Вызовы функционалов можно объединять в более сложные структуры таким же образом, как и вызовы обычных функций, а их композиции можно использовать в определениях новых функций. Композиции функционалов позволяют создавать и более мощные построения, достаточно ясные, но требующие некоторого внимания.

Согласно стандарту, в реализацию языка Clisp обычно включены функционалы: map, mapcar,maplist, mapcan, mapcon, mapc, mapl [6, 7]. Каждый из них покомпонентно обработает любой набор списков. Отличаются они схемами выбора аргументов для отображающей функции, характером воздействия на исходные данные и оформлением результатов, передаваемых объемлющим формулам.

Map

( map result-type function sequences ... )

Функция function вызывается на всех первых элементах последовательностей, затем на всех вторых и т.д. Из полученных результатов function формируется результирующая последовательность, строение которой задается параметром result-type с допустимыми значениями cons, list, array, string, NIL.

Mapcar

( mapcar function list ... )

Функция function применяется к первым элементам списков, затем ко вторым и т.д. Другими словами, function применяется к <головам> методично сокращающихся списков, и результаты применения собираются в результирующий список.

Maplist

( maplist function list ... )

Функционал аналогичен mapcar, но function применяется к <<хвостам>> списков list, начиная с полного списка.

Mapc и Mapl

Оба функционала работают как mapcar и maplist, соответственно, за исключением того, что они в качестве формального результата выдают первый список (своеобразная аналогия с формальными аргументами).

Mapcan и Mapcon

И эти два функционала аналогичны mapcar и maplist, но формирование результатов происходит не с помощью операции cons, которая строит данные в новых блоках памяти, а с помощью деструктивной функции nconc, которая при построении новых данных использует память исходных данных, из-за чего исходные данные могут быть искажены.

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

• отображающие функционалы позволяют строить программы из крупных действий;

• функционалы обеспечивают гибкость отображений;

• определение функции может совсем не зависеть от конкретных имен;

• с помощью функционалов можно управлять выбором формы результатов;

• параметром функционала может быть любая функция, преобразующая элементы структуры;

• функционалы позволяют формировать серии функций от общих данных;

• встроенные в Clisp функционалы приспособлены к покомпонентной обработке произвольного числа параметров;

• любую систему взаимосвязанных функций можно преобразовать к одной функции, используя вызовы безымянных функций.

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

Функции высших порядков используют другие функции в качестве аргументов или вырабатывают их как результат.

(defun mul-N (N) #'(lambda (x) (* x N)))

; конструктор семейства функций, множащих

; аргумент на N

(funcall (mul-N 25) 7)

; применение частной функции, умножающей на 25

Правильность выражений с такими функциями требует корректной подстановки параметров и учета ранга функции, определяющего возможность манипулирования функциональными значениями. Функции можно ранжировать на основе так называемых типовых выражений, представляющих области определения и значения функций. Например,

x+1 : Number -> Number

x+y : (Number Number) -> Number

Суперпозицию функций можно характеризовать следующими типовыми выражениями:

S(h,g) = { при h: X -> Y, g: Y -> Z строит f=g(h)

— суперпозиция }

: (X->Y Y->Z) -> (X->Z)

(defun super (f g)

#'(lambda (x) (funcall f (funcall g x)) ))

; конструктор суперпозиции функций

(funcall (super #'car #'cdr) '(1 2 3))

; применение суперпозиции CAR и CDR

Двойное применение функции можно определить независимо или через суперпозицию — типовое выражение от этого не зависит, но оно представляет собой параметризованное выражение.

  1. Принципы логического программирования: понятие логической программы, основные конструкции, факты, правила, вопросы, логические переменные, подстановки, абстрактный интерпретатор, значение логической программы, вычислительная модель логических программ, ПРОЛОГ как система, реализующая логический вывод в исчислении предикатов первого порядка.

Задана некая формальная система F, если определены:

алфавит системы — счетное множество символов;

формулы системы — некоторое подмножество всех слов, которые можно образовать из символов, входящих в алфавит (обычно задается процедура, позволяющая составлять формулы из символов алфавита системы);

аксиомы системы — выделенное множество формул системы;

правила вывода системы — конечное множество отношений между формулами системы.

Зададим логику первого порядка (или логику предикатов), на которой основывается Пролог. Язык логики предикатов — один из формальных языков, наиболее приближенных к человеческому языку.

Алфавит логики первого порядка составляют следующие символы:

переменные (будем обозначать их последними буквами английского алфавита u, v, x, y, z);

константы (будем обозначать их первыми буквами английского алфавита a, b, c, d);

функциональные символы (используем для их обозначения ближние буквы f и g);

предикатные символы (обозначим их дальними буквами p, q и r);

пропозициональные константы истина и ложь (true и false);

логические связки ¬ (отрицание), (конъюнкция), (дизъюнкция), (импликация);

кванторы: (существования), (всеобщности);

вспомогательные символы (, ), ,.

Всякий предикатный и функциональный символ имеет определенное число аргументов. Если предикатный (функциональный) символ имеет n аргументов, он называется n-местным предикатным (функциональным) символом.

Термом будем называть выражение, образованное из переменных и констант, возможно, с применением функций, а точнее:

всякая переменная или константа есть терм;

если t1,...,tn — термы, а f — n-местный функциональный символ,то f(t1,...,tn) — терм;

других термов нет.

Формулы логики первого порядка получаются следующим образом:

всякая атомная формула есть формула;

если A и B — формулы, а x — переменная, то выражения ¬A (читается «не A» или «отрицание A»), A B (читается «A и B»), A B (читается «A или B»), A B (читается «A влечет B»), хA (читается «для некоторого x» или «существует x») и xA (читается «для любого x» или «для всякого x»)– формулы;

других формул нет.

Факт констатирует, что между объектами выполнено некоторое отношение. Он состоит только из заголовка. Можно считать, что факт - это предложение, у которого тело пустое.

Правило - это предложение, истинность которого зависит от истинности одного или нескольких предложений. Обычно правило содержит несколько хвостовых целей, которые должны быть истинными для того, чтобы правило было истинным.

Свободная переменная - это переменная, которая еще не получила значения. Она не равняется ни нулю, ни пробелу; у нее вообще нет никакого значения. Такие переменные еще называют неконкретизированными.

Переменная, которая получила какое-то значение и оказалась связанной с определенным объектом, называется связанной. Если переменная была конкретизирована каким-то значением и ей сопоставлен некоторый объект, то эта переменная уже не может быть изменена.

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

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

Интуитивно ясно, что недетерминированная машина, перед которой возникло несколько альтернативных путей решения, осуществляет корректный выбор очередного действия. Подлинно недетерминированную машину реализовать нельзя, однако ее можно моделировать или аппроксимировать. В частности, Пролог-интерпритатор аппроксимирует недетерминированное поведение интерпретатора абстрактных логических программ с применением механизма последовательного поиска и возвратов. Однако тот факт, что детерминизм только "моделируется", но "реально не присутствует", для недетерминированного мышления во многих случаях не существенен, точно также как несущественны для символьного мышления детали обработки указателей в процессе унификации.

Выполнение программ на Прологе заключается в работе абстрактного

интерпретатора, при которой вместо произвольной цели выбирается самая

лева цель, а недетерминированный выбор предложения заменяется

последовательным поиском унифицируемого правила и механизма возврата.

Пролог (Prolog) - это программирование на языке логики.

Этот язык используется для задач, которые сводятся к объектам и отношениям между ними.

Пролог является реляционным языком.

Пользоваиель должен установить какие формальные отношения и объекты существуют в решаемой задаче и установить какие отношения справедливы для поиска решения.

Пролог - это декларативный язык. Он отличается от процедурных (императивных) языков:

• императивный - как делать

• декларативный - что делать

Порядок выполнения Пролог программы определяется:

• семантикой языка

• новыми фактами, которые Пролог выводит из имеющихся

• отчасти той управляющей информацией, которую задает программист

Пролог - это логический язык, в котором реализована логика предикатов 1-го порядка.

В самом языке предусмотрены элементы интеллектуальности:

• сопоставление с образцом

• поиск с возвратом

• недетерменизм

  1. Согласование целевых утверждений: диаграмма успешного доказательства целевых утверждений, доказательство целевых утверждений при использовании механизма возврата, правила установления соответствия, недетерминизм, понятие "связанной" переменной, операционная модель вычисления ПРОЛОГ-программ, ПРОЛОГ и математическая логика.

Вопрос к системе - это всегда последовательность, состоящая из одной или нескольких целей. Для того, чтобы ответить на вопрос, система пытается достичь всех целей. Достичь цели - это значит показать, что утверждения, содержащиеся в вопросе, истинны в предположении, что все отношения программы истинны. Другими словами, достичь цели - это значит показать, что она логически следует из фактов и правил программы. Если вопрос содержит переменные, система должна к тому же найти конкретные объекты, которые (будучи подставленными вместо переменных) обеспечивают достижение цели. Найденные конкретизации сообщаются пользователю. Если для некоторой конкретизации система не в состоянии вывести цель из остальных предложений программы, то ее ответом на вопрос будет "нет".

Таким образом, подходящей интерпретацией пролог-программы в математических терминах будет следующая: пролог-система рассматривает факты и правила в качестве множества аксиом, а вопрос пользователя - как теорему; затем она пытается доказать эту теорему, т.е. показать, что ее можно логически вывести из аксиом.

Проиллюстрируем этот подход на примере программы о родственных отношениях. Пусть имеются следующие аксиомы и факты:

родитель(пам,боб). % Пам-родитель Боба

родитель(том,боб).

родитель(том,лиз).

родитель(бoб,энн).

родитель(боб,пат).

родитель(пат,джим).

предок(X,Z):- % Правило пр1: X-предок Z

родитель(X,Z).

предок(X,Z):- % Правило пр2: X-предок Z

родитель(X,Y),

предок(Y,Z).

?-предок(том,пат)

Цепочка доказательства Пролог-системой показана на рис. 47а.

Рис. 47а. Все шаги достижения цели предок(том, пат). Правая

ветвь демонстрирует, что цель достижима.

Графическое представление шагов вычисления на рис. 47а имеет форму дерева. Вершины дерева соответствуют целям или спискам целей, которые требуется достичь. Дуги между вершинами соответствуют применению (альтернативных) предложений программы, которые преобразуют цель, соответствующую одной вершине, в цель, соответствующую другой вершине. Корневая (верхняя) цель достигается тогда, когда находится путь от корня дерева (верхней вершины) к его листу, помеченному меткой "да". Лист помечается меткой "да", если он представляет собой простой факт. Выполнение пролог-программы состоит в поиске таких путей. В процессе такого поиска система может входить и в ветви, приводящие к неуспеху. В тот момент, когда она обнаруживает, что ветвь не приводит к успеху, происходит автоматический возврат к предыдущей вершине, и далее следует попытка применить к ней альтернативное предложение.

Наиболее важной операцией над термами является сопоставление. Сопоставление само по себе может производить содержательные вычисления.

Пусть даны два терма. Будем говорить, что они сопоставимы, если:

(1) они идентичны или

(2) переменным в обоих термах можно приписать в качестве значений объекты (т.е. конкретизировать их) таким образом, чтобы после подстановки этих объектов в термы вместо переменных, последние стали идентичными.

Например, термы дата(Д, М, 1983) и дата(Д1, май, Y1) сопоставимы. Одной из конкретизации, которая делает эти термы идентичными, является следующая:

• Д заменяется на Д1

• М заменяется на май

• Y1 заменяется на 1983

С другой стороны, дата(Д, М, 1983) и дата(Д1, Ml, 1944) не сопоставимы, как и термы дата(X, Y, Z) и точка(X, Y, Z).

Сопоставление - это процесс, на вход которого подаются два терма, а он проверяет, соответствуют ли эти термы друг другу. Если термы не сопоставимы, будем говорить, что этот процесс терпит неуспех. Если же они сопоставимы, тогда процесс находит конкретизацию переменных, делающую эти термы тождественными, и завершается успешно.

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

Общие правила выяснения, сопоставимы ли два терма S и Т, таковы:

(1) Если S и Т - константы, то S и Т сопоставимы, только если они являются одним и тем же объектом.

(2) Если S - переменная, а Т - произвольный объект, то они сопоставимы, и S приписывается значение Т. Наоборот, если Т - переменная, а S - произвольный объект, то Т приписывается значение S.

(3) Если S и Т - структуры, то они сопоставимы, только если

(а) S и Т имеют одинаковый главный функтор и

(б) все их соответствующие компоненты сопоставимы.

Результирующая конкретизация определяется сопоставлением компонент.

Недетерминизм - это явление в поведении программы с точки зрения внешнего к программе наблюдателя. Нечто, называемое "наблюдатель", "видит" запрос процесса программы, ответ среды и реакцию программы на этот ответ. Если на один и тот же запрос могут следовать разные ответы, реакция программы на каждый из которых различна, то мы говорим, что программа ведет себя недетерминировано. Такой недетерминизм будем называть внешним. Мы также говорим, что программа ведет себя недетерминировано, когда на один и тоже ответ среды реакция программы различна. Причем, эту реакцию наблюдатель заранее предсказать не может. В этом случае мы будем говорить о внутреннем недетерминизме.

Итак, выделяется два вида недетерминизма: внутренний и внешний. Источником внешнего недетерминизма процесса является недетерминизм ответов среды на его запросы. Этот недетерминизм обуславливают разные причины. Например, техническая производительность физической среды, алгоритмы арбитража конфликтов в логической среде, использование недетерминированных операторов типа SELECT в языке ADA. Как следствие, в средах с разными техническими производительностями, разными алгоритмами арбитража у одной и той же программы последовательности обращений к логическим ресурсам при одинаковых исходных данных могут быть разными. Недетерминизм этого типа может возникать из-за различий в алгоритмах распределения ресурсов. Так, например, если процесс запросил сообщение и в логической среде для него есть несколько сообщений, то дальнейшее поведение процесса может зависеть от того, какое сообщение от среды он получит первым. А это может зависеть, например, от алгоритма буферизации сообщений, используемого в логической среде, от структуры и технической производительности среды связи.

Источником внутреннего недетерминизма являются данные, которые процесс получает в форме сообщений. Естественно, что поведение процесса самым непосредственным образом зависит от данных. Однако, два сообщения, которые наблюдатель считает одинаковыми, процесс может рассматривать как разные.

Процедурная семантика определяет, как пролог-система отвечает на вопросы. Ответить на вопрос - это значит удовлетворить список целей. Этого можно добиться, приписав встречающимся переменным значения таким образом, чтобы цели логически следовали из программы. Можно сказать, что процедурная семантика Пролога - это процедура вычисления списка целей с учетом заданной программы. "Вычислить цели" это значит попытаться достичь их (см. рис. 47б).

Рис. 47б. Входы и выходы процедуры вычисления списка целей.

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

Конечно, в настоящих реализациях Пролога в процедуру вычислить добавлены и еще некоторые усовершенствования. Одно из них - сокращение работы по просмотрам программы с целью повышения эффективности. Поэтому на практике пролог-система не просматривает все предложения программы, а вместо этого рассматривает только те из них, которые касаются текущего целевого утверждения.

Пролог восходит к математической логике, поэтому его синтаксис и семантику можно наиболее точно описать при помощи логики. Синтаксис Пролога - это синтаксис предложений логики предикатов первого порядка, записанных в так называемой форме предложений (форме, при которой кванторы не выписываются явно), а точнее, в виде частного случая таких предложений - в виде формул Хорна (предложений, имеющих самое большее один положительный литерал). Процедурный смысл Пролога основывается на принципе резолюций, применяющемся для автоматического доказательства теорем, который был предложен Робинсоном в его классической статье (1965 г.). В Прологе используется особая стратегия доказательства теоремы методом резолюций, носящая название SLD. Сопоставление в Прологе соответствует некоторому действию в логике, называемому унификацией.

  1. Рекурсивное представление данных и программ: построение рекурсивных программ, граничные условия и способы использования рекурсии, структуры и деревья, список как частный вид структуры, формы записи списков, работа со списками, примеры программ с рекурсивными определениями.

Одна из причин того, что рекурсия так естественна для определения отношений на Прологе, состоит в том, что объекты данных часто сами имеют рекурсивную структуру. К таким объектам относятся списки и деревья. Список либо пуст (граничный случай), либо имеет голову и хвост, который сам является списком (общий случай). Двоичное дерево либо пусто (граничный случай), либо у него есть корень и два поддерева, которые сами являются двоичными деревьями (общий случай). Поэтому для обработки всего непустого дерева необходимо сначала что-то сделать с его корнем, а затем обработать поддеревья.

Рекурсивные отношения логически совершенно корректны и понятны. На самом деле, рекурсия - один из фундаментальных приемов программирования на Прологе. Без рекурсии с его помощью невозможно решать задачи сколько-нибудь ощутимой сложности.

Декларативная семантика Пролога определяет, является ли целевое утверждение истинным, исходя из данной программы, и если оно истинно, то для какой конкретизации переменных. Запятая между целями означает их конъюнкцию. Точка с запятой между целями означает их дизъюнкцию. Процедурная семантика Пролога - это процедура достижения списка целей в контексте данной программы. Процедура выдает истинность или ложность списка целей и соответствующую конкретизацию переменных. Процедура осуществляет автоматический возврат для перебора различных вариантов. Декларативный смысл программ на "чистом Прологе" не зависит от порядка предложений и от порядка целей в предложениях.

Процедурный смысл существенно зависит от порядка целей и предложений. Поэтому порядок может повлиять на эффективность программы; неудачный порядок может даже привести к бесконечным рекурсивным вызовам. Имея декларативно правильную программу, можно улучшить ее эффективность путем изменения порядка предложений и целей при сохранении ее декларативной правильности. Переупорядочивание - один из методов предотвращения зацикливания.

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

Структурные объекты (или просто структуры) - это объекты, которые состоят из нескольких компонент. Эти компоненты, в свою очередь, могут быть структурами.

Все структурные объекты можно изображать в виде деревьев. Корнем дерева служит функтор, ветвями, выходящими из него, - компоненты. Если некоторая компонента тоже является структурой, тогда ей соответствует поддерево в дереве, изображающем весь структурный объект.

Если одно и то же имя появляется в программе в двух различных смыслах, как в вышеупомянутом примере с точкой, то пролог-система будет различать их по числу аргументов и интерпретировать это имя как два функтора: один - двухаргументный; второй - трех. Это возможно потому, что каждый функтор определяется двумя параметрами:

(1) именем, синтаксис которого совпадает с синтаксисом атомов;

(2) арностью - т. е. числом аргументов.

Как уже объяснялось, все структурные объекты в Прологе - это деревья, представленные в программе термами.

Список - это структура данных, которая либо пуста, либо состоит из двух частей: головы и хвоста. Хвост в свою очередь сам является списком.

Список рассматривается в Прологе как специальный частный случай двоичного дерева. Для повышения наглядности программ в Прологе предусматриваются специальные средства для списковой нотации, позволяющие представлять списки в виде [Элемент1,Элемент2,...] или [Голова|Хвост] или [Элемент1,Элемент2,...|Остальные].

Примером программы с рекурсивными определениями может быть программа с использованием повторения (repeat). Repeat - цель, которая всегда успешна. Ее особое свойство состоит в том, что она недетерминирована, поэтому всякий раз, как до нее доходит перебор, она порождает новую ветвь вычислений. Цель repeat ведет себя так, как если бы она была определена следующим образом:

repeat.

repeat :- repeat.

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

квадраты :-

repeat,

read(X),

(X = стоп, !;

Y is X*X,

write(Y), fail ).

  1. Встроенные предикаты: добавление и исключение утверждений, классификация термов, изменение и анализ утверждений, работа со структурами произвольного вида, воздействие на процесс возврата, реализация сложных способов выражения целевых утверждений, объявление операторов, обработка файлов, наблюдение за выполнением программы на ПРОЛОГе.

Встроенные предикаты - предикаты исходно определенные в прологе, для которых не существует процедур в базе данных.

Когда интерпретатор встречает цель, которая сравнивается с встроенным предикатом, он вызывает встроенную процедуру.

Встроенные предикаты обычно выполняют функции не связанные с логическим выводом.

При сопоставлении строенные предикаты обычно дают побочный эффект,который не устраняется при бэктрекинге.

Простые встроенные предикаты ввода-вывода.

Встроенные предикаты обеспечивают возможности ввода-вывода информации:

write/1 - этот предикат всегда успешен. Когда вызывается, то побочным эффектом будет вывод значения аргумента на экран. При бэктрекинге предикат дает неудачу. Бэктрекинг не сбрасывает побочный эффект.

nl/0 - этот предикат всегда успешен. Когда вызывается, то побочным эффектом будет перевод на следующую строку. При бэктрекинге предикат дает неудачу. Бэктрекинг не сбрасывает побочный эффект.

tab/1 - этот предикат всегда успешен. Когда вызывается, то побочным эффектом будет печать коли- чество пробелов заданное аргументом. Аргумент должен быть целым. При бэктрекинге предикат дает неудачу. Бэктрекинг не сбрасывает побочный эффект.

read/1 - этот предикат читает терм , который вводится с клавиатуры и заканчивается точкой. Этот терм сопоста- вляется с аргументом. При бэктрекинге предикат дает неудачу. Бэктрекинг не сбрасывает побочный эффект.

Реляционная модель предполагает, что база данных - это описание некоторого множества отношений. Пролог-программу можно рассматривать как именно такую базу данных: описание отношений частично присутствует в ней в явном виде (факты), а частично - в неявном (правила). Более того, встроенные предикаты дают возможность корректировать эту базу данных в процессе выполнения программ. Это делается добавлением к программе (в процессе вычисления) новых предложений или же вычеркиванием из нее уже существующих. Предикаты, используемые для этой цели, таковы: assert (добавить), asserta (добавить в начало), assertz (добавить в конец) и retract (удалить).

Цель assert(С) всегда успешна, а в качестве своего побочного эффекта вызывает "констатацию" предложения С, т. е. добавление его к базе данных, аналогично и retract(С).

Предложения, добавленные к программе таким способом, ведут себя точно так же, как и те, что были в "оригинале" программы.

При добавлении нового предложения может возникнуть желание указать, на какое место в базе данных его следует поместить. Такую возможность обеспечивают предикаты asserta и assertz. Предикат asserta(C) добавляет предложение C в начало базы данных, а предикат assertz(C) – в конец.

Терм — выражение формального языка (системы), является формальным именем объекта или именем формы. Термы бывают разных типов: переменные, целые числа, атомы и т.д. Если терм - переменная, то в некоторый момент выполнения программы он может оказаться конкретизированным или не конкретизированным. Далее, если он конкретизирован, то его значение может быть атомом, структурой и т. п.

Встроенные предикаты этого типа таковы: var (переменная), nonvar (непеременная), atom (атом), integer (целое), atomic (атомарный). Они имеют следующий смысл:

var(X) – не конкретизированная переменная;

nonvar(X) – терм, отличный от переменной, или уже конкретизированная переменная;

atom(X) – атом;

integer(X) – целое;

atomic(X) – целое или атом.

В процессе достижения цели пролог-система осуществляет автоматический перебор вариантов, делая возврат при неуспехе какого-либо из них. Такой перебор - полезный программный механизм, поскольку он освобождает пользователя от необходимости программировать его самому. С другой стороны, ничем не ограниченный перебор может стать источником неэффективности программы. Поэтому иногда требуется его ограничить или исключить вовсе. Для этого в Прологе предусмотрена конструкция "отсечение" (!).

Отсечение подавляет перебор. Его применяют как для повышения эффективности программ, так и для повышения выразительности языка. Эффективность повышается путем прямого указания (при помощи отсечения) пролог - системе не проверять альтернативы, про которые нам заранее известно, что они должны потерпеть неудачу. Отсечение дает возможность сформулировать взаимно исключающие утверждения при помощи правил вида: если Условие то Утверждение1 иначе Утверждение2. Отсечение дает возможность ввести отрицание как неуспех: not(Цель) определяется через неуспех цели Цель. Иногда бывают полезными две особые цели true и fail. true - всегда успешна, а fail - всегда терпит неудачу.

Ввод и вывод (отличный от связанного с вопросами к программе) осуществляется посредством встроенных процедур. Файлы являются последовательными. Существуют текущие входной и выходной потоки. Пользовательский терминал рассматривается как файл с именем user. Переключение между потоками осуществляется с помощью процедур:

sее(Файл) Файл становится текущим входным потоком

tell(Файл) Файл становится текущим выходным потоком

seen закрывается текущий входной поток

told закрывается текущий выходной поток

Файлы читаются и записываются двумя способами:

• как последовательности символов

• как последовательности термов

Встроенные процедуры для чтения и записи символов и термов таковы:

rеad(Терм) вводит следующий терм

write(Терм) выводит Терм

put(КодСимвола) выводит символ с заданным ASCII - кодом

get0(КодСимвола) вводит следующий символ

gеt(КодСимвола) вводит ближайший следующий "печатаемый" символ

Две процедуры облегчают форматирование:

nl начинает новую строку

tab(N) выводит N пробелов

Основным средством отладки является трассировка (tracing). "Трассировать цель" означает: предоставить пользователю информацию, относящуюся к достижению этой цели в процессе ее обработки пролог-системой. Такая детальная трассировка может оказаться непрактичной из-за непомерно большого количества трассировочной информации. Поэтому пользователь может применить "селективную" трассировку. Существуют два механизма селекции: первый подавляет выдачу информации о целях, расположенных ниже некоторого уровня; второй трассирует не все предикаты, а только некоторые, указанные пользователем.

предикатов. Обычно используется следующий стандартный набор таких предикатов:

trace запускает полную трассировку всех целей, следующих за trace

notrace прекращает дальнейшее трассирование

spy(P) устанавливает режим трассировки предиката Р.

nospy( Р) прекращает "слежку" за Р.

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