Навигация
Главная
Поиск
Форум
FAQ's
Ссылки
Карта сайта
Чат программистов

Статьи
-Delphi
-C/C++
-Turbo Pascal
-Assembler
-Java/JS
-PHP
-Perl
-DHTML
-Prolog
-GPSS
-Сайтостроительство
-CMS: PHP Fusion
-Инвестирование

Файлы
-Для программистов
-Компонеты для Delphi
-Исходники на Delphi
-Исходники на C/C++
-Книги по Delphi
-Книги по С/С++
-Книги по JAVA/JS
-Книги по Basic/VB/.NET
-Книги по PHP/MySQL
-Книги по Assembler
-PHP Fusion MOD'ы
-by Kest
Professional Download System
Реклама
Услуги

Автоматическое добавление статей на сайты на Wordpress, Joomla, DLE
Заказать продвижение сайта
Программа для рисования блок-схем
Инженерный калькулятор онлайн
Таблица сложения онлайн
Популярные статьи
OpenGL и Delphi... 65535
Форум на вашем ... 65535
21 ошибка прогр... 65535
HACK F.A.Q 65535
Бип из системно... 65535
Гостевая книга ... 65535
Invision Power ... 65535
Пример работы с... 65535
Содержание сайт... 65535
ТЕХНОЛОГИИ ДОСТ... 65535
Организация зап... 65535
Вызов хранимых ... 65535
Создание отчето... 65535
Имитационное мо... 65535
Программируемая... 65535
Эмулятор микроп... 65535
Подключение Mic... 65535
Создание потоко... 65535
Приложение «Про... 65535
Оператор выбора... 65535
Реклама
Сейчас на сайте
Гостей: 19
На сайте нет зарегистрированных пользователей

Пользователей: 13,361
новичок: uehuat
Новости
Реклама
Выполняем курсовые и лабораторные по разным языкам программирования
Подробнее - курсовые и лабораторные на заказ
Delphi, Turbo Pascal, Assembler, C, C++, C#, Visual Basic, Java, GPSS, Prolog, 3D MAX, Компас 3D
Заказать программу для Windows Mobile, Symbian

Компьютерный магазин на Turbo Pascal (База данных) + Пояснительная записка
Моделирование интернет магазина (Apache, Php, Html) на GPSS + Блок схема
Игра Sokoban на Delphi + Блок схемы

7.13. Применение предикатов clause и retract


В этой книге мы неоднократно сталкивались с применением встроенных предикатов. На самом деле многие из них можно определить на Прологе, используя более простые встроенные предикаты. В этом разделе мы рассмотрим несколько таких определений. Они могут найти практическое применение у тех программистов, которые используют неполную в каких-либо отношениях Пролог-систему, однако в любом случае они интересны, как примеры программирования на Прологе. Может быть, они наведут вас на мысль о разработке несколько отличающихся версий этих предикатов для своего собственного применения.
Мы можем определить с помощью предиката clause некоторую версию процедуры listing. Определим предикат распеч1 такой, что при согласовании цели распеч1(Х) с базой данных из последней будут выводиться на печать утверждения, заголовки которых совпадают с X . Поскольку определение распеч1 включает использование предиката clause , у которого X задан как первый аргумент, то мы вынуждены поставить условие, что переменная X конкретизирована таким образом, что главный функтор утверждения известен. Рассмотрим определение распеч1 :
распеч1(Х):-clause(Х,Y),выв_утвержд(Х,Y),write('.'),nl,fail.
распеч1(Х).
выв_утвержд(Х,true):-!, write(X).
выв_утвержд(Х,Y):- write((X:- Y)).



При попытке согласовать с базой данных цель распеч1(Х) первое утверждение осуществляет поиск в базе данных такого утверждения, у которого заголовок совпадает с X . Если такое утверждение найдено, то оно выводится на печать и затем с помощью предиката fail инициируется механизм возврата. Возвратный ход опять приводит нас к предикату clause, который находит другое такое же утверждение, если оно имеется, и т. д. Когда таких утверждений больше нет, цель clause больше не удается согласовать с базой данных. В этом случае будет выбрано второе утверждение определения предиката распеч1, и потому цель будет согласована с базой данных. «Побочным эффектом» этих действий является печать соответствующих утверждений. Определение предиката выв_утвержд задает способ печати найденных утверждений. Выделяется специальный случай, когда тело утверждения есть true. В этом случае на печать выводится только заголовок утверждения. Иначе на печать выводится заголовок и тело утверждения, соединенные функтором ':-'. Отметим, что использование «отсечения» здесь имеет целью указать, что в случае, когда тело есть true, можно применять только первое правило. Поскольку данный пример построен на использовании механизма возврата, то задание отсечения здесь существенно.
Встроенный предикат clause можно также применить при написании Пролог-интерпретатора на самом Прологе. Это означает, что мы можем определить действия, которые представляют собой выполнение Пролог-программы, причем исполнителем этих действий также является Пролог-программа. Ниже приводится определение предиката интерпрет такого, что цель интерпрет(Х) согласуется в том и только в том случае, когда X , рассматриваемая как цель, согласуется с базой данных.
Предикат интерпрет напоминает встроенный предикат call, но является более ограниченным.
интерпрет(true):-!.
интерпрет((Gl,G2)):-!, интерпрет(G1), интерпрет(G2).
интерпрет(Цель):-clause(Цель,ЕщеЦели), интерпрет(ЕщеЦели).



Первые два утверждения рассчитаны на специальные случаи, когда цель есть true и когда цель представляет собой конъюнкцию целей. Последнее утверждение рассчитано на случай простой цели. Данная процедура находит утверждение, заголовок которого совпадает с заданной целью, и затем интерпретирует цели, входящие в тело этого утверждения. Заметим, что приведенное определение не рассчитано на программы, где используются встроенные предикаты, поскольку у таких предикатов нет определяющих их в обычном смысле утверждений.
Рассмотрим определение предиката consult. Разумеется, предикат consult предусмотрен среди встроенных предикатов большинства Пролог-систем, однако интересно посмотреть, как он может быть определен на Прологе.
consult(Файл):-seeing(Input),sее(Файл),repeat,read(Tepм),обработать(Терм),seen,see(Input),!.
обработать(Терм):- маркер_конца_файла(Терм),!.
обработать((?- Q)):-!, call(Q),!, fail.
обработать(Утвержд):- assertz(Утвержд), fail.



Это определение отличается рядом интересных особенностей. Во-первых, цель seeing(Input) и ее партнер see(Input) призваны гарантировать, что текущий файл ввода не будет «забыт» после применения предикат consult. Во-вторых, предикат маркер_конца_файла здесь использован без определения. По замыслу он должен быть истинным только в том случае, когда его аргумент конкретизирован термом, используемым для представления конца файла (который мог бы встретиться при выполнении read). В разных реализациях Пролога для представления «конца файла» используются разные термы, поэтому маркер_конца_файла в разных реализациях может быть определен по-разному. Одно из возможных определений выглядит так:
маркер_конца_файла(конец_файла).



В определении предиката обработать интересна организация выполнения соответствующих действий для каждого терма, считанного из входного файла. Целевое утверждение обработать доказуемо только, когда его аргументом является маркер конца файла. Иначе после соответствующего действия имитируется неудача доказательства и инициируется механизм возврата, который возвращает программу к предикату repeat. Отметим важность «отсечения» в конце определения предиката consult. Оно фиксирует выбор, сделанный предикатом repeat [13] . И последнее замечание. Если терм, считанный из файла, представляет собой вопрос (см. второе утверждение определения предиката обработать), то делается попытка немедленно согласовать соответствующую цель с помощью предиката call (см. разд. 6.7).
В качестве примера использования предиката retract здесь приведено определение полезного предиката уберивсе. При согласовании с базой данных целевого утверждения уберивсе(Х) все утверждения, заголовки которых совпадают с X , удаляются из базы данных. Поскольку в данном определении используется предикат retract, то переменная X не может быть неконкретизированной, так как в противном случае не с чем будет сопоставлять утверждения из базы данных. Данное определение должно распознавать два вида утверждений с заголовками, совпадающими с X , - факты и правила. При обработке этих двух видов утверждений в вызове retract задаются разные аргументы. В определении используется то свойство, что retract будет срабатывать при возврате до тех пор, пока все утверждения, сопоставимые с его аргументами, не будут удалены из базы данных.
уберивсе(Х):- retract(X), fail.
уберивсе(Х):- retract((X:- Y)), fail. уберивсе(_).



В качестве примера использования предиката убери все здесь приведено определение предиката reconsult на Прологе. Назначение предиката reconsult сходно с назначением предиката consult, с той лишь разницей, что при reconsult каждое считанное утверждение замещает существующее утверждение того же предиката, а не добавляется к нему (см. разд. 6.1).
reconsult(Файл):-уберивсе(сделано(_)),seeing(Старый),sее(Файл),repeat,read(Терм),проверить(Терм),seen,see(Старый),!.
проверить(Х):- маркер_конца_файла(Х),!.
проверить((?- Цели)):-!, call (Цели),!, fail.
проверить(Утверждение):-заголовок(Утверждение, Заголовок), запись_сделана(3аголовок), assertz(Утверждение), fail.
запись_сделана(3аголовок):- сделано(Заголовок),!.
запись_сделана(3аголовок):- functor(Заголовок,Func,Arity), functor(Proc,Func,Arity), asserta(cдeлaнo(Proc)), уберивсе(Ргос),!.
заголовок((А:- В), А):-!.
заголовок (А, А).



Это определение похоже на определение consult, в котором вместо предиката обработать используется предикат проверить. Основное различие заключено в предикате запись_сделана . Когда в файле появляется первое утверждение для данного предиката, то, прежде чем к базе данных будет добавлено хотя бы одно новое утверждение, из нее должны быть удалены все старые утверждения для данного предиката. Удаление этих утверждений нельзя откладывать до момента, когда в базе данных появятся их новые версии, поскольку в этом случае мы удалили бы из базы данных те утверждения, которые только что были введены. Как же определить, что некоторое утверждение в файле является первым для соответствующего предиката? Ответ заключается в том, что мы регистрируем в базе данных предикаты, для которых уже нашлись утверждения в файле. Это делается с помощью предиката сделано . Когда из файла считывается первое утверждение например, для предиката foo с двумя переменными, то имеющиеся утверждения удаляются и новое утверждение добавляется к базе данных. Кроме того, к базе данных добавляется факт:
сделано(foo(_,_)).



В дальнейшем, при чтении остальных утверждений для предиката too, мы сможем проверить, что старые утверждения уже удалены из базы данных. Тем самым удается избежать ошибочного удаления новых утверждений. Для данного определения важно, что мы не добавляем в базу данных что-нибудь вроде:
сделано(foо(а,Х)).



поскольку в этом случае аргумент предиката сделано не обязательно совпадает с заголовком утверждения для foo. Пара запросов
…,functor(Заголовок,Func,Arity),functor(Proc,Func,Arity),…



конкретизирует Ргос структурой, имеющей тот же функтор, что и заголовок Заголовок , но с переменными в качестве аргументов (см. разд. 6.5).

Опубликовал Kest July 09 2009 21:22:48 · 0 Комментариев · 10037 Прочтений · Для печати

• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •


Комментарии
Нет комментариев.
Добавить комментарий
Имя:



smiley smiley smiley smiley smiley smiley smiley smiley smiley
Запретить смайлики в комментариях

Введите проверочный код:* =
Рейтинги
Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Нет данных для оценки.
Гость
Имя

Пароль



Вы не зарегистрированны?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Поделиться ссылкой
Фолловь меня в Твиттере! • Смотрите канал о путешествияхКак приготовить мидии в тайланде?
Загрузки
Новые загрузки
iChat v.7.0 Final...
iComm v.6.1 - выв...
Visual Studio 200...
CodeGear RAD Stud...
Шаблон для новост...

Случайные загрузки
Трассировка прово...
Игра "Астероиды" ...
Midi
index.php + мод ...
Панель случайной ...
Факториал [Исходн...
Printgrid
Файловый менеджер
ProLIB18
VksButton
Abbrevia
Text3D
UmEdit
PBFoldder
База игр
PRNDbgrid
Изучаем Ассемблер
Учебник по создан...
PHP 5 для "чайников"
Пример клиента ФТ...

Топ загрузок
Приложение Клие... 100772
Delphi 7 Enterp... 97809
Converter AMR<-... 20261
GPSS World Stud... 17014
Borland C++Buil... 14189
Borland Delphi ... 10267
Turbo Pascal fo... 7372
Калькулятор [Ис... 5972
Visual Studio 2... 5206
Microsoft SQL S... 3661
Случайные статьи
Шинная топология ЛВС
Планирование
Masterbatch
Листинг 15.1. Форм...
• Почта со специфи...
Использование сред...
Наиболее элементар...
Официальный сайт к...
Инструменты для по...
Для каких адресов ...
10.1. Массив точек
подтверждена довер...
Официальный сайт С...
Специальные встр...
Клуб Вулкан снова ...
Несколько фактов о...
Карта состояния па...
Интим магазин
Сущность эффекта и...
Режимы фокусировки
Файловые потоки бы...
Рабочий пример: те...
Многократная рекурсия
Работа асинхронног...
CD-ROM
Статистика



Друзья сайта
Программы, игры


Полезно
В какую объединенную сеть входит классовая сеть? Суммирование маршрутов Занимают ли таблицы память маршрутизатора?