我有几种建模为结构的资产类型,例如
#[derive(Debug, Deserialize, Serialize)]
struct Vehicle {
short: String,
name: String,
number_plate: String,
purchase_cost: u32,
purchase_date: NaiveDate,
charge_minute: f32,
charge_km: f32,
}
不同的结构体有不同的字段,但它们都有一个实现 ToString 的“short”和“name”字段(实际上它们都是字符串)
我想获得(短,名称)对的 Vec,所以:
fn vehicle_pairs(vs: &Vec<Vehicle>) -> Vec<(String, String)> {
vs.iter()
.map(|v| (v.short.to_string(), v.name.to_string()))
.collect::<Vec<_>>()
}
这很好。 为了将此函数推广到其他类型,我可能需要一个宏,因为为了使其通用,我需要指定与字段而不是方法相关的边界,我不相信这是可能的。
我是宏新手,今天刚刚阅读了一些文档。 我的第一次尝试:
macro_rules! pairs {
($T:ty) => {
fn get_pairs<T>(xs: &Vec<T>) -> Vec<(String, String)> {
xs.iter()
.map(|x| (x.short.to_string(), x.name.to_string()))
.collect::<Vec<_>>()
}
}
}
pairs!(Vehicle);
但这行不通。
如何创建一个通用函数,从具有这些字段的结构中提取(短,名称)?
我认为在我们的尝试中,宏的通用方面和通用参数
<T>
之间存在混淆。
我理解您认为
get_pairs()
适用于具有两个成员 short
和 names
可转换为 String
的 something序列。
首先,我会引入一个声明
get_pairs()
函数的特征。
然后宏可以帮助实现我们发现相关的任何序列。
#[derive(Debug)]
struct Vehicle {
short: String,
name: String,
number_plate: String,
purchase_cost: u32,
charge_minute: f32,
charge_km: f32,
}
trait GetPairs {
fn get_pairs(&self) -> Vec<(String, String)>;
}
macro_rules! impl_getpairs_on_short_and_name {
($T:ty) => {
impl GetPairs for [$T] {
fn get_pairs(&self) -> Vec<(String, String)> {
self.iter()
.map(|x| (x.short.to_string(), x.name.to_string()))
.collect::<Vec<_>>()
}
}
};
}
impl_getpairs_on_short_and_name!(Vehicle);
fn main() {
let vehicles =
Vec::from_iter(["A", "B", "C"].into_iter().map(|n| Vehicle {
short: format!("short_{}", n),
name: format!("name_{}", n),
number_plate: format!("plate_{}", n),
purchase_cost: 0,
charge_minute: 0.0,
charge_km: 0.0,
}));
println!("vehicles: {:#?}", vehicles);
let pairs = vehicles.get_pairs();
println!("pairs: {:?}", pairs);
}
/*
vehicles: [
Vehicle {
short: "short_A",
name: "name_A",
number_plate: "plate_A",
purchase_cost: 0,
charge_minute: 0.0,
charge_km: 0.0,
},
Vehicle {
short: "short_B",
name: "name_B",
number_plate: "plate_B",
purchase_cost: 0,
charge_minute: 0.0,
charge_km: 0.0,
},
Vehicle {
short: "short_C",
name: "name_C",
number_plate: "plate_C",
purchase_cost: 0,
charge_minute: 0.0,
charge_km: 0.0,
},
]
pairs: [("short_A", "name_A"), ("short_B", "name_B"), ("short_C", "name_C")]
*/