我有几种建模为结构的资产类型,例如
#[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,
}
#[derive(Debug)]
struct Pet {
short: String,
name: String,
age: u32,
}
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()
}
}
};
}
impl_getpairs_on_short_and_name!(Vehicle);
impl_getpairs_on_short_and_name!(Pet);
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 from vehicles: {:?}", pairs);
let pets = Vec::from_iter(["dog", "cat"].into_iter().map(|n| Pet {
short: format!("short_{}", n),
name: format!("name_{}", n),
age: 0,
}));
println!("pets: {:#?}", pets);
let pairs = pets.get_pairs();
println!("pairs from pets: {:?}", 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 from vehicles: [("short_A", "name_A"), ("short_B", "name_B"), ("short_C", "name_C")]
pets: [
Pet {
short: "short_dog",
name: "name_dog",
age: 0,
},
Pet {
short: "short_cat",
name: "name_cat",
age: 0,
},
]
pairs from pets: [("short_dog", "name_dog"), ("short_cat", "name_cat")]
*/