- •Функциональное и логическое программирование
- •Глава 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. Программирование на языке пролог
- •Общие сведения о языке Пролог. Язык Пролог как система, реализующая логический вывод в исчислении предикатов первого порядка.
- •Фразы Хорна как средство представления знаний.
- •Синтаксис языка Пролог.
- •Фразы, термы, факты, правила.
- •Константы:
- •Простейшая программа на Прологе
- •Выполнение запроса в Прологе.
- •Неудача запроса и возврат назад.
- •Декларативная и процедурная семантика Пролога.
- •Рекурсивные процедуры.
- •Списки.
- •Операторы.
- •Средства управления ходом выполнения программы. Предикат сократить (отсечение).
- •Отрицание как неудача запроса.
- •Встроенные предикаты.
- •Типы отношений.
- •Ограничения, обеспечивающие целостность отношений.
- •Свойства отношений.
- •Подходы к программированию на языке Пролог.
Вычисления в лисПе.
Программа, написанная на языке Лисп, состоит из форм и функций. Под формой понимается такое символьное выражение, значение которого может быть найдено интерпретатором.
К формам относят:
самоопределенные формы. Это объекты, представляющие лишь сами себя: числа, константы Т и NIL, а также знаки, строки, битовые векторы, ключи, начинающиеся с двоеточия и определяемые через ключевое слово &KEY в лямбда-списке;
символы, использующиеся в качестве переменных;
формы в виде списочной структуры, которыми являются:
вызовы функций и лямбда-вызовы;
специальные формы: SETQ, QUOTE и другие для управления вычислениями и контекстом,
макровызовы.
У каждой формы свой синтаксис и семантика, основанные на едином способе записи и интерпретации.
Управляющие структуры в языке Лисп выглядят внешне как вызовы функций:
они записываются в виде скобочного выражения, первый элемент которого действует как имя управляющей структуры, а остальные элементы как аргументы;
результатом вычисления, как и у функции, является значение, т.е. управляющие структуры представляют собой формы.
Однако управляющие структуры не являются вызовами функций, разные предложения используют аргументы по-разному.
Наиболее важные с точки зрения программирования синтаксические формы по их использования можно разделить на следующие группы.
Работа с контекстом:
QUOTE или блокировка вычисления;
Вызов функции и лямбда –вызов;
Предложения LET и LET*.
Последовательное исполнение:
PROG1, PROG2 и PROGN.
Разветвление вычислений:
условные предложения: COND, IF, WHEN, UNLESS;
выбирающее предложение CASE.
Итерации:
циклические предложения DO, DO*, LOOP, DOTIMES, DOUNTIL.
Передача управления:
предложения PROG, GO, RETURN.
Динамическое управление вычислением:
THROW, CATCH, BLOCK.
Предложение let создает локальную связь внутри формы:
(LET ((m1 знач1) (m2 знач2)...) форма1 форма2 ...).
Предложение LET вычисляется по следующему алгоритму:
статические переменные m1, m2, ... связываются (одновременно) с соответствующими значениями знач1, знач2, ... ;
слева направо вычисляются значения формы1, формы2, ... ;
значение последней формы возвращается в качестве значения всей формы LET:
после вычисления связи статических переменных ликвидируются и любые их изменения извне не будут видны.
Предложения LET можно делать вложенными одно в другое:
(LET ((x ‘a) (y ‘b)) (LET ((z ‘c)) (LIST x y z))) => (a b c)
(LET ((x (LET ((z ‘a)) z)) (y ‘b)) (LIST x y)) => (a b)
(LET ((x 1) (y (+ x 1))) (LIST x y)) => ERROR
При вычислении у У и Х еще нет связи. Значения переменным присваиваются одновременно. Это означает, что значения всех переменных mi вычисляются до того, как осуществляется связывание с формальными параметрами.
Подобной ошибки можно избежать с помощью формы LET*, которая вычисляет значения переменных последовательно:
(LET* ((m1 знач1) (m2 знач2)...) форма1 форма2 ...).
(LET* ((x 1) (y (+ x 1))) (LIST x y)) => (1 2)
Продемонстрируем, что связи переменных формы LET восстанавливаются после выхода из формы:
(setq x 2) => 2
(let ((x 0)) (setq x 1)) => 1
x => 2
Представим две формы записи присваивания значений переменным:
((lambda (x y)(list x y)) '(+ 2 3) 'c) => ((+ 2 3) c)
(let ((x '(+ 2 3))(y 'c))(list x y)) => ((+ 2 3) c),
для вложенных lambda, let:
((LAMBDA (x y)((lambda (z) (list x y z))'c))'a 'b) => (a b c)
(let ((x 'a)(y 'b))(let ((z 'c))(list x y z))) => (a b c)
((lambda (x y)(list x y))((lambda (z) z)'a)'b) => (a b)
(let ((x (let ((z 'a)) z))(y 'b))(list x y)) => (a b)
