#(AOC Day 2 Part 2 Spoilers) Why can't I chain `iter.map()` calls here?

7 messages · Page 1 of 1 (latest)

echo fox
#

This is my first year doing Advent of Code and I'm starting to really love working with iterators in Rust. :)

I finished the second part of day 2, but I ran into a minor issue that I really didn't look further into or try to "fix" but it sorta caught my attention. When I chain .map() calls here, it seems to have an issue with the lifetime of the stuff returned from the previous call to .map()...? What is this for<'a> fn(&'a T) -> _ type it's talking about? Is there some way to make this work while still having the chain or is my hacky fix the only way?

fn main() {
    let input = inputfile!("2.txt");

    // vvv WORKING CODE vvv
    let sum = input
        .lines()
        .map(|line| Game::from_line(line).required_counts().power())
        .sum::<u32>();

    let sum = input
        .lines()
        .map(|line| Game::from_line(line).required_counts())
        .map(RGB::power)
        .sum::<u32>();
    // BROKEN ^^^
    // Diagnostics:
    // 1. type mismatch in function arguments
    //    expected function signature `fn(RGB) -> _`
    //       found function signature `for<'a> fn(&'a RGB) -> _` [E0631]
    // 2. required by a bound introduced by this call [E0631]

    let sum = input
        .lines()
        .map(Game::from_line)
        .map(Game::required_counts)
        .map(RGB::power)
        .sum::<u32>();
    // BROKEN ^^^
    // Diagnostics:
    // 1. the method `map` exists for struct `Map<Map<Lines<'_>, fn(&str) ->
    // Game {Game::from_line}>, fn(&Game) -> RGB {Game::required_counts}>`, but its trait bounds were not satisfied
    //    the following trait bounds were not satisfied:
    //    `Map<Map<std::str::Lines<'_>, for<'a> fn(&'a str) -> Game {Game::from_line}>, for<'a> fn(&'a Game) -> RGB {Game::required_counts}>: Iterator`
    //    which is required by `&mut Map<Map<std::str::Lines<'_>, for<'a> fn(&'a str) ->
    //    Game {Game::from_line}>, for<'a> fn(&'a Game) -> RGB {Game::required_counts}>: Iterator` [E0599]

    println!("{}", sum);
}
echo fox
#

oddly enough this seems to work...

    let sum = input
        .lines()
        .map(Game::from_line)
        .map(|v| v.required_counts())
        .map(|v| v.power())
        .sum::<u32>();
#

so the whole for<'a> thing is irrelevant? it's just complaining that i'm passing the value and not a reference?

burnt token
#

Yeah, it looks like that's the case. The compiler error in the first broken snippet is clear on that - expecting an owned value to the function but the function takes a reference (function provided to map takes ownership of the Iterator items and changes them into something else)

The compiler error in the second one though is more terse, and seems to more imply that the Map structure produced by the second call doesn't implement Iterator for some reason (probably due to the generic parameters involved and the way Iterator trait is implemented for that type with respect to them)

So seems like there's two different compiler errors there to me though I haven't the foggiest about the second one with the failed bounds for implementing Iterator

echo fox
#

so the second one is just the same thing but looks less readable cuz the type is Map<...> instead of just T... right?