Mat*_*ick 3 variables scheme scope letrec
我不明白它们之间的区别(对于人为的例子而言):
(define average
(lambda (elems)
(define length
(lambda (xs)
(if (null? xs)
0
(+ 1 (length (cdr xs))))))
(define sum
(lambda (xs)
(if (null? xs)
0
(+ (car xs) (sum (cdr xs))))))
(define total (sum elems))
(define count (length elems))
(/ total count)))
Run Code Online (Sandbox Code Playgroud)
和
(define average
(lambda (elems)
(letrec ((length
(lambda (xs)
(if (null? xs)
0
(+ 1 (length (cdr xs))))))
(sum
(lambda (xs)
(if (null? xs)
0
(+ (car xs) (sum (cdr xs))))))
(total (sum elems))
(count (length elems)))
(/ total count))))
Run Code Online (Sandbox Code Playgroud)
据我所知,他们都创建了一个新的范围,并在该范围内创建了4个局部变量,这些变量相互引用并与自身相关,并评估并返回一个主体.
我在这里遗漏了什么,或者是letrecscoped defines的同义词?
我知道这可能是依赖于实现的; 我试图了解Lisps的基本原理.
你是正确的,你的代码define和letrec版本之间有相似之处.然而,魔鬼在细节中.在R5RS中,内部define具有letrec语义.在R6RS中,内部define具有letrec*语义.
有什么不同?您的代码实际上只突出了这种差异.至于哲浩的回答中提到,您的定义total和count内部相同letrec的length和sum不正确:length和sum不能保证通过你正在评估值的时间约束(length elems)和(sum elems),因为这些变量的结合是不能保证是左到右.
letrec*类似于letrec,但具有从左到右的保证.所以,如果你改变letrec了letrec*,那就没关系了.
现在,回到我最初的评论:因为R5RS的内部define使用letrec语义,即使你define的代码版本在R5RS实现下也是不正确的,但在具有letrec*语义的R6RS实现下也没问题.