我不明白两者之间有什么区别(对于人为的例子感到抱歉):
(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)))
和
(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))))
据我所知,它们都创建了一个新的作用域,并在该作用域中创建了 4 个局部变量,它们相互引用并引用自身,并评估并返回一个主体。
我在这里遗漏了什么,或者是
letrec
作用域 define
的同义词年代?我知道这可能取决于实现;我试图了解 Lisps 的基础知识。
最佳答案
你说得对,define
之间有相似之处。和 letrec
您的代码的版本。然而,魔鬼在细节中。在 R5RS 中,internal define
has letrec
semantics .在 R6RS 中,internal define
has letrec*
semantics .
有什么不同?您的代码实际上只是突出了这种差异。正如哲豪的回答所提到的,您对 total
的定义和 count
在同一个letrec
作为 length
和 sum
不正确:length
和 sum
不保证在您评估 (length elems)
的值时受到约束和 (sum elems)
,因为这些变量的绑定(bind)不保证是从左到右的。letrec*
类似于 letrec
,但有从左到右的保证。因此,如果您更改了 letrec
至letrec*
,会好的。
现在,回到我最初的评论:因为 R5RS 的内部 define
使用 letrec
语义,甚至你的define
代码的版本在 R5RS 实现下是不正确的,但在 R6RS 实现下是可以的,它有 letrec*
语义。
关于variables - 创建本地绑定(bind)的 'let' 或 'letrec' 和 'define' 之间有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11463232/