racket - 定义接受可变数量参数的宏生成的宏
问题描述
我正在尝试编写一个宏生成宏,它生成的宏需要可变数量的参数。
我想知道是否有办法使以下代码工作:
(define-syntax-rule (greet name)
(define-syntax-rule (name args ...)
(printf "hello ~a~n" (list args ...))))
现在它说“pattern variables
之前ellipsis
在里面没有template
:...
”
如果我自己采用内部define-syntax-rule
,它可以正常工作,那么为什么当它由另一个宏生成时它不工作呢?
解决方案
这样做至少有 3 种“风格”。
1:省略号——分别引用每个省略号
Soegaard已经回答说,您可以将...
正文中的every 替换为(... ...)
,以便将其解释为属于内部宏的文字省略号,而不是属于外部宏的“元”省略号:
(define-syntax-rule (greet name)
(define-syntax-rule (name args (... ...))
(printf "hello ~a~n" (list args (... ...)))))
优点:灵活,可以在体内自由混合文字(... ...)
和元椭圆...
缺点:如果你以前没见过,看起来很(... ...)
混乱
2:省略号-引用整个内部宏定义
但是,放置(... <something>)
某些东西不仅限于...
. 如果您将整个模板放在那里,则...
该模板中的任何 s 也将被“引用”,被视为文字而不是元,以相同的方式:
(define-syntax-rule (greet name)
(...
(define-syntax-rule (name args ...)
(printf "hello ~a~n" (list args ...)))))
优点:如果您有更大的嵌套深度,则不需要((... ...) (... ...))
像选项 1 那样,您只需要(... <something-containing (... <something>)>)
缺点:僵化,如果你把(... <something>)
一些东西放在周围,你就不能在那个东西里面使用元省略号。您不能像使用样式 1 或 3 那样自由地混合文字和元省略号。
3:创建一个模式变量来表示文字省略号
这是另一种方式,我觉得不太容易混淆,但它需要使用define-simple-macro
而不是define-syntax-rule
,以便您可以使用 绑定新的模式变量#:with
。
(require syntax/parse/define)
(define-simple-macro (<name> <arguments>)
#:with <pattern-variable> <expression>
<body-expression>)
您可以使用 with#:with
将ooo
模式变量绑定到文字省略号:#:with ooo (quote-syntax ...)
(require syntax/parse/define)
(define-simple-macro (greet name)
#:with ooo (quote-syntax ...)
(define-syntax-rule (name args ooo)
(printf "hello ~a~n" (list args ooo))))
优点:灵活,您可以在正文中自由混合文字ooo
和元椭圆。...
对我来说,它看起来不像(... ...)
or那样令人困惑((... ...) (... ...))
。
缺点:对于更深的嵌套,您可能需要多个#:with
- 定义,每个元级别一个。
推荐阅读
- python-3.x - wxPython 分层布局似乎没有正确调整大小
- android - 如何使用 activityScenarioRule
? - php - Activecollab 自托管帐户 API 身份验证无效响应
- android - 在 Android 中编辑图像
- swift - 将新 UITableView 单元格的 textField 设为 firstResponder
- python - Flask:如何使用第二个查询获取参数,该参数用于第一个查询调用的函数?
- python - Python:将 AJAX 响应数据保存到 .json 并将其保存到 pandas DataFrame
- mongodb - MongoDB:如何从生成 oplog 中排除集合
- python-3.x - 如何使用 Selenium 和 Python 从 div 标签中抓取字符串?
- mysql - 为什么我的 UPDATE DATE() 查询在 WHERE 失败?