Scheme 方案中的letrec定义有何错误(如有)?

Scheme 方案中的letrec定义有何错误(如有)?,scheme,macros,define-syntax,Scheme,Macros,Define Syntax,R5RS给出了语法库形式的建议宏定义: 它还以一种非常复杂的方式定义了letrec,当然不是我将如何定义它,我只会使用: (define-syntax letrec2 (syntax-rules () ((letrec2 ((name val) ...) body bodies ...) ((lambda () (define name val) ... body bodies ...))))) 就我所理解的letrec的语义而言,我经常使用

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

它还以一种非常复杂的方式定义了letrec,当然不是我将如何定义它,我只会使用:

(define-syntax letrec2
  (syntax-rules ()
    ((letrec2 ((name val) ...) body bodies ...)
     ((lambda ()
       (define name val) ...
       body bodies ...)))))
就我所理解的letrec的语义而言,我经常使用它作为命名let。它是这样工作的,然而,当我与哲学家们进行了相当多的辩论,他们认为他们可以反驳狭义相对论或已建立的音韵理论时,我知道当你认为你有一个复杂问题的简单解决方案时,这可能是错的。在某种程度上,这个宏不能满足letrec的语义,否则他们可能会使用它


在这个定义中,这些定义是letrec主体的局部定义,它们可以相互引用以实现相互递归,我不太确定有什么(如果有)是错误的。

在我看来,您已经将实现的责任从宏推到了编译器身上,这是R5RS设计者试图避免的

事实上,本地定义是在R5RS中用letrec实现的。看

我认为设计师的意图可以很好地概括为:

编程语言的设计不应将特性堆积在顶部 功能,但通过删除 造成这种情况的弱点和限制 附加功能似乎是必要的。 该方案表明,一个非常小的 形成规则的数量 表达式,对 它们是如何构成的,足以构成 一种实用高效的程序设计方法 足够灵活的语言 支持大多数主要的编程 今天使用的范例

编辑1: 转换为letrec的r5rs版本的内部定义示例。 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'.
...
在PLT方案中,R5RS模式将内部定义转换为letrec的R5RS版本。 您也可以在任何具有内部定义的代码上使用DrScheme的宏扩展器来测试这一点。

好问题

我认为
define
序列的问题在于:

“评估的顺序 表达式expr…未指定, 因此,一个程序不能评估一个 对任何变量的引用 之前由letrec表达式绑定 所有的值都已计算”

在这里:

R5RS声明
letrec
的语义与内部定义的语义完全相同。详情见:;我引述以下关键片段:

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

因此,根据内部定义定义
letrec
,正好解决了问题


此外,我发现定义
letrec
宏并将
lambda
desugar内部定义放入
letrec
比将所有复杂代码塞入
lambda
处理程序并在其上构建
letrec
更简单。这并没有涉及到在非顶级范围内引入相互递归绑定的更漂亮的形式是什么的问题…;-)

好吧,我终于找到了原因,它很简单,毫无用处,我的定义没有任何错误,事实上,这是由于一些优于R5RS中的错误造成的

寻找“letrec”,你们都不可能回答我的问题,什么是错的,显然没有什么是错的,R5RS显然在一个信息部分有一个“勘误表”。我想现在我不得不接受我自己的答案


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

嗯,define是一个原始表单,而不是一个库表单,这与letrec不同。定义和设置!真的不能用其他函数来定义。另外,在剩下的时间里,我不知道你的文章与我的观点有什么关系,我仍然把它作为一个宏。letrec是R5RS标准的一部分,尽管实现可以将其作为宏实现,但只要满足R5RS中给出的语义,就不需要它。在这里它仍然是一个宏,R5R中的宏是“建议”。@Lajla内部定义仅在某些实现中是一个基本形式。在某些实现中,内部定义可以根据letrec定义。只有在内部定义为基元时,宏才能用于定义letrec。内部定义通常是根据letrec来定义的,因为它遵循了我从R5RS简介中引用的哲学。你有没有引证表明这一点?因为如果这是真的,那显然就是原因。但据我所知,define始终是原始的,因为它具有完全独特的语义,如中所示,它不能出现在很多地方,并且要用宏定义内部定义,实现需要将letrec语法添加到每个有主体的表单中。你的消息来源只是说它是等效的,它没有明确说明它是如何实现的,但是如果你能提供一个引用,说明实现了这一点,那么这就是我们问题的明显答案。我编辑了我的答案,给出了一个例子。我不能在这里发布整个宏,但我确实包含了关于转换的评论。我现在有DrScheme 4.2.4,宏扩展器根本不扩展内部定义。此外,我的宏定义将不起作用,并且是循环的,到目前为止,它在PLT中起作用。我使用的示例是一个粗略的标识函数(lambda(x)(define(func a)a)(func x))。我通常有PLT到R5R。另外,在我自己的PLT文件夹中查看这个宏,它使用语法大小写,它似乎是R6RS。这可能就是为什么R5RS给出了letrec的定义,但最终没有使用define。虽然我真的不知道这比反向更容易,但这就是内部(和外部)定义