是否可以编写一个将扩展为函数/方法签名的Rust宏?

min*_*ree 9 methods macros method-signature rust

我希望能够得到以下内容:

macro_rules! impl_a_method(
    ($obj:ident, $body:block) => (
        fn a_method(foo: Foo, bar: Bar, baz: Baz) -> $obj $body
    )
)

// Implementation would look like:

impl_a_method!(MyType, {
    MyType {
        foo: foo.blah(),
        bar: bar.bloo(),
        baz: baz.floozy(),
    }
})
Run Code Online (Sandbox Code Playgroud)

我的真实世界示例包含具有更大签名的方法,我必须以30多种不同类型的独特方式实现这些方法.

我曾尝试与上述类似的宏观的东西,但是我碰到哪里rustc认为的错误foo,bar并且baz在扩展网站未解决的名称(即使我敢肯定,宏声明词汇之前使用).

可以这样做吗?

如果没有,你能推荐一种能达到类似效果的方法吗?

Vla*_*eev 6

由于宏观卫生,这是不可能的.宏体中引入的任何标识符都保证与宏调用站点上的任何标识符不同.您必须自己提供所有标识符,这有点违背宏的目的:

impl_a_method!(MyType, (foo, bar, baz), {
    MyType {
        foo: foo.blah(),
        bar: bar.bloo(),
        baz: baz.floozy(),
    }
})
Run Code Online (Sandbox Code Playgroud)

这是由这个宏完成的:

macro_rules! impl_a_method(
    ($obj:ty, ($_foo:ident, $_bar:ident, $_baz:ident), $body:expr) => (
        fn a_method($_foo: Foo, $_bar: Bar, $_baz: Baz) -> $obj { $body }
    )
)
Run Code Online (Sandbox Code Playgroud)

你真正保存的唯一一件事是编写方法参数的类型.

  • "宏观卫生"实际上是一个非常明确的想法:https://en.wikipedia.org/wiki/Hygienic_macro (10认同)