对于每个100%兼容的R7RS小程序,它不依赖于任何特定于实现或未定义的行为,程序中的每个letrec
实例都可以用letrec*
替换而不会导致任何行为变化,这是真的吗?换句话说,是否存在letrec
的出现不能用letrec*
代替的R7RS小程序?
我认为答案是肯定的,可以,假设该表单在R7RS术语中不是"错误"(但请参阅末尾的注释(。特别是,我认为如果有像这样的表格
(letrec ((v1 <e1>) (v2 <e2>)) ...)
那么,必须可以在不参考v1
的值的情况下评估<e2>
,但当评估<e2>
时,绑定确实存在:引用它只是一个错误。因此,特别是这是不允许的:
(let ((a 1)) (letrec ((a 2) (b a)) ...))
因为b
的init所指的绑定是由letrec
建立的,而不是由let
建立的,但引用该绑定的值还不合法。
在这种情况下,如果您简单地用letrec*
替换letrec
,那么<e2>
仍然不会引用v1
的值,因此结果将是相同的。
反之则不然:
(letrec* ((a 1) (b a)) ...)
很好,但你不能用letrec
代替letrec*
。
在这种情况下,我不清楚letrec
有什么有用的用途(也许这就是为什么Racket的letrec
具有Scheme的letrec*
的语义(。
注意这个答案的早期版本得出了相反的结论。我现在还不相信我对事情理解得足够好。