在 Rust 2021 中,我有一个名为
Intersection
的结构类型,我希望将它存储在一个可变长度列表中,所以可能是一个 Vec<Intersection>
。我可以轻松构建一个新容器:
#[derive(Debug)]
struct Intersection {
t: f64,
// ...
}
fn main () {
let i0 = Intersection { t: 0.1 };
let i1 = Intersection { t: 0.2 };
let vs = vec!(i0, i1);
for v in vs {
println!("{:?}", v);
}
}
这使用了
vec!
宏。
我现在想做的是稍微抽象一下容器类型,将实现(
Vec<>
)与 API 的用户分离。现在,为了以最少干扰的方式做到这一点,我可以只使用类型别名来鼓励解耦:
type Intersections = Vec<Implementation>;
为了补充这一点,我还想定义一个辅助函数,从可变数量的
Intersection
对象中创建这样一个集合。所以像这样使用的东西:
fn main () {
let i0 = Intersection { t: 0.1 };
let i1 = Intersection { t: 0.2 };
let i2 = Intersection { t: 0.3 };
let vs = intersections(i0, i1, i2); // <--- what can this be?
for v in vs {
println!("{:?}", v);
}
}
换句话说,我希望将函数
intersections()
的可变数量的参数转发给 vec!
宏。但是我知道 Rust 不支持可变参数,所以我需要编写一个在内部调用 vec!
的宏,也许称之为 intersections!(&i0, &i1, ...)
.
我看过标准库对
vec!
的实现,但我不确定如何将项目列表转发给 vec!
宏。
我很感激,因为我使用的是类型别名,所以我可以直接调用
vec!(...)
,但是我想将接口与 Vector 分离,这样如果我更改容器实现,我可以更改 intersections()
功能或 intersections!
宏以适应新的实现。这是在 C、C++、Haskell 等语言中很常见的事情,因此类型可以在以后重新定义。
vec!
宏的现有规则:
macro_rules! intersection {
() => { vec![] };
($elem:expr; $n:expr) => { vec![$elem; $n] };
($($x:expr),+ $(,)?) => { vec![$($x),+] };
}
然后你可以像这样调用你的
intersection!
宏,例如:
let vs = intersection![i0, i1];
// requires Intersection to implement Clone
let vs = intersection![Intersection { t: 0.1} ; 2];
let vs: Intersections = intersection![];
您可以将
vec
重新导出为intersections
pub use std::vec as intersections;
fn main() {
println!("{:?}",intersections!(1,2));
}