Scheme 是第一个拥有词法环境和闭包的 Lisp。它对 Common Lisp 的设计产生了相当大的影响。词法环境的替代方案是动态绑定。例子:
;; setup (on both)
(define v 10)
(define (adder v)
(lambda (x) (+ x v))))
;; lexical scheme results
(define add5 (adder 5))
(add5 3) ; ==> 8
(let ((v 6))
(add5 3)) ; ==> 8
;; dynamic scheme results
(define add5 (adder 5))
(add5 3) ; ==> 13 (since y is the global variable 10)
(let ((v 6))
(add5 3)) ; ==> 9 (since v is bound to 6 during the call to add5)
Scheme 没有动态变量,所以最后一部分不会发生。Common Lisp 实际上具有全局定义变量的动态范围,因此如果您可以在 CL 中实际测试它:
(defparameter *v* 10)
(defparameter *x* 0)
(defun adder (*v*)
(lambda (*x*) (+ *x* *v*))))
;; lexical scheme results
(defparameter *add5* (adder 5))
(funcall *add5* 3) ; ==> 13
(let ((*v* 6))
(funcall *add5* 3)) ; ==> 9
有些 lisp 方言只有动态绑定。picoLisp 和 elisp 的早期版本就是例子。
请注意,Common Lisp 使用funcall
的是因为我已将函数绑定到变量。那是因为它们有两个命名空间。一种用于评估操作员位置的表格,另一种用于其余位置。因此,在 CL 中,您可以list
命名函数和参数list
,它们是不同的值。下面是在 Scheme 中不起作用但在 CL 中可以正常工作的代码:
(let ((list '(1 2 3)))
(list list list))
; ==> ((1 2 3) (1 2 3)) in CL
; ==> Application: (1 2 3) is not a procedure error in Scheme