У меня есть структура данных Baz
, которую я хочу изменять, где бы она ни находилась внутри инкапсулирующей структуры данных.
Инкапсулирующие объекты живут в Option<Vec<_>>
, и поэтому я пытаюсь создать пустой итератор, а затем соединить его со следующим итератором, но не могу получить правильный пустой тип:
struct Foo {
id: i32,
bars: Option<Vec<Bar>>,
bazs: Option<Vec<Baz>>,
}
struct Bar {
id: i32,
bazs: Option<Vec<Baz>>,
}
struct Baz {
id: i32,
}
fn get_iter<'a>(foos: &'a mut Vec<Foo>) -> impl Iterator<Item = &'a mut Baz> {
foos.iter_mut().flat_map(|foo| {
let foo_bazs = if let Some(foo_bazs) = foo.bazs.as_mut() {
foo_bazs.iter_mut()
} else {
std::iter::empty()
};
let bar_bazs = if let Some(foo_bars) = foo.bars.as_mut() {
foo_bars.iter_mut().flat_map(|foo_bars| {
if let Some(bar_bazs) = foo_bars.bazs.as_mut() {
bar_bazs.iter_mut()
} else {
std::iter::empty()
}
})
} else {
std::iter::empty()
};
foo_bazs.chain(bar_bazs)
})
}
fn main() {}
Этот код дает:
error[E0308]: `if` and `else` have incompatible types
--> src/main.rs:19:13
|
16 | let foo_bazs = if let Some(foo_bazs) = foo.bazs.as_mut() {
| ________________________-
17 | | foo_bazs.iter_mut()
| | ------------------- expected because of this
18 | | } else {
19 | | std::iter::empty()
| | ^^^^^^^^^^^^^^^^^^ expected `IterMut<'_, Baz>`, found `Empty<_>`
20 | | };
| |_________- `if` and `else` have incompatible types
|
= note: expected struct `std::slice::IterMut<'_, Baz>`
found struct `std::iter::Empty<_>`
error[E0308]: `if` and `else` have incompatible types
--> src/main.rs:27:21
|
24 | / if let Some(bar_bazs) = foo_bars.bazs.as_mut() {
25 | | bar_bazs.iter_mut()
| | ------------------- expected because of this
26 | | } else {
27 | | std::iter::empty()
| | ^^^^^^^^^^^^^^^^^^ expected `IterMut<'_, Baz>`, found `Empty<_>`
28 | | }
| |_________________- `if` and `else` have incompatible types
|
= note: expected struct `std::slice::IterMut<'_, Baz>`
found struct `std::iter::Empty<_>`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `rust_test` (bin "rust_test") due to 2 previous errors
[Finished running. Exit status: 101]
Если я поменяю std::iter:empty()
на Default::default()
, ржавчина будет меньше жаловаться:
error[E0277]: the trait bound `FlatMap<std::slice::IterMut<'_, Bar>, std::slice::IterMut<'_, Baz>, {closure@src/main.rs:23:42: 23:52}>: Default` is not satisfied
--> src/main.rs:31:13
|
31 | Default::default()
| ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `FlatMap<std::slice::IterMut<'_, Bar>, std::slice::IterMut<'_, Baz>, {closure@src/main.rs:23:42: 23:52}>`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `rust_test` (bin "rust_test") due to 1 previous error
[Finished running. Exit status: 101]
Как вы можете/необязательно объединять итераторы в цепочку?
Option::iter_mut возвращает итератор, который возвращает один элемент, если Some
, или ни одного элемента, если None
. Вы можете просто использовать это и сгладить результат ( игровая площадка):
foos.iter_mut().flat_map(|foo| {
foo.bazs.iter_mut().flatten().chain(
foo.bars
.iter_mut()
.flatten()
.flat_map(|bar| bar.bazs.iter_mut().flatten()),
)
})