# Why for in loop not break if None is returned?

``````    let mut x1 = [10, 11, 12, 13, 14, 15, 16].iter();
let mut x2 = x1.map(|&v| {
if v == 13 {
None
} else {
Some(v)
}
});

for v in x2 {
println!("{:?}", v);
}
``````

The output is like below:
Some(10)
Some(11)
Some(12)
None
Some(14)
Some(15)
Some(16)

I think it should only output Some(10), 11, 12, then break if None is returned.

Why do you think it should stop at the None?

That's not what `map` does. If you want it to stop after something, you could consider using `take_while`.

(Note that if it was going to stop on `None`, then it shouldn't ever output `Some(10)`, but just `10`, because giving out options-that-aren't-supposed-to-be-none is just a nuisance for the caller.)

1 Like

@H2CO3

std::iter - Rust (rust-lang.org)
It says:

First, we call `into_iter()` on the value. Then, we match on the iterator that returns, calling `next` over and over until we see a `None` . At that point, we `break` out of the loop, and we’re done iterating.

I think for in loop will break if it encounter first None, Does it?

It does. Point is, when you return `None` from the closure in `map`, it doesn't come out as `None` - it comes as `Some(None)`.

3 Likes

But you're not calling `next`; you're using a for loop, which deals with that for you.

If you want to call `next` yourself, then you can stop at the inner `None` like this:

``````    let mut x1 = [10, 11, 12, 13, 14, 15, 16].iter();
let mut x2 = x1.map(|&v| if v == 13 { None } else { Some(v) });

while let Some(Some(v)) = x2.next() {
println!("{:?}", v);
}
``````

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f949c4bf9ac2c8605a3084bc3b697ba1

@Cerber-Ursi @scottmcm

The map signature is like this:

``````fn map<B, F>(self, f: F) -> Map<Self, F>ⓘ
where
F: FnMut(Self::Item) -> B,
``````

So, the return value of map closure is B, not Option<B>.
As the code of mine above, map closure treats the return value as Some(None) and Some(Some(v)).

Thanks you all again.

Another solution:

``````+    let mut ignore_from_here = false;
-    let mut x2 = x1.map(|&v| {
+    let mut x2 = x1.filter_map(|&v| {
-        if v == 13 {
+        if v == 13 || ignore_from_here {
+            ignore_from_here = true;
None
``````

However, it's better to use `take_while`: See Playground.

Using `map` will really just modify each element, and if you make the closure return `Some` or `None`, then the new iterator will return `Some(Some(_))` or `Some(None)` until it finally returns `None`. So you're adding an extra `Option` layer.

Consider this:

``````fn main() {
let x1 = [10, 11].into_iter();
for t in x1 {
println!("{t:?}");
}
let x1 = [10, 11].into_iter();
let x2 = x1.map(|v| Some(v));
for t in x2 {
println!("{t:?}");
}
let x1 = [10, 11].into_iter();
let x2 = x1.map(|v| Some(v));
let x3 = x2.map(|v| Some(v));
for t in x3 {
println!("{t:?}");
}
}
``````

Output:

``````10
11
Some(10)
Some(11)
Some(Some(10))
Some(Some(11))

``````

Some more playing:

``````struct MyIter<'a> {
data: &'a [i32],
index: usize,
}

impl<'a> Iterator for MyIter<'a> {
type Item = i32;
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.data.len() {
return None;
}
let value: i32 = self.data[self.index];
if value == 13 {
// if we increment `self.index` here, the iterator will not be fused, but it still works in this example:
//self.index += 1;
None
} else {
self.index += 1;
Some(value)
}
}
}

fn main() {
let x1 = MyIter { data: &[10, 11, 12, 13, 14, 15, 16], index: 0 };
for v in x1 {
println!("{:?}", v);
}
}
``````

Here, `None` really means that the iteration is finished. This works even if you comment-in `self.index += 1` in the example above. But then the iterator isn't fused.

Edit: I forgot to check `self.index >= self.data.len()` in the example above and just corrected it.

1 Like

A good mental exercise is to consider what would happen if you didn't explicitly return an `Option`, ie. no `Some` or `None`, just a completely different value. How should the iterator know when to stop in such a case?

1 Like

`None` is not special like `NULL` or `nil`. It doesn't "flatten" automatically, so `map` preserves what you return without confusing `None`-from-map with `None`-from-iterator.

To stop iteration on `None`, you can use `from_fn` instead of mapping an existing iterator.

2 Likes

To add to the other solutions, in my opinion the simpliest way to get what you expected is to use `Iterator::map_while`

6 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.