定义接受可变数量参数的宏生成的宏 [英] defining macro-generated macros that take in variable number of arguments

查看:43
本文介绍了定义接受可变数量参数的宏生成的宏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个宏生成宏,它生成的宏采用可变数量的参数.

I am trying to write a macro-generating macro, where the macro it generates takes a variable number of arguments.

我想知道是否有办法使以下代码工作:

I am wondering if there is a way to make the following code work:

(define-syntax-rule (greet name)
  (define-syntax-rule (name args ...)
    (printf "hello ~a~n" (list args ...))))

现在它说在 template 中的 ellipsis 之前没有 pattern variables 在:..."

Right now it says "no pattern variables before ellipsis in template in: ..."

如果我单独使用内部 define-syntax-rule 它可以正常工作,那么为什么它在由另一个宏生成时不起作用?

If I take the inner define-syntax-rule by itself it works fine, so why doesn't it work when it's being generated by another macro?

推荐答案

至少有 3 种样式"可以做到这一点.

There are at least 3 "Styles" of doing this.

Soegaard 已经回答 您可以将正文中的每个 ... 替换为 (... ...),以便将其解释为属于内部宏而不是属于外部宏的元"省略号:

Soegaard already answered that you can replace every ... in the body with (... ...), so that it gets interpreted as a literal ellipsis belonging to the inner macro instead of as a "meta" ellipsis belonging to the outer macro:

(define-syntax-rule (greet name)
  (define-syntax-rule (name args (... ...))
    (printf "hello ~a~n" (list args (... ...)))))

优点:灵活,可以在正文中自由混合文字 (... ...) 和元 ... 省略号

Advantages: Flexible, you can mix literal (... ...) and meta ... ellipses freely within the body

缺点:如果你之前没有看过(... ...),看起来会很混乱

Disadvantages: Looks confusing if you haven't seen (... ...) before

然而,将 (... <something>) 放在某物周围并不仅限于 ....如果您将整个模板放在那里,该模板中的任何 ... 也将被引用",以相同的方式被视为文字而不是元:

However, putting (... <something>) around something is not limited to just .... If you put a whole template there, any ...s within that template will also be "quoted", treated as literal instead of meta, in the same way:

(define-syntax-rule (greet name)
  (...
   (define-syntax-rule (name args ...)
     (printf "hello ~a~n" (list args ...)))))

优点:如果您有更大的嵌套深度,则不需要 ((... ...) (... ...)) 就像选项 1 那样,您只需要 (... <something-包含 (... <something>)>)

Advantages: If you have even greater nesting depths you wouldn't need ((... ...) (... ...)) as you would with option 1, you would just need (... <something-containing (... <something>)>)

缺点:僵硬,如果您将 (... <something>) 放在某物周围,则永远不能在该某物内使用元省略号.您不能像样式 1 或样式 3 那样自由地混合使用文字和元省略号.

Disadvantages: Rigid, if you put (... <something>) around something you can't ever use a meta ellipsis inside that something. You can't mix literal and meta ellipses freely like you could with style 1 or 3.

这是另一种方法,我觉得不太容易混淆,但它需要使用 define-simple-macro 而不是 define-syntax-rule,以便您可以绑定新的使用 #:with 的模式变量.

Here's another way, which I find less confusing, but it requires using define-simple-macro instead of define-syntax-rule, so that you can bind new pattern variables using #:with.

(require syntax/parse/define)

(define-simple-macro (<name> <arguments>)
  #:with <pattern-variable> <expression>
  <body-expression>)

您可以使用 with #:withooo 模式变量绑定到文字省略号: #:with ooo (quote-syntax ...)

You can use with #:with to bind an ooo pattern variable to a literal ellipsis: #: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 和元 ... 省略号.对我来说,它看起来不像 (... ...)((... ...) (... ...)) 那样令人困惑.

Advantages: Flexible, you can mix literal ooo and meta ... ellipses freely within the body. To me, it looks less confusing than (... ...) or ((... ...) (... ...)).

缺点:对于更深的嵌套,您可能需要多个 #:with 定义,每个元级别一个.

Disadvantages: For deeper nesting, you might need multiple #:with-definitions, one on each meta-level.

这篇关于定义接受可变数量参数的宏生成的宏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆