有没有办法让宏替换字符串中的东西?
Is there a way to make a macro replace things in strings?
该宏应该能够通过参数替换字符串中的条目。例如,这会起作用:
let string = "Hello, world!";
replace_macro!(string, "world", "Rust"); // Hello, Rust!
我不确定该怎么做,因为我之前尝试编写一个常规函数并调用它在宏中不起作用。如果可能的话,我想使用 macro_rules 而不是 proc 宏。
这是不可能的。宏无法检查 and/or 更改变量的值。
如果文字嵌入调用中是可能的 (replace_macro!("Hello, world!", "world", "Rust");
) 但需要 proc-macro: macro_rules!
宏无法检查 and/or 更改文字。
使用 proc 宏相当简单:
use quote::ToTokens;
use syn::parse::Parser;
use syn::spanned::Spanned;
type Args = syn::punctuated::Punctuated<syn::LitStr, syn::Token![,]>;
#[proc_macro]
pub fn replace_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input_span = input.span();
let args = match Args::parse_terminated.parse(input) {
Ok(args) => Vec::from_iter(args),
Err(err) => return err.into_compile_error().into(),
};
let (original, text, replacement) = match args.as_slice() {
[original, text, replacement] => (original.value(), text.value(), replacement.value()),
_ => {
return syn::Error::new(
input_span,
r#"expected `"<original>", "<text>", "<replacement>"`"#,
)
.into_compile_error()
.into()
}
};
original
.replace(&text, &replacement)
.into_token_stream()
.into()
}
它解析由逗号分隔的三个字符串文字的列表,然后调用 str::replace()
来完成真正的工作。
该宏应该能够通过参数替换字符串中的条目。例如,这会起作用:
let string = "Hello, world!";
replace_macro!(string, "world", "Rust"); // Hello, Rust!
我不确定该怎么做,因为我之前尝试编写一个常规函数并调用它在宏中不起作用。如果可能的话,我想使用 macro_rules 而不是 proc 宏。
这是不可能的。宏无法检查 and/or 更改变量的值。
如果文字嵌入调用中是可能的 (replace_macro!("Hello, world!", "world", "Rust");
) 但需要 proc-macro: macro_rules!
宏无法检查 and/or 更改文字。
使用 proc 宏相当简单:
use quote::ToTokens;
use syn::parse::Parser;
use syn::spanned::Spanned;
type Args = syn::punctuated::Punctuated<syn::LitStr, syn::Token![,]>;
#[proc_macro]
pub fn replace_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input_span = input.span();
let args = match Args::parse_terminated.parse(input) {
Ok(args) => Vec::from_iter(args),
Err(err) => return err.into_compile_error().into(),
};
let (original, text, replacement) = match args.as_slice() {
[original, text, replacement] => (original.value(), text.value(), replacement.value()),
_ => {
return syn::Error::new(
input_span,
r#"expected `"<original>", "<text>", "<replacement>"`"#,
)
.into_compile_error()
.into()
}
};
original
.replace(&text, &replacement)
.into_token_stream()
.into()
}
它解析由逗号分隔的三个字符串文字的列表,然后调用 str::replace()
来完成真正的工作。