【问题标题】:Is it possible to write a Rust macro that will expand into a function/method signature?是否可以编写一个将扩展为函数/方法签名的 Rust 宏?
【发布时间】:2014-07-23 08:15:21
【问题描述】:

我希望能够做到以下几点:

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(),
    }
})

我的真实示例中的方法具有更大的签名,我必须以独特的方式为 30 多种不同类型实现这些方法。

我已经尝试过类似于上述宏的方法,但是在 rustc 认为 foobarbaz 扩展站点上未解析的名称时遇到了错误(尽管我确信宏声明在词法上位于前面使用)。

有可能做这样的事情吗?

如果没有,您能否推荐一种可以实现类似效果的方法?

【问题讨论】:

    标签: methods macros rust method-signature


    【解决方案1】:

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

    impl_a_method!(MyType, (foo, bar, baz), {
        MyType {
            foo: foo.blah(),
            bar: bar.bloo(),
            baz: baz.floozy(),
        }
    })
    

    这是由这个宏完成的:

    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 }
        )
    )
    

    您在这里真正省下的唯一事情就是编写方法参数的类型。

    【讨论】:

    • “宏观卫生”实际上是一个非常明确的概念:en.wikipedia.org/wiki/Hygienic_macro
    • 在 Julia 中有一个函数esc,它使引入的符号保持原样,而不是转换为唯一名称(gensymed)。 Rust 中没有这样的东西吗?
    • @PostSelf 我不认为有 - 获得未转义标识符的唯一方法是在外部传递它。我相信这是故意的。
    • 我很想知道这是否至少可以通过 proc 宏实现?我试过写一个,但它似乎不起作用,但我不知道这是否只是因为我做错了什么。卫生不应成为 prog 宏的障碍,因为它们通常不卫生。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    • 1970-01-01
    • 2013-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多