Функционалы
Основываясь на едином представлении данных и программ, функции в качестве аргумента можно передать другую функцию. Аргумент, значение которого является функция, называют в функциональном программировании функциональным аргументом, а функцию, имеющую функциональный аргумент – функционалом. Аргументом функции может быть функция, однако, функция может быть и результатом. Такие функции называют функциями с функциональным значением. Функционал также может быть с функциональным значением.
Применяющие функционалы
Одним из основных типов функционалов являются функционалы, позволяющие применять функциональный аргумент к его параметрам. Такие функционалы называются применяющими или аппликативными функционалами. К применяющим функционалам относятся функции APPLY и FUNCALL.
APPLY является функцией двух аргументов: функции и списка, к элементам которого применяется функция.
Синтаксис функционала APPLY:
(apply fn список)
Û
(fn ’x1, ’x2, ..., ’xn),
где
список=(x1 x2 ... xn)
Например:
>(apply ’+ ’(2 3))
>(setq f ’+)
+
>(apply f ’(2 3))
Функционал FUNCALL по своему действию аналогичен APPLY, но аргументы для вызываемой функции он принимает не списком, а по отдельности:
(funcall fn x1 x2 ... xn)
Û
(fn x1 x2 ... xn)
Например:
>(setq f ’+)
>(funcall f 2 3)
Отображающие функционалы
Важный класс функционалов в практическом программировании на языке Лисп образуют отображающие функции или MAP-функции. MAP-функционалы являются функциями, которые некоторым образом отображают список (последовательность) в новую последовательность или порождают побочный эффект, связанный с этой последовательностью. Имена MAP-функций начинаются на MAP, и их вызов имеет вид:
(MAPX fn l1 l2 ... lN)
Здесь l1 ... lN – списки, а fn – функция от N аргументов. Как правило, MAP-функция применяется к одному аргументу-списку, т.е. fn является функцией от одного аргумента:
(MAPX fn список)
MAP-функция применяет функциональный аргумент к каждому элементу списка, заданного вторым аргументом, или к каждому cdr этого списка.
В таблице 6.1 приведены основные типы MAP-функций.
Таблица.6.1. Основные типы Map-функций
Игнорирование результата | Собирает каждый результат в список | Объединяет результаты в один список | |
Работает на каждом элементе списка | mapc | mapcar | mapcan |
Работает на каждом cdr | mapl | maplist | mapcon |
Значение функционала mapcar вычисляется путем применения функции fn к последовательным элементам xi списка, являющегося вторым аргументом:
(mаpcar fn ’(x1 x2 ... xN))
Û
(list (fn ’x1) (fn ’x2) ... (fn ’xN))
Например:
>(mapcar ’list ’(1 2 3))
((1) (2) (3))
Функционал maplist работает подобно mapcar, но действия осуществляются не над элементами списка, а над последовательными cdr этого списка. Например:
>(maplist ’list ’(1 2 3))
(((1 2 3)) ((2 3)) ((3)))
Функционалы mapcan и mapcon – аналоги функций mapcar и maplist, но эти функции не строят новый список из результатов, а объединяют результаты в один список:
(mapcan fn ’(x1 x2 ... xN))
Û
(nconc (fn ’x1) (fn ’x2) (fn ’x3) ... (fn ’xN))
Например:
>(mapcan ’list ’(1 2 3))
(1 2 3)
>(mapcon 'list '(1 2 3))
((1 2 3) (2 3) (3))
Если значением вызова функционального аргумента является NIL, то в объединенном списке его не видно. Это свойство функционалов mapcan и mapcon используется для реализации фильтров: например, можно использовать эти функционалы для удаления элементов, которые удовлетворяют (или не удовлетворяют) определенному условию. Подобную функцию remove-if (удаление элементов, удовлетворяющих условию) можно реализовать следующим образом:
(defun remove-if (funarg list)
(mapcan #’(lambda (elem)
(if (funcall funarg elem) nil
(list elem)))
list))
Теперь для удаления всех цифровых элементов списка (1 a 2 c 3 g) достаточно выполнить следующий вызов функции remove-if:
>remove-if ’numberp ’(1 a 2 c 3 g))
(a c g)
Функционалы mapc и mapl также аналогичны функциям mapcar и maplist, но не собирают и не объединяют результаты. Результаты просто теряются, а в качестве значения возвращается значение второго аргумента функции:
(mapc fn список)
Û
(prog2 (mapcar fn список) список)
Например:
>(mapc ’list ’(1 2 3))
(1 2 3)
>(mapl ’list ’(1 2 3))
(1 2 3)
Функционалы mapc и mapl прежде всего используют для получения побочного эффекта:
>(defun f (u v) (set u v))
F
>(mapc ’f ’(a b c) ’(1 2 3))
(A B C)
>b