在为自定义结构实现IntoIterator时,我在指定IntoIterator的IntoIter关联类型的类型时遇到了麻烦。因为into_iter函数调用了一个Map,而它本身返回了一个Map,而且如果我没记错的话,闭包默认会推断出一个新的生命周期(或者类似的东西),我陷入了一个我似乎无法理解的通用汤中。这听起来已经很矛盾了,所以我打算发布代码片段,并尝试解释预期的行为。
请注意,我对正在发生的事情感到非常困惑,所以我问的问题可能不合适,或者可以更好地制定,请随时提出一个更好的建议,以便我可以更新它。
在这段代码中,我们有一个结构(SubstitutionBlock),它以简洁的方式表示许多替换(许多SubstitutionEntry)。这里需要将简洁的表示(SubstitutionBlock)“拆分”为单个条目的迭代(多个SubstitutionEntry)。我试图为SubstitutionBlock实现IntoIterator,以产生SubstitutionEntry对象,但就像我说的,我就是不知道如何实现。
在花了整整一个下午的时间之后,我对代码的解决方案比变通/替代逻辑更感兴趣,但无论如何,如果你确实认为有更好的方法来实现这一点,请随时发布它。
为了完整起见,我发布了一个片段,但我相信Playground链接更有用:
Playground Link
use std::{collections::HashMap, iter::Map};
#[derive(Debug)]
pub struct SubstitutionBlock {
pub id: String,
pub aliases: HashMap<String, Vec<String>>,
pub format: Option<String>,
pub parents: Option<Vec<String>>,
}
#[derive(Debug)]
struct SubstitutionEntry {
id: String,
alias: String,
value: String,
format: Option<String>,
}
impl IntoIterator for SubstitutionBlock {
type Item = SubstitutionEntry;
/// HERE IS WHERE I STRUGGLE
// type IntoIter<'a> = Map<HashMap<String, Vec<String>>, fn((&'a String, &'a Vec<String>)) -> Map<&'a Vec<String>, fn(&String) -> SubstitutionEntry>>;
type IntoIter = Map<HashMap<String, Vec<String>>, fn((&String, &Vec<String>)) -> Map<&Vec<String>, fn(&String) -> SubstitutionEntry>>;
fn into_iter(self) -> Self::IntoIter {
self.aliases
.into_iter()
.map(
|(value, aliases)| aliases.into_iter().map(
|alias| SubstitutionEntry{
id: self.id.to_owned(),
alias: alias.to_owned(),
value: value.to_owned(),
format: self.format.to_owned(),
}
)
)
}
}
fn main() {
let sb = SubstitutionBlock{
id: String::from("id0"),
aliases: HashMap::from([
("value0", vec!["alias0, alias1, alias2"]),
]),
format: None,
parents: None,
};
for entry in sb.into_iter() {
println!("{:?}", entry);
}
}
2条答案
按热度按时间pb3skfrl1#
你想做的事有点不可能。
首先,这里是固定的函数体,以便它作为独立函数编译。你的闭包都不需要生命周期,因为它们都采用自己的值。
不可能的部分是你不能从trait方法返回不透明类型。你可以用几乎完整的类型来替换
impl Iterator<Item = SubstitutionEntry>
,但是当你在Map
上使用闭包类型时,你会被困在使用impl FnMut
,一种不透明类型。现在最好的解决办法就是把它们装箱。你可以装箱封闭,但我已经装箱整个东西,因为它更简单。这就是async-trait所做的。
另一种解决这个问题的方法是创建一个实现
Iterator
的结构体,并将您的逻辑置于其next
方法中,而不是使用map
。重新创建flat_map
的逻辑有点乏味,但是用定制结构替换一系列迭代器适配器的方法总是可行的。All of this in playground
相关内容:
impl Trait
as a function's return type in a trait definition?3pmvbmvn2#
这里是最惯用的解决方案,这是每晚唯一的。