我正在尝试找出惯用的堆叠迭代器的方式。我正在尝试使用Vec
个可以应用于迭代器的过滤器。
我首先尝试使用的是特征对象Vec
,但是当我尝试将它们存储在配置结构中时,编译器告诉我,由于的通用类型参数,我的特征不是对象安全的我为特征定义的filter
函数。
fn main() {
let domains = vec!["hello.com".to_owned(), "h.com".to_owned()];
let domain_filters = vec![DomainNameLength(5)];
let config = SearchConfig { domain_filters };
let filtered = config.filter_domains(domains);
println!("{:#?}", filtered);
}
struct SearchConfig {
domain_filters: Vec<Box<DomainNameFilter>>,
}
impl SearchConfig {
fn filter_domains(&self, domains: Vec<String>) -> Vec<String> {
filter_domains(self.domain_filters, domains)
}
}
fn filter_domains(filters: Vec<impl DomainNameFilter>, domains: Vec<String>) -> Vec<String> {
let mut filtered: Box<Iterator<Item = String>> = Box::new(domains.into_iter());
for f in filters {
filtered = f.filter(filtered);
}
filtered.collect()
}
trait DomainNameFilter {
fn filter<'a>(
&self,
iter: impl IntoIterator<Item = String> + 'a,
) -> Box<Iterator<Item = String> + 'a>;
}
struct DomainNameLength(u8);
impl DomainNameFilter for DomainNameLength {
fn filter<'a>(
&self,
iter: impl IntoIterator<Item = String> + 'a,
) -> Box<Iterator<Item = String> + 'a> {
let max = self.0;
Box::new(iter.into_iter().filter(move |x| x.len() as u8 <= max))
}
}
error[E0038]: the trait `DomainNameFilter` cannot be made into an object
--> src/main.rs:10:5
|
10 | domain_filters: Vec<Box<DomainNameFilter>>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `DomainNameFilter` cannot be made into an object
|
= note: method `filter` has generic type parameters
我的第二个要解决的问题是一个Vec
枚举,将调度编码为match
语句。这对我来说似乎比较干净,但是我觉得我缺少一个更好的策略。
fn main() {
let domains = vec!["hello.com".to_owned(), "h.com".to_owned()];
let domain_filters = vec![DomainFilter::Length(5)];
let config = SearchConfig { domain_filters };
let filtered = config.filter_domains(domains);
println!("{:#?}", filtered);
}
struct SearchConfig {
domain_filters: Vec<DomainFilter>,
}
impl SearchConfig {
fn filter_domains(&self, domains: Vec<String>) -> Vec<String> {
filter_domains(&self.domain_filters, domains)
}
}
pub enum DomainFilter {
Length(u8),
}
impl DomainFilter {
fn filter<'a>(
&self,
iter: impl Iterator<Item = String> + 'a,
) -> impl Iterator<Item = String> + 'a {
match self {
DomainFilter::Length(max) => {
let m = *max;
iter.filter(move |name| name.len() as u8 <= m)
}
}
}
}
pub fn filter_domains(filters: &[DomainFilter], domains: Vec<String>) -> Vec<String> {
let mut filtered: Box<Iterator<Item = String>> = Box::new(domains.into_iter());
for f in filters {
filtered = Box::new(f.filter(filtered));
}
filtered.collect()
}
我一直在文档中寻找一种构成迭代器的机制,似乎对此没有任何支持。我正在尝试执行以下操作。
let domains = vec!["hello.com"];
let filtered = compose(vec![DomainFilter::Length(5)]).filter(domains);
与this question的主要区别在于,我试图在第一个示例中存储Vec
的非对象安全特征,这是不可能的。在另一个问题中,他们只需要保存下一个整数即可取模。