假设我有一个这样的结构:
struct Foo {
a: i32,
b: i32,
}有没有可能用macro_rules定义一个宏,这样我就可以创建这样的Foo了?
let f1 = make_foo!(
a=5,
);
let f2 = make_foo!(
b=2,
a=6,
);
let f3 = make_foo!(
b=9,
);
let f4 = make_foo!();我希望所有参数都是可选的-我将在宏中或通过Default特性指定一个默认值-理想情况下,顺序并不重要,尽管这只是“拥有它很好”。
发布于 2021-04-26 01:11:57
使用字段记录更新语法可以做到这一点:
#[derive(Debug, Default)]
struct Foo {
a: i32,
b: i32,
}
macro_rules! make_foo {
($($field:ident = $value:expr),* $(,)?) => {
Foo {
$(
$field: $value,
)*
..Default::default()
}
}
}发布于 2021-04-26 03:40:00
为了跟进Cerberus的回答,如果您想对传递的值进行逐个字段处理,可以添加一个具有匹配字段名的函数的模块,如下所示:
#[derive(Debug, Default)]
pub struct Foo {
a: i32,
b: String,
}
mod foo_setters {
pub fn a(x: i32) -> i32 { x }
pub fn b(x: &str) -> String { x.to_owned() }
}
macro_rules! make_foo {
($($field:ident = $value:expr),* $(,)?) => {
Foo {
$(
$field: foo_setters::$field($value),
)*
..Default::default()
}
}
}
pub fn foo() -> Foo {
make_foo!(
a = 5,
b = "hi", // No need for .to_string()!
)
}发布于 2021-04-26 00:42:09
棘手的部分是找出存在哪些字段。也许可以编写一个proc宏来实现这一点,但我建议您使用另一种方法。
Rust中惯用的方式是使用Builder模式。有一个crate可以自动为您的:https://docs.rs/derive_builder/0.10.2/derive_builder/编写这些构建器
https://stackoverflow.com/questions/67255730
复制相似问题