尽管将文本替换应用于 Lisp 表单可能很危险(因为存在多重评估等危险),但在这种情况下,查看此表单并了解它如何组合在一起可能会有所帮助:
((lambda (len)
(lambda (l)
...))
eternity)
是一个应用程序,即一个函数调用。被调用的函数接受一个参数,称为len
,并返回另一个接受单个参数的函数l
。被调用的函数是用 调用的eternity
。当调用完成时,结果是这个函数:
(lambda (l)
(cond
((null? l) 0)
(else (+ 1 (eternity (cdr l))))))
现在,这个函数接受一个列表l
,如果它是空的,则返回0
。否则,它计算(cdr l)
(列表的其余部分),并eternity
使用该值调用。当它返回时,1
被添加到结果中,这就是整个函数的返回值。当然,问题在于eternity
(define eternity
(lambda (x)
(eternity x)))
也可以写成
(define (eternity x)
(eternity x))
只需接受一个参数x
,然后调用eternity
with x
。那是一个无限循环。在上面,我写了“当返回时”,但实际上,(eternity (cdr l))
永远不会返回。所以,
((lambda (len)
(lambda (l)
(cond
((null? l) 0)
(else (+ 1 (len (cdr l)))))))
eternity)
是一个函数调用,它返回一个函数(lambda (l) …)
,0
如果调用一个空列表,则返回一个函数,并进入一个非空列表的无限循环。
从程序分析的角度来看,值得注意的是,还有其他值不会进入无限循环。例如,如果你用一个字符串调用它,那么(cdr l)
将是一个错误。