
- •1. Предмет ии Хар-ка понятия интеллектуальности
- •2.Декларат и процедур.
- •3.Понятие предиката.Логика рассуждений.
- •4.Структура программы(разделы в языке пролог)
- •5.Понятие цели, внутренняя и внешняя
- •6.Факты и правила
- •7.Откат и отсечение
- •8.Организация рекурсии
- •9.Вычисление частичных сумм рядов
- •10.Списки в турбопрологе
- •11.Списки в лиспе
- •13.Определение функции в лиспе
- •14.Рекурсии в лиспе
11.Списки в лиспе
Язык функционального программирования Лисп (Lisp) был разработан в 1958 году Джоном МакКарти (JohnMcCarthy). Название Лисп (Lisp) происходит от Listprocessing(обработка списков). Основным фундаментальным типом данных в языке LISP является список. Название языка LISP образовано от "LIStProcessing" ("обработка списка").
Список рекурсивно определяется так:
Список ::= NIL | (S ─ выражение . Список)
Согласно этому определению любой непустой список является точечной парой.
Приведем примеры списков:
(LISP Functionallanguage)
(5 6 (8 (9)) 23 NIL)
Важно выделить понятие пустого списка, который не содержит элементов, он обозначается () или атомом NIL. Например, (NIL ()) ─ список, состоящий из двух пустых списков. Оперативная память компьютера, на котором "работает" LISP, логически разбивается на маленькие области, которые называются списочными ячейками. Списочная ячейка состоит из полей с именами CAR и CDR, каждое из которых содержит указатель. Указатель может ссылаться на другую списочную ячейку или на другой объект языка LISP, например, на атом. Указатели между ячейками образуют как бы цепочку, по которой можно из предыдущей ячейки попасть в следующую и так, наконец, до атомарных объектов. Каждый атом, известный системе, записан в определенном месте памяти лишь один раз. Графически списочную ячейку будем представлять прямоугольником, разделенным на поля CAR и CDR. Указатель изображается в виде стрелки, начинающейся в одной из частей прямоугольника и заканчивающейся на изображении другой ячейки или атоме, на который ссылается указатель.
Пример 1. Изобразим список (A B C D) в графической нотации:
Основные функции обработки списков
К операциям выделения отдельных частей списков и создания из них новых структур сводятся многие алгоритмы обработки символьной информации. Основными функциями, на основе которых выполняются указанные действия, являются встроенные функции CAR, CDR и CONS. Эти функции определяются на основе функций CAR, CDR, CONS. Список - частный случай точечной пары, то применимы функции, аргументы которых заданы точечными парами.
В Лиспе имеется ряд других полезных функций для обработки списков:
LAST ─ выделяет последний элемент списка (результат - список);
NTH ─ выделяет n-й элемент списка;
SUBST ─выполняет замену элементов в списке;
BUTLAST ─ выделяет список без последних элементов;
MEMBER ─ проверяет принадлежность элемента списку;
LENGTH ─вычисляет длину списка;
REVERSE ─ выполняет обращение списка;
ADJOIN ─добавляет элемент в множество, представленное списком;
REMOVE─ удаляет элемент из списка.
13.Определение функции в лиспе
Определение функций
Чтобы определить функцию, необходимо указать количество аргументов функций , а также правило f, устанавливающее суть отображения.
В языке Лисп для этого применяется лямбда-выражение:
(lambda ({переменная}*){форма}*)
Здесь конструкция ({переменная}*) называется лямбда ─ списком и представляет собой список формальных параметров, которые соответствуют аргументам функции. Последовательность форм влямбда выражении определяет правило формирования значения функции и называется телом функции. Пусть требуется определить функцию, вычисляющую х5. Тогда лямбда-выражение будет иметь вид:
(lambda (х) ( * х ххх х))
Чтобы задать функцию, строящую список из двух аргументов х и у, можно использовать выражение
(lambda (x у) (cons x (cons у nil)))
Для того, чтобы применить функцию, определенную лямбда-выражением, к некоторым аргументам, необходимо в вызове функции записать вместо имени функции лямбда-выражение. К примеру:
((lambda (x)(* x xxx x)) 4) ─> 1024
((lambda (x y) (cons x (cons у nil))) 'a 'b) ─ > (A B)
В первом примере формальному параметру X лямбда ─ списка присваивается фактическое значение 4, а затем вычисляется тело лямбда ─ выражения. Во втором примере формальным параметрам X и У назначаются значения фактических параметров, заданных атомами А и В, из которых строится список (А В). После произведенных вычислений связи между формальными параметрами и значениями фактических параметров разрушаются.
Вычисление с помощью лямбда ─ вызовов требует каждый раз при очередном вызове необходимо снова описывать тело функции. Проблема решается, если слямбда ─ выражением связать некоторое имя (символ). Для связи имени и лямбда ─ выражения в Лиспе применяется форма DEFUN:
( defun имя лямбда ─ выражение )
При этом для упрощения записи влямбда ─ выражении опускается слово LAMBDA и скобки. В итоге получаем:
(defun имя лямбда ─ список {форма}*)
Результатом вызова формы DEFUN является имя определенной функции. Например:
(defunstepen 5 ( х ) (* х ххх х)) ─ >STEPEN 5
(defunspisok ( ху) (cons x (cons у nil))) ─ > SPISOK
Теперь указанные выше лямбда ─ вызовы можно заменить следующими вызовами:
(stepen 5 4) ─ > 1024
(spisok 'а b) ─ > (АВ)
Отметим, что имя функции представляется символом. Поэтому можно говорить о том, что DEFUN устанавливает связь между символом и определением функции. Создавать функции можно в любом текстовом редакторе и хранить в файле с расширением .lsp. Определения функций могут храниться в файлах и загружаться используя функцию LOAD:
(load<имя файла>)
Эта функция загружает файл выражений и выполняет эти выражения.
<Имя файла> - это строковая константа, которая представляет собой имя
файла без расширения (подразумевается расширение ".lsp"). Если
операция успешно завершена, LOAD возвращает имя последней функции, определенной в файле. Если операция не выполнена, LOAD возвращает имя файла в виде строкового выражения.
После запуска интерпретатора необходимо функцией load загрузить файл с библиотекой, к примеру, созданных пользователем функций на диске С: в каталоге PROG.
>(load “C:\\prog\\bibl.lsp”)