Как указывает Крис, код не будет работать. Поэтому я собираюсь использовать новый пример для объяснения идиомы let
over lambda
.
Когда вы окружаете lambda
форму с let
, как это:
(let ((x 0))
(lambda ()
; body
))
Код в теле lambda
может получить доступ (включая изменение) к x
даже после окончания let
и возврата новой функции. Это один из примеров создания «замыкания», который поначалу сложно понять.
По сути это означает, что вы можете создать функцию с неким "внутренним состоянием". Вы можете использовать это, чтобы делать такие вещи, как создание «генераторов аккумулятора» или создание функций, которые подсчитывают количество вызовов, которые они были вызваны, или даже имитируют «объекты» (внутреннее состояние + методы). Вот несколько надуманных примеров:
A double
функция, которая подсчитывает, сколько раз она была вызвана:
(define double
(let ((count 0)) ; closed over variable
(lambda (x)
(if (eq? x 'count)
count
(begin
(set! count (+ count 1)) ; incr the count variable introduced by let
(+ x x))))))
> (double 1)
2
> (double 1)
2
> (double 1)
2
> (double 'count) ; ask the double function how many times it's been called
3
>
Этот пример действительно любезен Пол Грэм (http://www.paulgraham.com/accgen.html)
(define make-accumulator
(lambda ()
(let ((x 0))
(lambda (i)
(set! x (+ x i)) ; incr x by i
x))))
> (define acc (make-accumulator))
> (acc 1)
1
> (acc 1)
2
> (acc 1)
3
> (acc 1)
4
>
Каждый раз, когда acc
вызывается с 1
, значение, которое он возвращает, отличается.
Для примеров «объектов» найдите «объекты и замыкания» или просто прочитайте соответствующие разделы SICP: http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-20.html#%_sec_3.1