Урок 9. Лямбда — функции в LISP

LISP   16 декабря 2012  Автор статьи:  

В данном уроке мы научимся передавать функции в качестве параметра, а также познакомимся с лямбда функциями. В языке LISP имеется возможность вызывать функции по их имени:

(funcall '+ 2 2);4

С таким же успехом название функции я мог бы передать как параметр в другой функции. Для чего это может быть нужно? Если у вас есть какая — то функция, которая работает только с каким — то определенным типом данных, но она могла бы стать более общей, если бы умела работать со всеми типами, тогда мы будем передавать название функции, которая умеет делать это с конкретным типом данных, а вызывать ее уже по имени внутри нашей функции. Длинная фраза, которая означает ровно то, что если ваша функция например реализует какой — то алгоритм сортировки, то так как объекты которые мы сортируем могут быть разной природы, целые числа, вещественные числа, какие — то списки и прочее, то мы возьмем и начнем передавать имя функции, которая будет сравнивать два конкретных объекта в функцию сортировки. Таким образом, вместо того, чтобы принимать на вход один список она будет принимать на вход и список и название функции, которая будет сравнивать конкретный тип данных. Для закрепления давайте напишем операцию rember c произвольной проверкой:

(defun rember(testp lst a)
(cond ((null lst) nil)
((funcall testp (car lst) a) (cdr lst))
(t (cons (car lst)(rember testp (cdr lst) a)))
))
(rember '< '(1 2 3 4 5) 2);(2 3 4 5)

Лямбда - выражение имеет следующую сигнатуру:

(lambda (x1 ... xn) fn);сигнатура
(lambda (x y) (+ x y));пример

Где x1, x2 и так далее формальные параметры, а fn - это тело функции.
Для того, чтобы вызвать лямбда выражение достаточно поставить его на место функции:

((lambda (x y) (+ x y)) 1 1);2

Вычисление лямбда функций происходит в два этапа: сначала вычисляются фактические параметры и связываются с формальными, а затем уже происходит выполнение функции. В чем плюс использования лямбда функции? В том, что мы можем возвращать не только целые числа и так далее, но и функции. Давайте напишем функцию myeq, которая будет возвращать функция без имени, которая будет сравнивать некоторой значение, с значением, которое мы будем передавать в myeq:

(defun myeq (a)
(function (lambda (x) (equal x a)))
)
(funcall (myeq 1) 1);T

Работа с лямбда функциями дает громадные возможности по расширению возможностей ваших функций, а также может помочь повысить уровни абстракции. Кроме этого, вы также можете положить вновь полученную функцию в какую - нибудь переменную и вызывать с помощью funcall:

(setq func (myeq 1))
(funcall func 1);T

Научиться программировать

  • на Delphi

  • на Java

  • на C++