4

I'm trying to decode a digit to an integer and either get an iterator over just this digit or an empty iterator if it wasn't a digit. I tried to do it like that:

let ch = '1';
ch.to_digit(10).map(once).unwrap_or(empty())

This doesn't compile. I get the following error message:

error[E0308]: mismatched types
 --> src/lib.rs:6:41
  |
6 |     ch.to_digit(10).map(once).unwrap_or(empty());
  |                                         ^^^^^^^ expected struct `std::iter::Once`, found struct `std::iter::Empty`
error[E0308]: mismatched types
 --> src/lib.rs:6:41
  |
6 |     ch.to_digit(10).map(once).unwrap_or(empty());
  |                                         ^^^^^^^ expected struct `std::iter::Once`, found struct `std::iter::Empty`
  |
  |
  = note: expected type `std::iter::Once<u32>`
             found type `std::iter::Empty<_>`

  = note: expected type `std::iter::Once<u32>`
             found type `std::iter::Empty<_>`

I there any way to tell the .unwrap_or(...) that I don't care of the actual type, but just that I will get an implementation of Iterator?

Matthias Wimmer
  • 3,789
  • 2
  • 22
  • 41
  • I believe your question is answered by the answers of [What is the correct way to return an Iterator (or any other trait)?](https://stackoverflow.com/q/27535289/155423) and [Conditionally iterate over one of several possible iterators](https://stackoverflow.com/q/29760668/155423). If you disagree, please [edit] your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Aug 02 '18 at 22:29
  • TL;DR the duplicates: No. [Use `Either`](https://stackoverflow.com/a/50204370/155423) or [a boxed trait object](https://stackoverflow.com/a/29760740/155423). – Shepmaster Aug 02 '18 at 22:30
  • I don't think that my problem is a duplicate of https://stackoverflow.com/questions/27535289/what-is-the-correct-way-to-return-an-iterator-or-any-other-trait?noredirect=1&lq=1 as my problem isn't related to the return type of the function. I'll check whether the `Either` helps. Thanks. – Matthias Wimmer Aug 03 '18 at 06:07
  • I think what I actually was asking is how to convert an `Option` to an iterator over the contained value (if any). That's exactly what the `.iter()` method on `std::option::Option` is for. So I might just delete this question as the answer is in the rust docs. What do you think? – Matthias Wimmer Aug 03 '18 at 07:12
  • 1
    You can also answer your own question if you believe someone might someday have the same problem as you – mcarton Aug 03 '18 at 08:07
  • *as my problem isn't related to the return type of the function* — yes, it is, because you were trying to return *either* a `iter::Once` **or** `iter::Empty`. It's literally what the error message states. You are trying to return one type in one case and a different type in another case. – Shepmaster Aug 03 '18 at 12:27

1 Answers1

3

The IntoIterator trait exists solely for the purpose of being able to convert types into iterators:

Conversion into an Iterator.

By implementing IntoIterator for a type, you define how it will be converted to an iterator. This is common for types which describe a collection of some kind.

One benefit of implementing IntoIterator is that your type will work with Rust's for loop syntax.

How to convert an Option<T> to an iterator of zero or one element?

Option implements IntoIterator:

impl<'a, T> IntoIterator for &'a mut Option<T>
impl<T> IntoIterator for Option<T>
impl<'a, T> IntoIterator for &'a Option<T>

The same is true for Result.

All you need to do is call into_iter (or use the value in a place that calls IntoIterator like a for loop):

fn x() -> impl Iterator<Item = u32> {
    let ch = '1';
    ch.to_digit(10).into_iter()
}

See also:

Community
  • 1
  • 1
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366