有啥方法可以首先获取参数,最后在球拍中的函数中获取名称?
Posted
技术标签:
【中文标题】有啥方法可以首先获取参数,最后在球拍中的函数中获取名称?【英文标题】:Is there any way to take at first the arguments and at last the name in a function in racket?有什么方法可以首先获取参数,最后在球拍中的函数中获取名称? 【发布时间】:2021-05-10 15:18:38 【问题描述】:我被要求在球拍中编写一个程序,以便将算术运算符的行为从前缀更改为后缀。更确切地说:
我希望这段代码:(a b +)
的行为类似于:(+ a b)
我想使用define-syntax-rule
来改变+ 运算符的行为,但我有一个问题,在使用define-syntax-rule
时,我们首先编写宏的名称,然后编写参数。
我的问题:有没有办法在球拍函数中写出开头的参数和最后的名字?
【问题讨论】:
【参考方案1】:完成此操作的最简单方法是创建自己的#%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 ...))
使用.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 变成了一种惰性语言。
【讨论】:
非常感谢,这工作得很好。你能简单解释一下 lang.rkt 中的代码吗? 当然!我编辑了帖子以添加解释。 @LeifAndersen, IIRC,#lang s-exp
不需要,对吧?你可以require
它。
这基本上是正确的。我不使用require
的原因是因为你会遇到#%app
高于要求(原始球拍#%app
,低于要求(新的#%app
)的情况。我找到了线索可能会混淆代码。以上是关于有啥方法可以首先获取参数,最后在球拍中的函数中获取名称?的主要内容,如果未能解决你的问题,请参考以下文章
球拍中的make-hash make-weak-hash有啥区别?