Luk*_*odt 4 rust rust-proc-macros
我正在编写一个程序宏,我需要多次发出一个很长的标识符(可能是因为卫生,例如)。我quote!
用来创建TokenStream
s,但我不想一遍又一遍地重复长标识符!
例如,我想生成此代码:
let very_long_ident_is_very_long_indeed = 3;
println!("{}", very_long_ident_is_very_long_indeed);
println!("twice: {}", very_long_ident_is_very_long_indeed + very_long_ident_is_very_long_indeed);
Run Code Online (Sandbox Code Playgroud)
我知道我可以创建一个Ident
并将其插入到quote!
:
let my_ident = Ident::new("very_long_ident_is_very_long_indeed", Span::call_site());
quote! {
let #my_ident = 3;
println!("{}", #my_ident);
println!("twice: {}", #my_ident + #my_ident);
}
Run Code Online (Sandbox Code Playgroud)
到目前为止一切顺利,但我需要在我的代码库中的许多函数中使用该标识符。我希望它是const
我可以在任何地方使用的。但是,这失败了:
const FOO: Ident = Ident::new("very_long_ident_is_very_long_indeed", Span::call_site());
Run Code Online (Sandbox Code Playgroud)
出现此错误:
let very_long_ident_is_very_long_indeed = 3;
println!("{}", very_long_ident_is_very_long_indeed);
println!("twice: {}", very_long_ident_is_very_long_indeed + very_long_ident_is_very_long_indeed);
Run Code Online (Sandbox Code Playgroud)
我怀疑这些功能是否会const
很快被标记。
我可以使字符串本身成为一个常量:
const IDENT: &str = "very_long_ident_is_very_long_indeed";
Run Code Online (Sandbox Code Playgroud)
但是无论我想在哪里使用标识符,我都需要调用Ident::new(IDENT, Span::call_site())
,这会很烦人。我只想写#IDENT
在我的quote!
调用中。我能以某种方式使它工作吗?
幸运的是,有办法!
通过内插#
在quote!
通过作品的ToTokens
特质。实现该特性的所有内容都可以插入。因此,我们只需要创建一个可以构造为常量并实现ToTokens
. trait 使用类型 fromproc-macro2
而不是标准类型proc-macro
。
use proc_macro2::{Ident, Span, TokenStream};
struct IdentHelper(&'static str);
impl quote::ToTokens for IdentHelper {
fn to_tokens(&self, tokens: &mut TokenStream) {
Ident::new(self.0, Span::call_site()).to_tokens(tokens)
}
}
Run Code Online (Sandbox Code Playgroud)
现在您可以定义您的标识符:
const IDENT: IdentHelper = IdentHelper("very_long_ident_is_very_long_indeed");
Run Code Online (Sandbox Code Playgroud)
并直接在quote!
:
quote! {
let #IDENT = 3;
}
Run Code Online (Sandbox Code Playgroud)
(完整示例)
归档时间: |
|
查看次数: |
308 次 |
最近记录: |