5

R5RS 给出了语法库形式的宏定义:

http://schemers.org/Documents/Standards/R5RS/HTML/r5rs-ZH-10.html#%_sec_7.3

这也以非常复杂的方式定义了letrec,当然不是我将如何定义它,我将简单地使用:

(define-syntax letrec2
  (syntax-rules ()
    ((letrec2 ((name val) ...) body bodies ...)
     ((lambda ()
       (define name val) ...
       body bodies ...)))))

据我了解 letrec 的语义,我经常将其用作命名的 let。它以这种方式工作,但是由于我与那些认为他们可以反驳狭义相对论或已建立的语音理论的哲学家进行了相当多的辩论,我知道当你认为你有一个复杂问题的简单解决方案时,它可能是错误的。一定有某个地方这个宏不能满足 letrec 的语义,否则他们可能会使用它。

在这个定义中,定义是 letrec 主体的本地定义,它们可以相互引用以进行相互递归,我不太确定什么(如果有的话)是错误的。

4

4 回答 4

5

在我看来,您已经将实现的责任从宏推到了编译器,这是 R5RS 设计人员似乎试图避免的。

事实上,本地定义是用 R5RS 中的 letrec 实现的。请参阅6.2.2 内部定义

我认为设计师的意图在 R5RS 的介绍中得到了很好的总结:

编程语言的设计不应通过将功能堆积在功能之上,而应消除使附加功能显得必要的弱点和限制。Scheme 证明了用于形成表达式的极少数规则,对它们的组成方式没有任何限制,足以形成一种实用且高效的编程语言,该语言足够灵活以支持当今使用的大多数主要编程范式。

edit1:转换为 r5rs 版本的 letrec 的内部定义示例。PLT方案4.2.5收集/r5rs/main.ss

(define-syntax (r5rs:body stx)
(syntax-case stx (let)
  [(_ (let () . body))
   #'(let () . body)]
  [_
   ;; Convert internal definitions to `r5rs:letrec', as opposed
   ;; to `letrec'.
...

在 R5RS 模式下的 PLT 方案中,确实将内部定义转换为 R5RS 版本的 letrec。您也可以通过在任何具有内部定义的代码上使用 DrScheme 的宏扩展器来自行测试。

于 2010-05-14T17:55:42.603 回答
3

R5RS 声明 的语义letrec与内部定义的语义完全相同。有关详细信息,请参见专门讨论后者的部分;我引用下面的关键片段:

包含内部定义的 <body> 始终可以转换为完全等效的letrec表达式。

因此letrec,根据内部定义进行定义只会转移问题。

此外,我发现定义一个letrec宏并在lambda内部定义去糖letrec比将所有复杂的代码填充到lambda处理程序中并在此基础letrec上构建更简单。这没有涉及在非顶级范围中引入相互递归绑定的更漂亮形式的问题...... ;-)

于 2010-05-15T02:37:36.037 回答
0

好问题。

我认为一系列的问题define是这样的:

“表达式 expr ... 的计算顺序未指定,因此在计算所有值之前,程序不得计算对 letrec 表达式绑定的任何变量的引用”

这里: http ://www.scheme.com/tspl4/binding.html#./binding:s20

于 2010-05-14T19:28:04.253 回答
0

好吧,我终于找到原因了,就这么简单,没用,我的定义没有错,实际上是由于比R5RS中的那个更优的一些错误。

http://community.schemewiki.org/?scheme-faq-macros

寻找“letrec”,你们都无法回答我关于哪里出了问题的问题,显然没有任何问题,R5RS 显然在信息部分有一个“勘误表”。现在我猜我将被迫接受我自己的答案......

现在引出的问题是,为什么 R5RS 的作者没有选择这个简单的解决方案,而是选择了一个非常复杂的解决方案,甚至包含一个错误......

于 2010-06-07T03:41:19.737 回答