Can a Rust macro create new identifiers?

天涯浪子 提交于 2019-12-17 05:13:05

问题


I'd like to create a setter/getter pair of functions where the names are automatically generated based on a shared component, but I couldn't find any example of macro rules generating a new name.

Is there a way to generate code like fn get_$iden() and SomeEnum::XX_GET_$enum_iden?


回答1:


My mashup crate provides a stable way to create new identifiers that works with any Rust version >= 1.15.0.


#[macro_use]
extern crate mashup;

macro_rules! make_a_struct_and_getters {
    ($name:ident { $($field:ident),* }) => {
        // Define the struct. This expands to:
        //
        //     pub struct S {
        //         a: String,
        //         b: String,
        //         c: String,
        //     }
        pub struct $name {
            $(
                $field: String,
            )*
        }

        // Use mashup to define a substitution macro `m!` that replaces every
        // occurrence of the tokens `"get" $field` in its input with the
        // concatenated identifier `get_ $field`.
        mashup! {
            $(
                m["get" $field] = get_ $field;
            )*
        }

        // Invoke the substitution macro to build an impl block with getters.
        // This expands to:
        //
        //     impl S {
        //         pub fn get_a(&self) -> &str { &self.a }
        //         pub fn get_b(&self) -> &str { &self.b }
        //         pub fn get_c(&self) -> &str { &self.c }
        //     }
        m! {
            impl $name {
                $(
                    pub fn "get" $field(&self) -> &str {
                        &self.$field
                    }
                )*
            }
        }
    }
}

make_a_struct_and_getters!(S { a, b, c });



回答2:


No, not as of Rust 1.22.


If you can use nightly builds...

Yes: concat_idents!(get_, $iden) and such will allow you to create a new identifier.

But no: the parser doesn't allow macro calls everywhere, so many of the places you might have sought to do this won't work. In such cases, you are sadly on your own. fn concat_idents!(get_, $iden)(…) { … }, for example, won't work.



来源:https://stackoverflow.com/questions/27415011/can-a-rust-macro-create-new-identifiers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!