I don't know why i am getting this error, I don't even understand what this error actually means.
Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `std::str::Chars<'_>: std::iter::ExactSizeIterator` is not satisfied
--> src/main.rs:15:26
|
15 | .rev();
| ^^^ the trait `std::iter::ExactSizeIterator` is not implemented for `std::str::Chars<'_>`
|
= note: required because of the requirements on the impl of `std::iter::DoubleEndedIterator` for `std::iter::Enumerate<std::str::Chars<'_>>`
= note: required because of the requirements on the impl of `std::iter::DoubleEndedIterator` for `std::iter::Filter<std::iter::Enumerate<std::str::Chars<'_>>, [closure@src/main.rs:5:33: 5:90]>`
= note: required because of the requirements on the impl of `std::iter::DoubleEndedIterator` for `std::iter::Map<std::iter::Filter<std::iter::Enumerate<std::str::Chars<'_>>, [closure@src/main.rs:5:33: 5:90]>, [closure@src/main.rs:6:30: 13:26]>`
= note: required because of the requirements on the impl of `std::iter::DoubleEndedIterator` for `std::iter::Map<std::iter::Map<std::iter::Filter<std::iter::Enumerate<std::str::Chars<'_>>, [closure@src/main.rs:5:33: 5:90]>, [closure@src/main.rs:6:30: 13:26]>, [closure@src/main.rs:14:30: 14:48]>`
rev changes the iteration direction, and will stop when both ends meet. The error tells you that the DoubleEndedIterator trait isn't implemented for this iterator.
You may want to collect the result into a Vec to reverse the iterator, and then call rev.
Enumerate can't count backwards unless it knows how many items are in the incoming iterator. Chars doesn't know how many chars it will produce because utf-8 encoded characters have variable length -- it only knows the total byte length of the whole string.
If you know your string is plain ASCII, probably so for ISBN, then you could iterate bytes instead.
16 | .rev();
| ^^^ method not found in `std::vec::Vec<u32>`
|
= note: the method `rev` exists but the following trait bounds were not satisfied:
`std::vec::Vec<u32>: std::iter::Iterator`
which is required by `&mut std::vec::Vec<u32>: std::iter::Iterator`
`[u32]: std::iter::Iterator`
which is required by `&mut [u32]: std::iter::Iterator`
I mean something like this, although as @cuviper said, since you are checking an ISBN which is probably ASCII, you could work with the bytes instead of chars.
pub fn is_valid_isbn(isbn: &str) -> bool {
let alphanumeric = isbn
.chars()
.enumerate()
.filter(|(index, c)| (*index == 9 && c == &'X') || c.is_numeric())
.map(|(_, character)| {
if character == 'X' {
Some(10)
} else {
character.to_digit(10)
}
})
.map(|x| x.unwrap_or(0))
.collect::<Vec<_>>()
.into_iter()
.rev()
.collect::<Vec<_>>();
println!("Alphanumeric {:?}", alphanumeric);
false
}
So the iterationa over loop is decided by a collect not on the adapaters i.e I can implement multiple maps but they only be run over the whole vector when I collect?
Yes. Iterators are lazy, they only do something if the consumer asks them, and the consumer will query the whole chain at once.
You can also think of this: to iterate over the iterator multiple times, you'd have to clone it before first loop, and then feed the clone to the second loop. But neither map nor collect require the iterator to be clonable.