- •Оглавление
- •Предисловие
- •Предисловие к русскому изданию
- •Глава 1. Введение
- •1.1. Новые инструменты
- •1.2. Новые приемы
- •1.3. Новый подход
- •Глава 2. Добро пожаловать в Лисп
- •2.1. Форма
- •2.2. Вычисление
- •2.3. Данные
- •2.4. Операции со списками
- •2.5. Истинность
- •2.6. Функции
- •2.7. Рекурсия
- •2.8. Чтение Лиспа
- •2.9. Ввод и вывод
- •2.10. Переменные
- •2.11. Присваивание
- •2.12. Функциональное программирование
- •2.13. Итерация
- •2.14. Функции как объекты
- •2.15. Типы
- •2.16. Заглядывая вперед
- •Итоги главы
- •Упражнения
- •Глава 3. Списки
- •3.1. Ячейки
- •3.2. Равенство
- •3.3. Почему в Лиспе нет указателей
- •3.4. Построение списков
- •3.5. Пример: сжатие
- •3.6. Доступ
- •3.7. Отображающие функции
- •3.8. Деревья
- •3.9. Чтобы понять рекурсию, нужно понять рекурсию
- •3.10. Множества
- •3.11. Последовательности
- •3.12. Стопка
- •3.13. Точечные пары
- •3.14. Ассоциативные списки
- •3.15. Пример: поиск кратчайшего пути
- •3.16. Мусор
- •Итоги главы
- •Упражнения
- •Глава 4. Специализированные структуры данных
- •4.1. Массивы
- •4.2. Пример: бинарный поиск
- •4.3. Строки и знаки
- •4.4. Последовательности
- •4.5. Пример: разбор дат
- •4.6. Структуры
- •4.7. Пример: двоичные деревья поиска
- •4.8. Хеш-таблицы
- •Итоги главы
- •Упражнения
- •Глава 5. Управление
- •5.1. Блоки
- •5.2. Контекст
- •5.3. Условные выражения
- •5.4. Итерации
- •5.5. Множественные значения
- •5.6. Прерывание выполнения
- •5.7. Пример: арифметика над датами
- •Итоги главы
- •Упражнения
- •Глава 6. Функции
- •6.1. Глобальные функции
- •6.2. Локальные функции
- •6.3. Списки параметров
- •6.4. Пример: утилиты
- •6.5. Замыкания
- •6.6. Пример: строители функций
- •6.7. Динамический диапазон
- •6.8. Компиляция
- •6.9. Использование рекурсии
- •Итоги главы
- •Упражнения
- •Глава 7. Ввод и вывод
- •7.1. Потоки
- •7.2. Ввод
- •7.3. Вывод
- •7.4. Пример: замена строк
- •7.5. Макрознаки
- •Итоги главы
- •Упражнения
- •Глава 8. Символы
- •8.1. Имена символов
- •8.2. Списки свойств
- •8.3. А символы-то не маленькие
- •8.4. Создание символов
- •8.5. Использование нескольких пакетов
- •8.6. Ключевые слова
- •8.7. Символы и переменные
- •8.8. Пример: генерация случайного текста
- •Итоги главы
- •Упражнения
- •Глава 9. Числа
- •9.1. Типы
- •9.2. Преобразование и извлечение
- •9.3. Сравнение
- •9.4. Арифметика
- •9.5. Возведение в степень
- •9.6. Тригонометрические функции
- •9.7. Представление
- •9.8. Пример: трассировка лучей
- •Итоги главы
- •Упражнения
- •Глава 10. Макросы
- •10.1. Eval
- •10.2. Макросы
- •10.3. Обратная кавычка
- •10.4. Пример: быстрая сортировка
- •10.5. Проектирование макросов
- •10.6. Обобщенные ссылки
- •10.7. Пример: макросы-утилиты
- •10.8. На Лиспе
- •Итоги главы
- •Упражнения
- •Глава 11. CLOS
- •11.1. Объектно-ориентированное программирование
- •11.2. Классы и экземпляры
- •11.3. Свойства слотов
- •11.4. Суперклассы
- •11.5. Предшествование
- •11.6. Обобщенные функции
- •11.7. Вспомогательные методы
- •11.8. Комбинация методов
- •11.9. Инкапсуляция
- •11.10. Две модели
- •Итоги главы
- •Упражнения
- •Глава 12. Структура
- •12.1. Разделяемая структура
- •12.2. Модификация
- •12.3. Пример: очереди
- •12.4. Деструктивные функции
- •12.5. Пример: двоичные деревья поиска
- •12.6. Пример: двусвязные списки
- •12.7. Циклическая структура
- •12.8. Неизменяемая структура
- •Итоги главы
- •Упражнения
- •Глава 13. Скорость
- •13.1. Правило бутылочного горлышка
- •13.2. Компиляция
- •13.3. Декларации типов
- •13.4. Обходимся без мусора
- •13.5. Пример: заранее выделенные наборы
- •13.6. Быстрые операторы
- •13.7. Две фазы разработки
- •Итоги главы
- •Упражнения
- •Глава 14. Более сложные вопросы
- •14.1. Спецификаторы типов
- •14.2. Бинарные потоки
- •14.3. Макросы чтения
- •14.4. Пакеты
- •14.5. Loop
- •14.6. Особые условия
- •Глава 15. Пример: логический вывод
- •15.1. Цель
- •15.2. Сопоставление
- •15.3. Отвечая на запросы
- •15.4. Анализ
- •Глава 16. Пример: генерация HTML
- •16.1. HTML
- •16.2. Утилиты HTML
- •16.3. Утилита для итерации
- •16.4. Генерация страниц
- •Глава 17. Пример: объекты
- •17.1. Наследование
- •17.2. Множественное наследование
- •17.3. Определение объектов
- •17.4. Функциональный синтаксис
- •17.5. Определение методов
- •17.6. Экземпляры
- •17.7. Новая реализация
- •17.8. Анализ
- •Комментарии
- •Алфавитный указатель
15.4. Анализ |
261 |
|
|
|
|
|
Если мы выполним (clrhash |
*rules*) и затем определим следующие |
|
правила и факты: |
|
|
(<- (parent donald nancy)) |
|
|
(<- (parent donald debbie)) |
|
|
(<- (male donald)) |
|
|
(<- (father ?x ?y) (and (parent ?x ?y) (male ?x))) |
|
|
(<- (= ?x ?y)) |
|
|
(<- (sibling ?x ?y) (and (parent ?z ?x) |
|
|
(parent ?z ?y) |
|
|
(not (= ?x ?y)))) |
|
|
то сможем сделать следующие выводы: |
|
|
> (with-answer (father ?x ?y) |
|
|
(format t "~A is the father of ~A.~%" ?x ?y)) |
|
|
DONALD is the father of DEBBIE. |
|
|
DONALD is the father of NANCY. |
|
|
NIL |
|
|
> (with-answer (sibling ?x ?y) |
|
|
(format t "~A is the sibling of ~A.~%" ?x ?y)) |
|
|
DEBBIE is the sibling of NANCY. |
|
|
NANCY is the sibling of DEBBIE. |
|
|
NIL |
|
|
|
|
Рис. 15.7. Программа в работе |
|
15.4. Анализ
Может показаться, что написанный нами код является простым и есте ственным решением поставленной задачи. На самом деле, он крайне не эффективен. В действительности, мы написали, по сути, интерпрета тор, в то время как могли создать компилятор.
Приведем набросок того, как это может быть сделано. Основная идея заключается в запаковке всей программы в макросы <- и with-answer. В таком случае основная часть работы будет выполняться на этапе ком пиляции, тогда как сейчас она выполняется непосредственно во время запуска. (Зародыш этой идеи можно увидеть в avg на стр. 181.) Будем представлять правила как функции, а не как списки. Вместо функций типа prove и prove-and, интерпретирующих выражения в процессе рабо ты, у нас будут функции для преобразования выражений в код. Выра жения становятся доступны в момент определения правила. Зачем ждать, пока выражение будет использовано, чтобы его проанализиро вать? Это относится и к with-answer, который будет вызывать функции типа <- для генерации своего раскрытия.
262 |
Глава 15. Пример: логический вывод |
Кажется, что подобная программа будет значительно сложнее написан ной в этой главе, но на деле реализация предложенной идеи займет все го в два-три раза больше времени. Читателям, желающим узнать боль ше о подобных методиках, рекомендуется посмотреть книги «On Lisp» и «Paradigms of Artificial Intelligence Programming»1, которые содер жат примеры программ, написанных в таком стиле.
1Peter Norvig «Paradigms of Artificial Intelligence Programming», Morgan Kaufman, 1992. Эта книга, также известная как PAIP, рассматривает про граммирование задач искусственного интеллекта. Автор использует Com mon Lisp и сопровождает книгу большим количеством кода, который до ступен по адресу: http://norvig.com/paip/README.html. – Прим. перев.