以下代码中,由于语法闭包,set!修改的是局部变量而非全局变量

1
2
3
4
(define add2
(lambda (x)
(set! x (+ x 2))
x))

以下代码修改的是全局变量,因为指定给lambda传入一个空的参数列表

1
2
3
4
(define bump-counter
(lambda ()
(set! counter (+ counter 1))
counter))

let & let*

1
2
3
4
5
(let ((x 1)
(y 2)
(z 3))
(list x y z))
; ==> (1 2 3)

let可以显式的让参数进行语法闭包,设置为局部变量

1
2
3
(let ((x 1)
(y x))
(+ x y))

let针对变量的引用并不是从结构体中调用的,不作为结构的一部分,而是调用全局变量,以上的结构中,***(y x)是将全局变量中的x赋值给y*

如果想在引用时,优先考虑结构体内的变量,优先调用局部变量,使用let*

1
2
3
4
5
6
7
8
(let* ((x 1)
(y x))
(+ x y))

; ==>
(let ((x 1))
(let ((y x))
(+ x y)))

以下代码显示了Scheme的特性,可以将procedure赋值给变量,即一切皆数据

1
2
(let ((cons (lambda (x y) (+ x y))))
(cons 1 2))

fluid-let

fluid-let将内部的procedure求值时的全局变量临时进行设置

1
2
3
4
5
6
(fluid-let ((counter 99))
(display (bump-counter))
(newline)
(display (bump-counter))
(newline))
; ==> 100 101

在换成let后,bump-counter的引用依然是从全局变量中调用,即使设置了局部变量