В Lispex функции — основные строительные блоки логики и абстракции. Они объекты первого класса: их можно связывать, передавать и возвращать.
Определение функций
Именованные функции создаются сахаром define, анонимные — формой lambda.
Именованные функции через define
(define (add x y)
(+ x y))
(add 5 10) ; ⇒ 15
Анонимные функции через lambda
(lambda (n) (* n 2))
Функции как объекты первого класса
Быть "объектом первого класса" означает, что с функциями обращаются так же, как с любыми другими значениями данных (такими как число или список). Их можно:
1. Хранить в привязках
Привяжите функцию как любое другое значение.
(define square (lambda (n) (* n n)))
(define square-alias square)
(square-alias 10) ; ⇒ 100
2. Передавать в качестве аргументов
Вы можете передавать функции в качестве аргументов в другие функции. Это основа для функций высшего порядка.
(define (apply-it f v)
(f v))
(define square (lambda (n) (* n n)))
(apply-it square 10) ; ⇒ 100
3. Возвращать из других функций
Функция может создавать и возвращать другую функцию. Этот мощный паттерн объясняется в разделе "Замыкания" ниже.
Понимание замыканий
Когда функция создается, она захватывает окружение (переменные и их значения), в котором она была определена. Это захваченное окружение называется замыканием (closure). Это позволяет функции "помнить" значения, даже когда она вызывается за пределами своей исходной области видимости.
Пример: фабрика функций
(define (make-adder amount-to-add)
(lambda (n)
(+ n amount-to-add)))
(define add-five (make-adder 5))
(define add-ten (make-adder 10))
(add-five 100) ; ⇒ 105
(add-ten 100) ; ⇒ 110
Рекурсия
В Лиспекс итерация наиболее идиоматично достигается с помощью рекурсии. Этот подход позволяет избежать побочных эффектов и изменений состояния.
(define (factorial n)
(if (<= n 1)
1
(* n (factorial (- n 1)))))
(factorial 5) ; ⇒ 120