Trying to understand how rev() works

So I encountered this while reading through the documentation of iter::Map

let mut c = 0;

for pair in vec!['a', 'b', 'c'].into_iter()
                               .map(|letter| { c += 1; (letter, c) })
                               .rev() {
    println!("{:?}", pair);
}

This code produces this result : ('c', 1), ('b', 2), ('a', 3).
This is what is confusing me , why isn't the result ('c', 3), ('b', 2), ('a', 1) ?

I tried asking on some other site and I was told that rev() is called first and then map() and then into_iter() , I wonder why because rev() is the last function to be called.

Your initial call to rev() doesn't actually evaluate the whole iterator result -- it just constructs the iterator type. Iterators are lazy, so the calls updating your mutable state c happen with reverse characters. Your iterator type is roughly Rev<Map<IntoIter>>, and the for-loop calls will look something like this:

  • call Rev::next()
    • call Map::next_back()
      • call IntoIter::next_back()
        • returns 'c'
      • call the map closure
        • c += 1
        • returns ('c', 1)
    • ... returns ('c', 1)
  • call Rev::next()
    • call Map::next_back()
      • call IntoIter::next_back()
        • returns 'b'
      • call the map closure
        • c += 1
        • returns ('b', 2)
    • ... returns ('b', 2)
  • call Rev::next()
    • call Map::next_back()
      • call IntoIter::next_back()
        • returns 'a'
      • call the map closure
        • c += 1
        • returns ('a', 3)
    • ... returns ('a', 3)

For a properly synchronized count, you probably want enumerate().

4 Likes

makes sense to me now , Thanks a lot !!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.