- •Функциональное и логическое программирование
- •Глава 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. Программирование на языке пролог
- •Общие сведения о языке Пролог. Язык Пролог как система, реализующая логический вывод в исчислении предикатов первого порядка.
- •Фразы Хорна как средство представления знаний.
- •Синтаксис языка Пролог.
- •Фразы, термы, факты, правила.
- •Константы:
- •Простейшая программа на Прологе
- •Выполнение запроса в Прологе.
- •Неудача запроса и возврат назад.
- •Декларативная и процедурная семантика Пролога.
- •Рекурсивные процедуры.
- •Списки.
- •Операторы.
- •Средства управления ходом выполнения программы. Предикат сократить (отсечение).
- •Отрицание как неудача запроса.
- •Встроенные предикаты.
- •Типы отношений.
- •Ограничения, обеспечивающие целостность отношений.
- •Свойства отношений.
- •Подходы к программированию на языке Пролог.
Задание параметров в лямбда-списке.
Defun-форма может содержать в себе ключевые слова, с помощью которых аргументы вызова функции можно трактовать по-разному. Ключевые слова начинаются со знака &, и их записывают перед соответствующими параметрами в лямбда-списке. Действие ключевого слова распространяется до следующего ключевого слова. Параметры, перечисленные в списке до первого ключевого слова, являются обязательными.
Необязательные параметры. Значения параметров, объявленных при помощи ключевого слова &OPTIONAL, можно в вызове не указывать. В этом случае они связываются со значением NIL или со значением выражения по умолчанию, если таковое имеется.
Пример: х –обязательный параметр, у – необязательный параметр со значением по умолчанию.
(defun fn (x &optional (y (+ x 2))) (list x y)) => fn
(fn 2) => (2 4) - вычисляется значение по умолчанию
(fn 2 6) => (2 6) - умолчание не используется
Переменное количество параметров. Параметр, указанный после ключевого слова &REST, связывается со списком несвязанных параметров, указанных в вызове. Таким функциям можно передавать переменное количество параметров.
(defun fn (x &optional y &rest z) (list x y z)) => fn
(fn 2 3) => (2 3 nil)
(fn 1 2 3 4 5) => (1 2 (3 4 5))
(defun fn (x &optional y &rest z) (list x y (car z))) => fn
(fn 1 2 3 4 5 ) => (1 2 3)
Ключевые параметры. Если формальные параметры обозначены в определении функции словом &KEY, то соответствующие им фактические параметры можно перечислять в вызове в произвольном порядке при помощи специальных ключей.
Ключом является имя формального параметра, перед которым поставлено двоеточие, например, «:Х». Соответствующий фактический параметр следует за ключом и отделяется от него пробелом.
Ключевые параметры являются необязательными.
(defun fn (&key x y (z 3)) (list x y z)) => fn
(fn :z 4 :x 5 :y 6) => (5 6 4)
(fn :y 6 :x 5) => (5 6 3)
Передача параметров и область их действия.
В программировании используются в основном два способа передачи параметров: по значению и по ссылке.
По значению. Изменения значения формального параметра во время вычисления функции никак не отражаются на значении фактического параметра. С помощью таких параметров можно передавать информацию только внутрь процедур, но не обратно из них. В Лиспе используется передача параметров по значению.
По ссылке. Изменения значений формальных параметров видны извне, и можно возвращать данные из процедуры с помощью присваивания значений формальным параметрам. В Лиспе в чистом виде передачи параметров по ссылке не предусмотрено. Но такой же эффект достигается с помощью:
псевдофункций, меняющих структуры (побочные эффекты их использования отражаются на значениях всех переменных, ссылающихся на некоторый элемент данных);
механизма возврата значений из многозначных функций (напоминает передачу параметров по ссылке).
Формальные параметры функции называют статическими переменными (локальными). Связи статической переменной действительны только в пределах той формы, в которой они определены. После вычисления функции, созданные на это время связи формальных параметров ликвидируются, и происходит возврат к тому состоянию, который был до вызова функции.
(setq x 'а) => а
(defun abc (x) (setq x 'в)) => авс
(авс х) => в
х => а – статическое значение х изменяется, но первоначальное значение не меняется.
Свободные переменные – это переменные, которые используются в функции, но не входят в число ее формальных параметров. Изменения свободных переменных остаются в силе после окончания выполнения функции.
(SETQ x 'r) => r
x => r
(defun abc1 () (setq x 'в)) => abc1
(abc1) => b
x => b – при вызове функции авс1 значение переменной х изменилось
Таким образом, область действия переменных, являющихся формальными параметрами функции, является статической.
Для задания динамических (глобальных) переменных используется директива
(DEFVAR переменная &OPTIONAL начальное значение)
Значение глобальной переменной определяется динамически во время вычисления, а не в зависимости от места ее определения. Значение свободной переменной, являющейся формальным параметром внешнего вызова, вычисляется следующим образом:
использование статической переменной в качестве формального параметра во внешней форме не влияет на значение свободной переменной. Значение свободной переменной определяется в соответствии с глобальным значением, присвоенным на самом внешнем уровне с помощью setq;
для динамической переменной связь, установленная в более внешнем вызове, остается в силе для всех вложенных контекстов, возникающих во время вычисления, если переменная снова не связывается.
(setq x 100) => 100 - глобальное значение х
(defun f1 (x) (f2 2 )) => f1 - статическая переменная х
(defun f2 (y) (list x y)) => f2 - свободная переменная х, ее значением является глобальное значение 100.
(f1 1) => (100 2)
(defvar x 100) => x - начиная с этого момента х определяется динамически по последней связи.
(f1 1) => (1 2)
