Подходим руки, которые возвращают итераторы?
У меня есть некоторый код, который пытается выполнить сопоставление, где каждая ветвь может возвращать свой тип, но все эти типы реализуютIterator<Item=usize>
,
let found: Iterator<Item = usize> = match requirements {
Requirements::A => MatchingAs { ainternals: [] },
Requirements::B => MatchingBs { binternals: [] },
Requirements::C => MatchingCs { cinternals: [] },
};
return found.any(|m| m == 1)
... где MatchingAs
, MatchingBs
, а также MatchingCs
все impl
std::iter::Iterator<Item = usize>
,
Я бью стену с тем фактом, что Iterator
не размером:
| the trait `std::marker::Sized` is not implemented for `std::iter::Iterator<Item=usize>`
Есть ли хороший подход, чтобы совместимые руки возвращали объекты с общей чертой, а затем полагались (только) на черту при обработке результатов?
1 ответ
Первый рефлекс, когда вы хотите вернуть то, что не Sized
это к Box
это (иначе, положить его в кучу, вернуть указатель):
let found: Box<Iterator<Item = usize>> = match requirements {
Requirements::A => Box::new(MatchingAs { ainternals: [] }),
Requirements::B => Box::new(MatchingBs { binternals: [] }),
Requirements::C => Box::new(MatchingCs { cinternals: [] }),
};
found.any(|m| m == 1)
Здесь этого недостаточно, потому что сейчас match
будет жаловаться, что вы возвращаете разные типы: Box<MatchingAs>
, Box<MatchingBs>
...
Тем не мение, Box<Concrete>
может быть приведен к Box<Trait>
всякий раз, когда есть impl Trait for Concrete
, так:
let found = match requirements {
Requirements::A => Box::new(MatchingAs { ainternals: [] }) as Box<Iterator<Item = usize>>,
Requirements::B => Box::new(MatchingBs { binternals: [] }) as Box<Iterator<Item = usize>>,
Requirements::C => Box::new(MatchingCs { cinternals: [] }) as Box<Iterator<Item = usize>>,
};
found.any(|m| m == 1)
Существует, однако, решение без распределения: используйте дженерики.
fn search<T: Iterator<Item = usize>>(t: T) -> bool {
t.any(|m| m == 1)
}
а затем применить эту функцию к каждой ветви match
:
match requirements {
Requirements::A => search(MatchingAs {ainternals: []}),
Requirements::B => search(MatchingBs {binternals: []}),
Requirements::C => search(MatchingCs {cinternals: []}),
}
Компромисс в том, что он немного ближе к ад-колбеку, с несколько косвенным потоком.