- •Функциональное и логическое программирование
- •Глава 1. Классификация языков и стилей программирования 3
- •Глава 2. Программирование на языКе лисп 16
- •Глава 3. Программирование на языке пролог 89
- •Глава 1. Классификация языков и стилей программирования
- •Основные парадигмы программирования
- •Процедурное (императивное, директивное) программирование.
- •Объектно-ориентированное программирование.
- •Декларативное программирование
- •Логическое программирование.
- •Функциональное программирование.
- •Классификация языков программирования
- •Функциональные языки
- •Логические языки
- •Глава 2. Программирование на языКе лисп
- •История создания языка Лисп
- •Диалекты языка Лисп
- •Лисп-машины
- •Область применения языка Лисп
- •Особенности языка Лисп Одинаковая форма данных и программ
- •Хранение данных, не зависящее от места
- •Автоматическое и динамическое управление памятью
- •Функциональная направленность
- •Динамическая проверка типов
- •Интерпретирующий и компилирующий режимы работы;
- •Пошаговое программирование
- •Единый системный и прикладной язык программирования
- •Основы языка Лисп
- •Понятие функции.
- •Quote блокирует вычисления
- •Базовые функции языка.
- •Функция car возвращает в качестве значения первый элемент списка.
- •Функция cdr - возвращает в качестве значения хвостовую часть списка, т. Е. Список, получаемый из исходного списка после удаления из него головного элемента:
- •Функция cons включает новый элемент в начало списка:
- •Предикат equal проверяет идентичность записей:
- •Предикат equalp проверяет наиболее общее логическое равенство:
- •Другие простейшие встроенные функции Лиспа. Функция null проверяет, является ли аргумент пустым списком:
- •Комбинации вызовов car и cdr позволяют получить любой элемент списка:
- •Наиболее общая функция, выделяющая n-й элемент списка (при этом индексация начинается с 0):
- •Функция last позволяет выделить последний элемент списка:
- •Функция list - создает список из элементов:
- •Функция setq – невычисляющее присваивание:
- •Функция setf - обобщенная функция присваивания:
- •Функции, обладающие побочным эффектом, называются псевдофункциями.
- •С символом можно связать именованные свойства:
- •Функция get - возвращает значение свойства, связанного с символом:
- •Псевдофункция remprop удаляет свойство и его значение:
- •Вызов интерпретатора eval вычисляет значение выражения.
- •Ввод и вывод.
- •Использование файлов.
- •Определение функций
- •Задание параметров в лямбда-списке.
- •Передача параметров и область их действия.
- •Вычисления в лисПе.
- •Предложение let создает локальную связь внутри формы:
- •Последовательные вычисления.
- •Разветвление вычислений.
- •Циклические вычисления.
- •Передача управления.
- •Другие циклические структуры.
- •Динамическое управление из другого контекста
- •Внутреннее представление списков
- •Функциональное программирование Рекурсия. Различные виды рекурсии.
- •Функции более высокого порядка.
- •Применяющие функционалы.
- •Отображающие функционалы.
- •Макросы
- •Типы данных
- •Основные типы данных:
- •Глава 3. Программирование на языке пролог
- •Общие сведения о языке Пролог. Язык Пролог как система, реализующая логический вывод в исчислении предикатов первого порядка.
- •Фразы Хорна как средство представления знаний.
- •Синтаксис языка Пролог.
- •Фразы, термы, факты, правила.
- •Константы:
- •Простейшая программа на Прологе
- •Выполнение запроса в Прологе.
- •Неудача запроса и возврат назад.
- •Декларативная и процедурная семантика Пролога.
- •Рекурсивные процедуры.
- •Списки.
- •Операторы.
- •Средства управления ходом выполнения программы. Предикат сократить (отсечение).
- •Отрицание как неудача запроса.
- •Встроенные предикаты.
- •Типы отношений.
- •Ограничения, обеспечивающие целостность отношений.
- •Свойства отношений.
- •Подходы к программированию на языке Пролог.
Диалекты языка Лисп
MACLISP
Кроме символьной обработки MacLisp широко использовался в традиционных числовых вычислениях, применяемых, например, в робототехнике, обработке речи и изображений. Исходя из требований, предъявляемых этими областями, в MacLisp были включены новые математические типы данных, такие как матричная и битовая обработка, а также широкий набор арифметических функций и средств. Быть может, важнейшая из них – возможность вычислений с неограниченной точностью, основывающаяся на созданных Кнутом алгоритмах.
MacLisp был также первой Лисп-системой, для которой создан хороший транслятор. Транслятор генерирует машинную программу в форме списков. Машинный код в виде списка легко обрабатывать и результирующий код для числовых задач получался эффективнее, чем у лучших фортрановских трансляторов.
Самым большим недостатком системы является то, что ее никогда не документировали должным образом. Документация по этой системе разбросана по различным отчетам и руководствам. MacLisp был исследовательской системой и не предназначался для обучения и промышленного использования.
MYLISP
Интерпретатор MyLisp-85, разработанный для ПЭВМ серии IBM PC – удачный вариант реализации диалекта языка, включающий сравнительно ограниченный набор базовых функций (около 260) и оказавшийся вследствие этого более простым для изучения.
По сравнению с Common Lisp диалект MyLisp не имеет такого широкого спектра доступных типов данных. В нем обеспечивается работа только с двумя типами числовой информации: целыми числами с любым основанием и рациональными. В диалекте отсутствуют средства работы со структурами, массивами, потоками и другими типами данных, указанная реализация языка Лисп имеет одно существенное преимущество – возможность пополнения базового набора функций путем подключения подпрограмм, написанных на языке ассемблера, что позволило повысить гибкость использования интерпретатора и эффективность прикладного программного обеспечения, создаваемого на его основе. Возможность такого пополнения отсутствует в большинстве других Лисп-систем, являющихся в этом смысле замкнутыми программными продуктами.
Набор базовых функций интерпретатора MyLisp включает ряд функций, обеспечивающих доступ практически ко всем функциям ОС ЭВМ через соответствующие прерывания. Наконец, указанная Лисп-система обеспечивается библиотеками Лисп-функций, дополняющими базовый набор функциями, имеющимися в диалектах Common Lisp и InterLisp, что облегчает решение проблемы переносимости исходных текстов программных модулей, а также библиотеками, позволяющими выполнять манипулирование окнами на экране дисплея и обрабатывать управляющие воздействия через устройство типа «мышь». В комплект дополнительного программного обеспечения к интерпретатору входят интерактивный редактор текстов и простая обучающая система, написанные на диалекте языка MyLisp.
INTERLISP
InterLisp появился в 1972 году. InterLisp уже не был языком в том же смысле, что и MacLisp или другие Лисп-системы или обычные традиционные системы программирования. Он представлял собой интегрированную среду программирования, в которую вошло множество различных вспомогательных средств. InterLisp стал классическим примером хорошо развитых программных средств в системах разделения времени.
Этот диалект наряду с Common Lisp один из наиболее распространенных, имеет достаточно развитый аппарат представления и манипулирования различными структурами данных, включая массивы. Среди общих особенностей данного варианта языка следует отметить использование для обозначения встроенных функций нетрадиционных имен, что порой затрудняет перенос готовых программных продуктов на другие диалекты и другие ЭВМ.
В 1974 году фирма Xerox начала разработку для языка InterLisp персональной рабочей станции под названием Alto. В реализации языка Лисп для Alto впервые применили специально спроектированную микропрограммируемую систему команд мини-ЭВМ, способную с более высокой производительностью, чем универсальные ЭВМ, интерпретировать Лисп-программы. Из этой машины Alto впоследствии развились Лисп-машины серии 1100 фирмы Xerox.
На основе версии InterLisp, работавшей в системе разделения времени, была создана совместимая снизу вверх версия InterLisp-D, используемая на Лисп-машинах серии 1100. В ее пользовательский интерфейс входили многооконное взаимодействие, графика с высокой разрешающей способностью, средства выбора из меню и мышь, а также ориентированный на использование экрана инспектор структур данных.
При создании языка InterLisp работа велась весьма тщательно. Система хорошо документирована и более новые версии совместимы с более ранними. Так преимуществом системы стало непрерывно пополняющееся большое количество переносимого программного обеспечения. С другой стороны, ограничение системы старым, зафиксированным уже в конце 70-х годов диалектом, сделало систему отчасти устаревшей и трудно расширяемой. В InterLisp среди прочего отсутствуют иерархические типы данных, объекты и замыкания. К тому же он базируется на динамическом связывании, тогда как новые версии Лисп – статические. Однако из InterLisp берет начало новая версия – Common Lisp (1986). Для программирования на более высоком уровне в InterLisp разработаны такие средства, в которых уже присутствовали объекты.
InterLisp – столь замкнутая система, что доступна только ее оттранслированная версия в машинных кодах. В некоторых других системах, таких как, например ZetaLisp, поддерживается версия Лисп на исходном языке, которая доступна пользователю и может модифицироваться им. Развитие закрытых систем, похожих на InterLisp, связано с ресурсами, имеющимися у создавших их лабораторий.
InterLisp использует свыше 500 функций и большое количество системных имен и флажков, с помощью которых можно настроить и подогнать систему. InterLisp был реализован в системе разделения времени на многих больших ЭВМ.
В InterLisp основное внимание было уделено удобству системы для пользователя. Главный принцип разработчиков этого диалекта: все, что может иметь место в системе, должно естественно выражаться в терминах ее входного языка. Поэтому в InterLisp программисту доступно все. Он может переопределять любые, в том числе и встроенные функции; задавать и переопределять реакции на ошибки; работать непосредственно с уровня входного языка с внутренними структурами интерпретатора и т. д. При этом система поддерживает свою целостность и работоспособность.
FRANZLISP
MacLisp стал основой для многих новых диалектов языка Лисп, первым из которых был FranzLisp. Этот диалект назван в честь известного венгерского композитора. Главным мотивом разработки FranzLisp было желание получить современную Лисп-систему для новых машин VAX, чтобы на них можно было использовать программное обеспечение Лисп. FranzLisp в довольно большой степени напоминает MacLisp, однако в диалекте отсутствуют некоторые устаревшие особенности MacLisp.
Новый диалект был реализован в университете в Беркли на ЭВМ VAX 780/11 на языке Си под управлением системы UNIX. Благодаря своей хорошей переносимости FranzLisp получил распространение во многих университетах и исследовательских учреждениях.
ZETALISP
ZetaLisp также опирается на MacLisp. Он создан в 70-е годы в MIT (Massachusetts Institute of Technology – Массачусетский технологический институт) в рамках проекта по созданию Лисп-машины, финансированного оборонным агентством. С самого начала его целью было изготовление коммерческого продукта. В 1979 году в связи с проектом родились два предприятия, изготавливающие Лисп-машины: Symbolic Inc. и Lisp Machine Inc. (LMI). После этого в 80-е годы работа по развитию ZetaLisp продолжалась в них независимо друг от друга на коммерческой основе. В какой-то мере системы отличаются друг от друга, но в части ZetaLisp машины почти совместимы.
ZetaLisp содержит следующие развитые механизмы и черты:
широкий выбор типов данных;
возможность объектно-ориентированного программирования в системе Flavor;
управляющие структуры, динамические механизмы передачи управления
сопрограммы и процессы;
гибкий механизм ключевых слов в лямбда-списке и многозначные функции;
ввод и вывод, основывающийся на потоках;
пространства имен;
уже готовые функции, в том числе для сортировки, работы с линейными управлениями и матричные вычисления.
COMMON LISP
Этот диалект отличается наиболее широким представлением различных структур данных и включает около 800 встроенных функций. В этом диалекте обеспечиваются средства обработки основных классов числовой информации: целых, вещественных и комплексных. Символьные данные (литеры, литеральные атомы, строки) в Common Lisp соответствуют основным возможностям других Лисп-систем. Дополнительно имеются средства обработки непечатных литер в символьных именах.
Одним из существенных преимуществ диалекта Common Lisp является наличие средств обработки массивов и структур, по своим возможностям не уступающих соответствующим средствам традиционных языков программирования (Фортран, Паскаль). Массивы в Common Lisp могут иметь любое неотрицательное число измерений и индексируются последовательностью целых чисел. Тип компонентов массива может быть произвольным. Выделяется подкласс векторов – одномерных массивов, среди которых отдельно рассматриваются строки и битовые массивы.
Структуры Common Lisp являются типом многокомпонентных записей, определяемых пользователем и имеющих именованные компоненты. Встроенное макроопределение DEFSTRUCT используется для определения структур новых типов. Для создания данных нового типа в виде структуры предусмотрены средства автоматической генерации набора функций, обеспечивающих средства манипулирования объектами этого класса.
Удобным средством контроля доступа к различным переменным и функциям Лисп-программ в Common Lisp являются пакеты. Пакет - множество имен объектов, определенных и доступных в нем. Внутри пакета имена объектов подразделяются на внутренние и внешние. Первые предназначены для использования только внутри данного пакета, а вторые – для обеспечения связи с другими пакетами. Лисп-интерпретатор представляет широкий спектр средств манипулирования с пакетами. Как правило, Лисп-система имеет в своем составе четыре стандартных пакета: Лисп (содержащий примитивы системы), user (умалчиваемый пакет прикладных программ и данных пользователя), keyword (содержащий ключевые слова всех встроенных функций и функций, определяемых пользователем), system (зарезервированный для системных целей).
Значительной переработке и расширению в Common Lisp подверглись средства ввода-вывода и передачи информации. Для эффективной организации различных обменов с внешней средой введена концепция потоков, позволяющих осуществлять одно- и (или) двухстороннюю передачу информации. Для потоков предусмотрен набор базовых функций. В диалекте различают символьные и двоичные потоки. В первом случае передача осуществляется по байтам, а во втором – целыми числами. Кроме стандартных потоков пользователь имеет возможность создавать и использовать собственные потоки.
В дополнение к указанным типам данных Common Lisp имеет ряд специфических классов объектов: хэш-таблицы, обеспечивающие эффективный способ доступа к данным по ключу; READ-таблицы, обеспечивающие управление обработкой информации поступающей из входного потока Лисп-системы, и некоторые другие. Такое множество имеющихся в диалекте различных типов данных, с одной стороны, развеивает существующее ошибочное представление о языке Лисп как о средстве обработки только символьной информации, а с другой – наличие мощных средств манипулирования типами данных существенно усложняет его.
Этот диалект открыт: принципиальным является то, что осталась возможность в будущем, когда подойдет время и будет достигнуто согласие, добавить новые средства и методы. Эта идея как раз соответствует духу языка Лисп.
Common Lisp не является готовой программной системой в том же смысле, что и InterLisp, поскольку вопросы среды в основном оставлены открытыми. В стандарте не определено, каким должен быть редактор или другие вспомогательные средства. Сказано лишь в самом общем виде, каким образом они вызываются. Для того чтобы обеспечить быстрое развитие, среда и инструментальные средства не затронуты стандартизацией, и поэтому есть возможность создавать различные среды для различных целей. Common Lisp не определяет также и интерфейс пользователя.
В Common Lisp много внимания уделено практическим требованиям, и, вероятно, поэтому не все его черты эстетичны и чисты. Несомненно, что и другие Лисп-системы будут использоваться в дальнейшем, и их также необходимо развивать.
Common Lisp предназначен не только для работы со списками или для символьной обработки, он является универсальным языком программирования, включающим в себя особенно хорошие средства для численных вычислений, управления данными и связи. На Common Lisp можно с одинаковым успехом писать программы в традиционных операторном, процедурном, фразовом стиле, а также и в свойственных языку Лиспу стилях. В языке содержатся предпосылки для использования различных способов и стилей программирования, таких как процедурное, функциональное, макропрограммирование, программирование, управляемое данными, и продукционное программирование, а также средства, необходимые для логического и объектного программирования и реализации других средств более высокого уровня.
Можно смело сказать, что Common Lisp содержит почти все, что на сегодняшний день могут дать другие известные языки программирования, и, кроме того, он предусматривает средства для расширения языка.
