我读过一本关于方案的书,里面有下面的例子:
(define map
(lambda (f s)
(if (null? s)
'()
(cons (f (car s))
(map f (cdr s)))))
(map (lambda (s)
(set! s '(1 2 3 4))
'hello)
'(a b c d))
它说,在动态范围内,我们将进入无限循环。但是为什么呢?根据我的理解,在我们应用了应用程序之后,我们到达了map with
f = (lambda (s)
(set! s '(1 2 3 4))
'hello)
和s= '(a b c d)
。现在,对于第一次运行,我们将在(car '(a b c d)
上应用f
:
((lambda (s)
(set! s '(1 2 3 4))
'hello)
(car '(a b c d)))
现在,它将a
改为(1 2 3 4)
。等等......这里的循环在哪里?
我认为作者的意思是f (car s)
执行后,s
的值将是'(1 2 3 4)
,因此(cdr s)
的值将是'(2 3 4)
,因此每次都将无限调用(map f '(2 3 4))
。
然而,我不认为这是对动态作用域的准确描述。由于s
是lambda的一个参数(因此不是一个自由变量),因此只有该参数应该受到set!
的影响,而map
函数的s
应该不受影响。所以不应该有无限循环——不管你是否使用动态作用域。如果我将代码转换为elisp(它是动态作用域的),代码实际上不会导致无限循环。所以我认为你的书中说使用动态作用域会产生无限循环的说法是错误的。