有没有办法首先在球拍的函数中获取参数,最后获取名称?

Is there any way to take at first the arguments and at last the name in a function in racket?

我被要求在球拍中编写一个程序,以便将算术运算符的行为从前缀更改为后缀。更确切地说: 我希望这段代码:(a b +) 表现得像:(+ a b)

我想使用 define-syntax-rule 来改变 + 运算符的行为,但我有一个问题,在使用 define-syntax-rule 时我们首先写了宏的名称,然后我们写的论据。 我的问题:有没有什么办法可以在球拍函数中把参数写在开头,最后写名字?

完成此操作的最简单方法是创建您自己的 #%app 宏。由于您实际上是在此处创建一种新语言,因此您需要两个模块:一个定义您的语言的 'lang' 模块,以及一个用于您要用该语言编写的程序的 'use' 模块。这可以用两个文件或一个文件使用子模块来完成。

在这里,我将使用两个文件向您展示:

lang.rkt

#lang racket
(provide (except-out (all-from-out racket)
                     #%app)
         (rename-out [-app #%app]))
(require syntax/parse/define)

(define-syntax-parse-rule (-app args ... proc)
  (#%app proc args ...))

use.rkt

#lang s-exp "lang.rkt"
(3 2 +) ; => 5

请注意,这只会更改函数调用,不会更改其他形式。所以:

use2.rkt

#lang s-exp "lang.rkt"
(define x 42)
(2 x *) ; => 84

编辑:

解释 lang.rkt 中发生的事情。它采用 racket 语言,并重新导出除 #%app 宏之外的所有语言。 (作为参考,球拍(f args ...)中的所有功能应用都扩展为(#%app f args ...)。)

对于#%app宏,我们定义了另一个宏-app,将函数调用从末尾移动到开头,并使用了Racket的#%app宏。然后我们在导出时将 -app 重命名为 #%app

this paper 的第 5.1 节为您提供了相同内容的概述,但是将 Racket 变成了一种惰性语言。