Позволяет использовать правила замещения.make-add-one
можно переписать так:
(define make-add-one (lambda ()
(define inc (lambda (x) (+ 1 x))
inc))
Поскольку inc
только что возвращено, мы можем упростить его до следующего:
(define make-add-one (lambda ()
(lambda (x) (+ 1 x)))
Теперь myfn
мы можем заменитьвызов make-add-one
с кодом, который есть внутри лямбды:
(define myfn (make-add-one)) ; ==
(define myfn (lambda (x) (+ 1 x)))
И наконец, мы можем использовать правила подстановки при последнем вызове:
(myfn 2) ; ==
((lambda (x) (+ 1 x)) 2) ; ==
(+ 1 2) ; ==
3
Сейчас make-add-one
создает новую функцию, идентичную всем остальным функциямЭто на самом деле ничего не добавляет.Хорошим примером того, где это полезно, является следующий пример:
(define (make-add by-what)
(lambda (value) (+ value by-what)))
(define inc (make-add 1))
(define add5 (make-add 5))
(map add5 '(1 2 3)) ; ==> (6 7 8)
(map inc '(1 2 3)) ; ==> (2 3 4)
Просто чтобы увидеть, что это то же самое:
(add5 2) ; ==
((make-add 5) 2) ; ==
((lambda (value) (+ value 5)) 2) ; ==
(+ 2 5) ; ==
; ==> 7
И как это работает.В лексически ограниченном языке все формы lambda
фиксируют переменные, которые не связаны в их собственном списке параметров из области, в которой он был создан.Это известно как закрытие.Простой пример этого приведен здесь:
(define x 10)
(define test
(let ((x 20)
(lambda (y) (+ x y))))
(test 2) ; ==> 22
Так что в схеме test
использует x
из let
даже после того, как область вышла, так как lambda
была создана в этой области.В динамически ограниченном языке (test 2)
вернет 12
, а два предыдущих примера также приведут к другим результатам и ошибкам.
Лексическая область видимости появилась в первую очередь в Algol, который является предшественником всех языков семейства C, таких как C, java, perl.Схема была, вероятно, первым языком, и это был основной дизайн самого языка.Без закрытия первая версия Scheme была такой же, как и ее основной язык MacLisp.