Автор работы: Пользователь скрыл имя, 19 Февраля 2011 в 15:30, лабораторная работа
Цель: Ознакомиться со средой MuLisp. Изучить базовые функции Лиспа, символы и их свойства, а также средства для работы с числами.
1.Основные положения программирования на Лиспе.
2.Загрузка системы, системный редактор.
3.Базовые функции языка. Символы, свойства символов.
4.Средства языка для работы с числами.
5.Задание к лабораторной работе.
6.Вопросы.
(T (PRINC «ошибка ввода»))))
7. Вопросы.
1. Для чего используется предложение LET?
2. В чем его отличие от предложения LET*?
3. Чем различаются функции COND и IF?
4. Каковы возвращаемые ими значения?
5. Чем различаются функции PROG1 и PROGN?
6. Почему не желательно использовать
операторы передачи управления? Чем
их можно заменить?
Лабораторная работа №4.
Тема: Рекурсия в Лиспе. Функционалы и макросы.
Цель: Изучить основы программирования с применением рекурсии. Научиться работать с функционалами и макросами.
1. Рекурсия. Различные формы рекурсии.
2. Применяющие функционалы.
3. Отображающие функционалы.
4. Макросы.
5. Задание к лабораторной работе.
6.
Вопросы.
1. Рекурсия. Различные формы рекурсии.
Основная идея рекурсивного определения заключается в том, что функцию можно с помощью рекуррентных формул свести к некоторым начальным значениям, к ранее определенным функциям или к самой определяемой функции, но с более «простыми» аргументами. Вычисление такой функции заканчивается в тот момент, когда оно сводится к известным начальным значениям.
Рекурсивная процедура, во-первых содержит всегда по крайней мере одну терминальную ветвь и условие окончания. Во-вторых, когда процедура доходит до рекурсивной ветви, то функционирующий процесс приостанавливается, и новый такой же процесс запускается сначала, но уже на новом уровне. Прерванный процесс каким-нибудь образом запоминается. Он будет ждать и начнет исполняться лишь после окончания нового процесса. В свою очередь, новый процесс может приостановиться, ожидать и т. д.
Будем говорить о рекурсии по значению и рекурсии по аргументам. В первом случае вызов является выражением, определяющим результат функции. Во втором - в качестве результата функции возвращается значение некоторой другой функции и рекурсивный вызов участвует в вычислении аргументов этой функции. Аргументом рекурсивного вызова может быть вновь рекурсивный вызов и таких вызовов может быть много.
Рассмотрим следующие формы рекурсии:
Рекурсия называется простой, если вызов функции встречается в некоторой ветви лишь один раз. Простой рекурсии в процедурном программировании соответствует обыкновенный цикл.
Для
примера напишем функцию вычисления чисел
Фибоначчи (F(1)=1; F(2)=1;
F(n)=F(n-1)+F(n-2) при n>2):
(DEFUN FIB (N)
(IF (> N 0)
(IF (OR N=1 N=2) 1
(+ (FIB (- N 1)) (FIB (- N 2))))
‘ОШИБКА_ВВОДА))
Рекурсию называют параллельной, если она встречается одновременно в нескольких аргументах функции:
(DEFUN f ...
...(g ... (f ...) (f ...) ...)
...)
Рассмотрим использование параллельной рекурсии на примере преобразования списочной структуры в одноуровневый список:
(DEFUN PREOBR (L)
(COND
Рекурсия является взаимной между двумя и более функциями, если они вызывают друг друга:
(DEFUN f ...
...(g ...) ...)
(DEFUN g ...
...(f ...) ...)
Для
примера напишем функцию обращения или
зеркального отражения в виде двух взаимно
рекурсивных функций следующим образом:
(DEFUN obr (l)
(COND ((ATOM l) l)
(T (per l nil))))
(DEFUN per (l res)
(COND ((NULL l) res)
(T (per (CDR l)
2. Применяющие функционалы.
Функции, которые позволяют вызывать другие функции, т. е. применять функциональный аргумент к его параметрам называют применяющими функционалами. Они дают возможность интерпретировать и преобразовывать данные в программу и применять ее в вычислениях.
APPLY
APPLY является функцией двух аргументов, из которых первый аргумент представляет собой функцию, которая применяется к элементам списка, составляющим второй аргумент функции APPLY:
(APPLY fn
список)
_(SETQ a ‘+) р +
_(APPLY a ‘(1 2 3)) р 6
_(APPLY
‘+ ‘(4 5 6)) р 15
FUNCALL.
Функционал FUNCALL по своему действию аналогичен APPLY, но аргументы для вызываемой он принимает не списком, а по отдельности:
(FUNCALL fn x1 x2
... xn)
_(FUNCALL ‘+ 4 5 6) р 15
FUNCALL и APPLY позволяют задавать вычисления
(функцию) произвольной формой, например,
как в вызове функции, или символом, значением
которого является функциональный объект.
Таким образом появляется возможность
использовать синонимы имени функции.
С другой стороны, имя функции можно использовать
как обыкновенную переменную, например
для хранения другой функции (имени или
лямбда-выражения), и эти два смысла (значение
и определение) не будут мешать друг другу:
_(SETQ list ‘+) р +
_(FUNCALL list 1 2) р 3
_(LIST
1 2) р
(1 2)
3. Отображающие функционалы.
Отображающие или MAP-функционалы являются функциями, которые являются функциями, которые некоторым образом отображают список (последовательность) в новую последовательность или порождают побочный эффект, связанный с этой последовательностью. Каждая из них имеет более двух аргументов, значением первого должно быть имя определенной ранее или базовой функции, или лямбда-выражение, вызываемое MAP-функцией итерационно, а остальные аргументы служат для задания аргументов на каждой итерации. Естественно, что количество аргументов в обращении к MAP-функции должно быть согласовано с предусмотренным количеством аргументов у аргумента-функции. Различие между всеми MAP-функциями состоит в правилах формирования возвращаемого значения и механизме выбора аргументов итерирующей функции на каждом шаге.
Рассмотрим основные типы MAP-функций.
Значение этой функции вычисляется путем применения функции fn к последовательным элементам xi списка, являющегося вторым аргументом функции. Например в случае одного списка получается следующее выражение:
(MAPCAR fn ‘(x1 x2 ... xn))
В
качестве значения функционала возвращается
список, построенный из результатов вызовов
функционального аргумента MAPCAR.
_(MAPCAR ‘LISTP ‘((f) h k (i u)) р (T NIL NIL T)
_(SETQ x ‘(a b c)) р (a b c)
_(MAPCAR ‘CONS x ‘(1 2 3)) р ((a . 1) (b . 2) (c . 3))
MAPLIST действует подобно MAPCAR,
но действия осуществляет не над элементами
списка, а над последовательными CDR этого
списка.
_(MAPLIST ‘LIST ‘((f) h k (i u)) р (T T T T)
_(MAPLIST
‘CONS ‘(a b c) ‘(1 2 3)) р (((a b c) 1 2 3) ((b c) 2 3) ((c ) 3))
Функционалы MAPCAR и MAPLIST используются для программирования циклов специального вида и в определении других функций, поскольку с их помощью можно сократить запись повторяющихся вычислений.
Функции MAPCAN
и MAPCON
являются аналогами функций MAPCAR и MAPLIST. Отличие состоит в том,
что MAPCAN
и MAPCON
не строят, используя LIST, новый список из результатов,
а объединяют списки, являющиеся результатами,
в один список.
4. Макросы.
Программное формирование выражений наиболее естественно осуществляется с помощью макросов. Макросы дают возможность писать компактные, ориентированные на задачу программы, которые автоматически преобразуются в более сложный, но более близкий машине эффективный лисповский код. При наличии макросредств некоторые функции в языке могут быть определены в виде макрофункций. Такое определение фактически задает закон предварительного построения тела функции непосредственно перед фазой интерпретации.