Функционалы

Основываясь на едином представлении данных и программ, функции в качестве аргумента можно передать другую функцию. Аргумент, значение которого является функция, называют в функциональном программировании функциональным аргументом, а функцию, имеющую функциональный аргумент – функционалом. Аргументом функции может быть функция, однако, функция может быть и результатом. Такие функции называют функциями с функциональным значением. Функционал также может быть с функциональным значением.

Применяющие функционалы

Одним из основных типов функционалов являются функционалы, позволяющие применять функциональный аргумент к его параметрам. Такие функционалы называются применяющими или аппликативными функционалами. К применяющим функционалам относятся функции 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

Наши рекомендации