ЗАДАНИЯ И МЕТОДИЧЕСКИЕ УКАЗАНИЯ к лабораторным работам по дисциплине «Функциональное»

advertisement
ЗАДАНИЯ И МЕТОДИЧЕСКИЕ УКАЗАНИЯ
к лабораторным работам
по дисциплине «Функциональное»
для студентов 4 курса
дневного отделения факультета АВТ,
обучающихся по направлению
230100.62 — Информатика и ВТ
ОГЛАВЛЕНИЕ
Лабораторная работа №1. Основы функционального программирования (4 часа)
....................................................................................................................................... 3
Лабораторная работа №2. Рекурсивные структуры данных (списки и деревья) (4
часа) ............................................................................................................................ 10
Лабораторная работа №3. Ассоциативные списки и списки свойств символа. (4
часа) ............................................................................................................................ 19
Лабораторная работа №4. Функционалы. (4 часа) ................................................ 24
2
Лабораторная работа №1.
Основы функционального программирования
(4 часа)
Цель работы:
Приобретение практических навыков написания и отладки программ на
языке функционального программирования Lisp.
Задание:
В соответствии с вариантом написать программу на языке
функционального программирования Lisp.
Вариант 1:
 Определить рекурсивную функцию, возвращающую значение n-го
члена ряда Фибоначчи: f(0)=0, f(1)=1, f(n)=f(n-1)+f(n-2).
 Определить функцию, вычисляющую, сколько всего атомов в списке
(списочной структуре).
Вариант 2:
 Определить рекурсивную функцию для удаления последнего элемента
списка.
 Определить функцию, вычисляющую глубину списка (самой глубокой
ветви).
Вариант 3:
 Определить рекурсивную функцию, возвращающую произведение
двух целых положительных чисел (использовать суммирование).
 Определить функцию, реализующую головоломку «Ханойские
башни».
Вариант 4:
 Определить рекурсивную функцию, возвращающую последний
элемент списка.
3
 Определить функцию, подсчитывающую число элементов списка без
какого-либо указываемого элемента.
Вариант 5:
 Определить рекурсивную функцию, возвращающую значение суммы
ряда целых четных чисел от 2 до n.
 Определить функцию (first_elem x y), которая возвращает первый
элемент, входящий в оба списка x и y, в противном случае nil.
Вариант 6:
 Определить рекурсивную функцию, возвращающую значение n-го
члена ряда Фибоначчи: f(0)=0, f(1)=1, f(n)=f(n-1)+f(n-2).
 Определить функцию, вычисляющую, сколько всего атомов в списке
(списочной структуре).
Вариант 7:
 Определить рекурсивную функцию для удаления последнего элемента
списка.
 Определить функцию, вычисляющую глубину списка (самой глубокой
ветви).
Вариант 8:
 Определить рекурсивную функцию, возвращающую произведение
двух целых положительных чисел (использовать суммирование).
 Определить функцию, реализующую головоломку «Ханойские
башни».
Вариант 9:
 Определить рекурсивную функцию, возвращающую последний
элемент списка.
 Определить функцию, подсчитывающую число элементов списка без
какого-либо указываемого элемента.
Вариант 10:
4
 Определить рекурсивную функцию, возвращающую значение суммы
ряда целых четных чисел от 2 до n.
 Определить функцию (first_elem x y), которая возвращает первый
элемент, входящий в оба списка x и y, в противном случае nil.
Содержание отчета (отчет в электронном виде):
 отчет сохранить в файле с именем АВТ-000 Иванов (лр1-4).doc;
 титульный лист (образец можно скачать по адресу
http://ermak.cs.nstu.ru/flp/2014_fp_labworks_title_page.doc);
 цель работы;
 задание;
 исходный текст программы;
 выводы по работе.
5
Теоретические сведения
Базовые функции
В Lisp’е существует пять основных функций, называемых базовыми:
 (car list) — отделяет голову списка (первый элемент списка);
 (cdr list) — отделяет хвост списка (все элементы, кроме первого,
представленные в виде списка);
 (cons head tail) — соединяет элемент и список в новый список, где
присоединенный элемент становится головой нового списка;
 (equal object1 object2) — проверяет объекты на равенство;
 (atom object) — проверяет, является ли объект атомом.
Так как функции equal и atom возвращают значения nil или t, их можно
назвать базовыми предикатами.
Рассмотрим примеры для перечисленных функций:
> (car ‘(one two three))
ONE
> (car ‘(one))
ONE
> (car ‘())
NIL
> (cdr ‘(first second third))
(SECOND THIRD)
> (cdr ‘(first))
NIL
> (cdr ‘())
NIL
> (cons 1 ‘(2 3))
(1 2 3)
> (cons 1 nil)
(1)
> (cons nil nil)
(NIL)
> (equal ‘(1 2 3) ‘(1 2 3))
T
> (equal ‘(1 2 3) ‘(3 2 1))
NIL
> (equal ‘one ‘two)
6
NIL
> (atom ‘one)
T
> (atom 1)
T
> (atom (1))
NIL
Предложения prog1, prog2, progN
(progX form1 form2 … formN)
Назначение: выполнение последовательных вычислений.
Пример:
>(progn (setq x 2) (setq y (* 3 x)))
6
Предложение cond
(cond (predicate1 form1) (predicate2 form2) … (predicateN formN))
Назначение: выполнение ветвления.
Пример: функция, определяющая тип выражения (пустой список, атом
или список).
>(defun deftype(arg)
(cond ((null arg) ‘empty) ((atom arg) ‘atom) (t ‘list)))
DEFTYPE
>(deftype ‘(a b c))
LIST
>(deftype (atom ‘(a t o m)))
EMPTY
Предложение if
(if (condition) thenform elseform)
Назначение: выполнение ветвления.
Пример:
>(setq x ‘(a b c))
(A B C)
>(if (atom x) ‘atom ‘list)
LIST
7
Предложение do
(do ((var1 value1) (var1 value1) … (var1 value1))
(endcondition form11 form12)
form 21 form 22)
Назначение: выполнение циклических вычислений.
Пример: вычисление суммы целых чисел от n до 0.
>(defun count (n)
(do ((result n))
;;начальное значение
((= n 0) result)
;;условие окончания цикла
(setq n (- n 1))
(setq result (+ result n))
)
)
COUNT
>(count 5)
15
Простая рекурсия
Функция является рекурсивной, если в ее определении содержится вызов
этой же функции. Рекурсия является простой, если вызов функции встречается
в некоторой ветви лишь один раз. Простой рекурсии в процедурном
программировании соответствует обыкновенный цикл.
Пример: построение копии списка.
>(defun listcopy (list)
(cond ((null list) nil)
(t (cons (car list) (listcopy (cdr list))))))
LISTCOPY
>(listcopy ‘(a b c))
(A B C)
;;граничное условие
;;рекурсия
Трассировка программы
Для отладки программы можно использовать возможности трассировки.
Трассировка позволяет проследить процесс нахождения решения.
8
Для того, чтобы включить трассировку, можно воспользоваться
следующей директивой:
(trace function)
Назначение: включает режим трассировки.
Пример:
>(trace listcopy)
(LISTCOPY)
>(listcopy '(a b))
Entering: LISTCOPY, Argument list: ((A B))
Entering: LISTCOPY, Argument list: ((B))
Entering: LISTCOPY, Argument list: (NIL)
Exiting: LISTCOPY, Value: NIL
Exiting: LISTCOPY, Value: (B)
Exiting: LISTCOPY, Value: (A B)
(A B)
(untrace function)
Назначение: отключает режим трассировки.
Пример:
>(untrace listcopy)
NIL
Контрольные вопросы:
1.
2.
3.
9
Лабораторная работа №2.
Рекурсивные структуры данных (списки и деревья)
(4 часа)
Цель работы:
Получение навыков написания программ на языке функционального
программирования Lisp для работы с рекурсивными структурами данных.
Задание:
В соответствии с вариантом написать программу для работы со списком,
элементами которого являются бинарные деревья.
Вариант 1:
 Имеется список, элементы которого — непустые бинарные деревья.
Для каждого элемента списка найти среднее арифметическое
листьевых вершин, из полученных результатов сформировать список.
Выполнить реверс для полученного списка.
Вариант 2:
 Имеется список, элементы которого — непустые бинарные деревья.
Для каждого элемента списка проверить упорядоченность, из
полученных результатов сформировать список. Получить n-й элемент
списка-результата.
Вариант 3:
 Имеется список, элементы которого — бинарные деревья, пустые и
непустые. Удалить из списка все пустые бинарные деревья, затем
вывести на экран все элементы полученного списка в виде деревьев.
Вариант 4:
 Имеется список, элементы которого — непустые бинарные деревья.
Для каждого элемента списка найти глубину дерева, из полученных
10
результатов сформировать список. Для полученного списка выполнить
циклический сдвиг вправо на заданное число элементов.
Вариант 5:
 Имеется список, элементы которого — непустые бинарные деревья.
Для каждого элемента списка найти число вершин, значения которых
лежат в определенном диапазоне, из полученных результатов
сформировать список. Из полученного списка удалить 2-ой, 4-ой и т.д.
элементы.
Вариант 6:
 Имеется список, элементы которого — непустые бинарные деревья.
Для каждого элемента списка выполнить преобразование дерева в
список. В полученных списках заменить все элементы, равные 0, на -1.
Вариант 7:
 Имеется список, элементы которого — непустые бинарные деревья.
Для каждого элемента списка найти количество отрицательных узлов
дерева, из полученных результатов сформировать список.
Преобразовать полученный список арабских чисел (максимальное
значение 10) в список римских чисел.
Вариант 8:
 Имеется список, элементы которого — непустые бинарные деревья.
Для каждого элемента списка найти количество вершин бинарного
дерева, значения которых не равны 0, из полученных результатов
сформировать список. Для полученного списка подсчитать количество
заданных элементов в списке.
Вариант 9:
 Имеется список, элементы которого — непустые бинарные деревья.
Для каждого элемента списка найти среднее арифметическое
положительных узлов дерева, из полученных результатов
сформировать список. Для полученного списка подсчитать количество
элементов списка без какого-либо указываемого элемента.
11
Вариант 10:
 Имеется список, элементы которого — непустые бинарные деревья.
Для каждого элемента списка найти количество вершин бинарного
дерева, значения которых равны 0, из полученных результатов
сформировать список. Для полученного списка подсчитать количество
элементов списка, значения которых лежат в определенном диапазоне.
Содержание отчета (отчет в электронном виде):
 отчет сохранить в файле с именем АВТ-000 Иванов (лр1-4).doc;
 титульный лист (образец можно скачать по адресу
http://ermak.cs.nstu.ru/flp/2014_fp_labworks_title_page.doc);
 цель работы;
 задание;
 исходный текст программы;
 выводы по работе.
12
Теоретические сведения
Рекурсия по значению и рекурсия по аргументу
Можно говорить о двух видах рекурсии: рекурсии по значению и
рекурсии по аргументу. Рекурсия по значению определяется в случае, если
рекурсивный вызов является выражением, определяющим результат функции.
Рекурсия по аргументу существует в функции, возвращаемое значение которой
формирует некоторая нерекурсивная функция, в качестве аргумента которой
используется рекурсивный вызов.
Вот несколько примеров простой рекурсии.
Возведение числа x в степень n с помощью умножения (рекурсия по
аргументу):
> (defun power (x n)
(cond
;x0=1 (любое число в нулевой степени равно 1)
((= n 0) 1)
;xn=x(n-1)*n (значение x в степени n вычисляется возведением x в степень n-1
;и умножением результата на n)
(t (* (power x (- n 1)) x))))
> (power 2 3)
8
> (power 10 0)
1
Копирование списка (рекурсия по аргументу):
> (defun copy_list (list)
(cond
;копией пустого списка является пустой список
((null list) nil)
;копией непустого списка является список, полученный из головы и копии
;хвоста исходного списка
(t (cons (car list) (copy_list (cdr list))))))
COPY_LIST
>(copy_list ‘(1 2 3))
(1 2 3)
>(copy_list ())
NIL
13
Определение принадлежности элемента списку (рекурсия по значению):
> (defun member (el list)
(cond
;список просмотрен до конца, элемент не найден
((null list) nil)
;очередная голова списка равна искомому элементу, элемент найден
((equal el (car list)) t)
;если элемент не найден, продолжить его поиск в хвосте списка
(t (member el (cdr list)))))
MEMBER
> (member 2 '(1 2 3))
T
> (member 22 '(1 2 3))
NIL
Соединение двух списков (рекурсия по аргументу):
> (defun append (list1 list2)
(cond
;соединение пустого списка и непустого дает непустой список
((null list1) list2)
;соединить голову первого списка и хвост первого списка,
;соединенный со вторым списком
(t (cons (car list1) (append (cdr list1) list2)))))
APPEND
> (append '(1 2) '(3 4))
(1 2 3 4)
> (append '(1 2) ())
(1 2)
> (append () '(3 4))
(3 4)
> (append () ())
NIL
Реверс списка (рекурсия по аргументу):
> (defun reverse (list)
(cond
;реверс пустого списка дает пустой список
((null list) nil)
;соединить реверсированный хвост списка и голову списка
(t (append (reverse (cdr list)) (cons (car list) nil)))))
14
REVERSE
> (reverse '(one two three))
(THREE TWO ONE)
> (reverse ())
NIL
Другие виды рекурсии
Рекурсию можно назвать простой, если в функции присутствует лишь
один рекурсивный вызов. Такую рекурсию можно назвать еще рекурсией
первого порядка. Но рекурсивный вызов может появляться в функции более,
чем один раз. В таких случаях можно выделить следующие виды рекурсии:
 параллельная рекурсия — тело определения функции function_1
содержит вызов некоторой функции function_2, несколько аргументов
которой являются рекурсивными вызовами функции function_1.
(defun function_1 … (function_2 … (function_1 …) … (function_1 …) …
)…)
 взаимная рекурсия — в теле определения функции function_1
вызывается некоторая функции function_2, которая, в свою очередь,
содержит вызов функции function_1.
(defun function_1 … (function_2 … ) … )
(defun function_2 … (function_1 … ) … )
 рекурсия более высокого порядка — в теле определения функции
аргументом рекурсивного вызова является рекурсивный вызов.
(defun function_1 … (function_1 … (function_1 …) … ) … )
Рассмотрим примеры параллельной рекурсии. В разделе, посвященном
простой рекурсии, уже рассматривался пример копирования списка (функция
copy_list), но эта функция не выполняет копирования элементов списка в
случае, если они являются, в свою очередь также списками. Для записи
функции, которая будет копировать список в глубину, придется
воспользоваться параллельной рекурсией.
> (defun full_copy_list (list)
(cond
15
;копией пустого списка является пустой список
((null list) nil)
;копией элемента-атома является элемент-атом
((atom list) list)
;копией непустого списка является список, полученный из копии головы
;и копии хвоста исходного списка
(t (cons (full_copy_list (car list)) (full_copy_list (cdr list))))))
FULL_COPY_LIST
> (full_copy_list '(((1) 2) 3))
(((1) 2) 3)
> (full_copy_list ())
NIL
Не обойтись без параллельной рекурсии при работе c бинарными
деревьями. Бинарное дерево, как и все прочие данные, представляются в Lisp’е
в виде списков. Например, упорядоченное бинарное дерево можно представить
в виде списка (4 (2 (1 nil nil) (3 nil nil)) (5 nil nil)). Константы nil представляют
пустые деревья. В таком представлении первый элемент списка — это узел
дерева, второй элемент списка — левое поддерево и третий элемент списка —
правое поддерево. Другой вариант представления дерева— (((nil 1 nil) 2 (nil 3
nil)) 4 (nil 5 nil)). В таком представлении первый элемент списка — это левое
поддерево, второй элемент списка — узел дерева и третий элемент списка —
правое поддерево. Можно использовать и другие варианты представления
деревьев. Рассмотрим простой пример работы с бинарным деревом — обход
дерева и подсчет числа узлов дерева. Для работы с элементами дерева, которые
являются, по сути, элементами списка, очень удобно использовать стандартные
функции Lisp’а, для получения первого, второго и третьего элементов списка
— fist, second и third, соответственно.
> (defun node_counter (tree)
(cond
;число узлов пустого дерева равно 0
((null tree) 0)
;число узлов непустого дерева складывается из: одного корня,
;числа узлов левого поддерева и числа узлов правого поддерева
(t (+ 1 (node_counter (second tree)) (node_counter (third tree))))))
NODE_COUNTER
16
> (node_counter '(4 (2 (1 nil nil) (3 nil nil)) (5 nil nil)))
5
> (node_counter nil)
0
Пример взаимной рекурсии — реверс списка. Так как рекурсия взаимная,
в примере определены две функции: reverse и rearrange. Функция rearrange
рекурсивна сама по себе.
> (defun reverse (list)
(cond
((atom list) list)
(t (rearrange list nil)))))
REVERSE
> (defun rearrange (list result)
(cond
((null list) result)
(t (rearrange (cdr list) (cons (reverse (car list)) result)))))
REARRANGE
> (reverse '(((1 2 3) 4 5) 6 7))
(7 6 (5 4 (3 2 1)))
Пример рекурсии более высокого порядка — второго. Классический
пример функции с рекурсией второго порядка — функция Аккермана.
Функция Аккермана определяется следующим образом:
B (0, n) = n+1
B (m, 0) = B (m-1, 0)
B (m, n) = B (m-1, B (m, n-1))
где m>=0 и n>=0.
> (defun ackerman
(cond
((= n 0) (+ n 1))
((= m 0) (ackerman (- m 1) 1))
(t (ackerman (- m 1) (ackerman m (- n 1))))))
ACKERMAN
> (ackerman 2 2)
7
> (ackerman 2 3)
9
17
> (ackerman 3 2)
29
Контрольные вопросы:
1.
2.
18
Лабораторная работа №3. Ассоциативные списки и списки свойств
символа.
(4 часа)
Цель работы:
Получение навыков написания программ на языке функционального
программирования Lisp для работы с ассоциативными списками и списками
свойств символа.
Задание:
В соответствии с вариантом написать программу для работы с
ассоциативным списком, вторым элементом точечных пар которого является
символ, обладающий списком свойств.
Вариант 1:
 Имеется ассоциативный список, вторым элементом точечных пар
которого является символ. Организовать формирование списка
свойств символа, определяемого по заданному ключу. Ввод имен
свойств и их значений выполнить с клавиатуры. Организовать вывод
ассоциативного списка и списка свойств его элементов в наглядном
виде.
Вариант 2:
 Имеется ассоциативный список, вторым элементом точечных пар
которого является символ. Удалить заданное свойство у символа
точечной пары, доступного по заданному ключу.
Вариант 3:
 Имеется ассоциативный список, вторым элементом точечных пар
которого является символ. Изменить значение заданного свойства на
новое заданное значение у всех символов ассоциативного списка, у
которых это свойство имеется.
19
Вариант 4:
 Имеется ассоциативный список, вторым элементом точечных пар
которого является символ. Изменить значение заданного свойства на
новое заданное значение у всех символов ассоциативного списка, у
которых это свойство имеется.
Вариант 5:
 Имеется ассоциативный список, вторым элементом точечных пар
которого является символ. Построить список ключей для всех
символов, обладающих заданным свойством в списке свойств символа.
Вариант 6:
 Имеется ассоциативный список, вторым элементом точечных пар
которого является символ — название города. Список свойств каждого
символа — это координаты X и Y города относительно некоторого
начала координат. Найти расстояние между двумя заданными по
ключам городами.
Вариант 7:
 Имеется ассоциативный список, вторым элементом точечных пар
которого является символ — имя некоторого лица. Список свойств
каждого символа — это имена отца и матери. Определить, являются ли
два заданных ключами лица братьями или сестрами.
Вариант 8:
 Имеется ассоциативный список, вторым элементом точечных пар
которого является символ. Удалить элементы ассоциативного списка с
дублирующимися списками свойств символов.
Вариант 9:
 Имеется ассоциативный список, вторым элементом точечных пар
которого является символ. Построить список ключей для всех
символов, не обладающих заданным свойством в списке свойств
символа.
20
Вариант 10:
 Имеется ассоциативный список, вторым элементом точечных пар
которого является символ. Удалить заданное свойство и его значение у
всех символов ассоциативного списка, у которых это свойство
имеется.
Содержание отчета (отчет в электронном виде):
 отчет сохранить в файле с именем АВТ-000 Иванов (лр1-4).doc;
 титульный лист (образец можно скачать по адресу
http://ermak.cs.nstu.ru/flp/2014_fp_labworks_title_page.doc);
 цель работы;
 задание;
 исходный текст программы;
 выводы по работе.
21
Теоретические сведения
Ассоциативные списки
Ассоциативный список (associative list, a-list) — основанная на списках и
точечных парах структура данных — список точечных пар.
((key1 . data1) (key 2 . data 2) … (key n . data n))
Первый элемент пары — ключ (как правило, символ), второй элемент —
данные, которые могут быть любыми лисповскими объектами.
С помощью а-списков можно объединять разнотипные, поименованные
ключами данные в единую структуру данных.
Основные действия с а-списками:
 создание списка;
> (defun pairlis (keys data)
(cond
((null keys) nil)
(t (cons (cons (car keys) (car data))(pairlis (cdr keys) (cdr data))))))
PAIRLIS
> (setq словарь (pairlis '(стол бумага карандаш) '(table paper pencil)))
((СТОЛ . TABLE) (БУМАГА . PAPER) (КАРАНДАШ . PENCIL))
> словарь
((СТОЛ . TABLE) (БУМАГА . PAPER) (КАРАНДАШ . PENCIL))
 поиск данных по ключу;
(defun assoc (key a-list)
(cond
((null a-list) nil)
((equal (caar a-list) key) (cdar a-list))
(t (assoc key (cdr a-list)))))
> (assoc 'бумага словарь)
PAPER
 обновление данных.
Списки свойств символа
22
С символом можно связать список именованных свойств (property list, plist).
Функции для работы со списком свойств символа:
 присваивание нового значения;
(putprop символ значение свойство)
 получение значения;
(get символ свойство)
 удаление значения;
(remprop символ свойство)
 получение списка свойств.
(symbol-plist символ)
> (symbol-plist 'berry)
NIL
> (putprop 'berry 'cranberry 'name)
CRANBERRY
> (putprop 'berry 'red 'colour)
RED
> (putprop 'berry 'sour 'taste)
SOUR
> (symbol-plist 'berry)
(TASTE SOUR COLOUR RED NAME CRANBERRY)
> (remprop 'berry 'colour)
NIL
> (symbol-plist 'berry)
(TASTE SOUR NAME CRANBERRY)
23
Лабораторная работа №4. Функционалы.
(4 часа)
Цель работы:
Получение навыков написания программ на языке функционального
программирования Lisp с использованием функционалов.
Задание:
В соответствии с вариантом написать программу с использованием
функционала.
Вариант 1:
 Имеется список чисел, определить функционал, возвращающий список
квадратов/кубов этих чисел.
Вариант 2:
 Имеется список чисел, определить функционал, возвращающий список
инкрементированных/декрементированных чисел.
Вариант 3:
 Имеется список чисел, определить функционал, возвращающий список
квадратов/квадратных корней чисел.
Вариант 4:
 Имеется список углов в радианах, определить функционал,
возвращающий список sin/cos этих углов.
Вариант 5:
 Имеется список чисел, определить функционал, возвращающий список
квадратов/квадратных корней чисел.
Вариант 6:
 Имеется список чисел, определить функционал, возвращающий список
квадратов/кубов этих чисел.
24
Вариант 7:
 Имеется список чисел, определить функционал, возвращающий список
инкрементированных/декрементированных чисел.
Вариант 8:
 Имеется список чисел, определить функционал, возвращающий список
квадратов/квадратных корней чисел.
Вариант 9:
 Имеется список углов в радианах, определить функционал,
возвращающий список sin/cos этих углов.
Вариант 10:
 Имеется список чисел, определить функционал, возвращающий список
квадратов/квадратных корней чисел.
Содержание отчета (отчет в электронном виде):
 отчет сохранить в файле с именем АВТ-000 Иванов (лр1-4).doc;
 титульный лист (образец можно скачать по адресу
http://ermak.cs.nstu.ru/flp/2014_fp_labworks_title_page.doc);
 цель работы;
 задание;
 исходный текст программы;
 выводы по работе.
25
Теоретические сведения
Функционалы
Функционалы — функции, использующие в качестве аргументов или
результатов другие функции.
Функция копирования списка:
> (defun copy-list (list)
(cond
((null list) nil)
(t (cons (car list) (copy-list (cdr list))))))
COPY-LIST
Функция подсчета суммы элементов списка:
> (defun sum-list (list)
(cond
((null list) 0)
(t (+ (car list) (sum-list (cdr list))))))
SUM-LIST
Внешние отличия в записи этих функций малосущественны, что
позволяет ввести более общую функцию func-list, в определении которой имена
«copy-list» и «sum-list» могут быть заданы как значения параметра fn:
> (defun func-list (list x fn)
(cond
((null list) x)
(t (funcall fn (car list) (func-list (cdr list) x fn)))))
FUNC-LIST
Теперь можно определить новые варианты функций copy-list2 и sum-list2.
> (defun copy-list2 (list)
(func-list list nil (function cons)))
COPY-LIST2
> (defun sum-list2 (list)
(func-list list 0 (function +)))
SUM-LIST2
26
Применяющие функционалы
Применяющий функционал — функция, применяющая функциональный
аргумент к своим параметрам.
Применяющий функционал apply — функция двух аргументов, первый
агрумент-функция применяется к элементам списка, составляющим второй
аргумент.
(apply fn list)
> (apply '+ '(2 3))
5
Применяющий функционал funcall — аналогичен apply, но аргументы для
вызываемой функции принимаются не списком, а поэлементно.
(funcall fn elem1 elem2 … elemn)
> (funcall '+ 2 3)
5
Отображающие функционалы
Отображающий функционал — функция, некоторым образом
отображающая список в новый список или порождающая побочный эффект.
Отображающий функционал mapcar применяет функцию к
последовательным элементам списка, являющегося вторым аргументом.
> (mapcar 'atom '(a (b) c))
(T NIL T)
> (mapcar 'cons '(a b c) '(1 2 3))
((A . 1) (B . 2) (C . 3))
Отображающий функционал maplist работает подобно mapcar, но
действия осуществляются не над элементами списка, а над cdrпоследовательностями списка.
> (maplist 'atom '(a (b) c))
(NIL NIL NIL)
> (maplist 'cons '(a b c) '(1 2 3))
(((A B C) 1 2 3) ((B C) 2 3) ((C) 3))
27
Download