Brady Dean
Brady Dean

Reputation: 3573

How to help the type inference system infer the type of a closure argument?

I have this closure color, but the type system cannot infer the type of its pixel argument.

pub fn solve_part2(input: &[u32]) -> String {
    let color = |pixel| {
        pixel
            .skip_while(|l| **l == 2)
            .next()
            .map(|c| char::from_digit(*c, 10).unwrap())
            .unwrap()
    };

    let pixel = |n| input.iter().skip(n).step_by(25 * 6);
    (0..(25 * 6)).map(|px| color(pixel(px))).collect()
}

With the type annotated, it becomes

let color = |pixel: std::iter::StepBy<std::iter::Skip<std::slice::Iter<u32>>>| {
    pixel
        .skip_while(|l| **l == 2)
        .next()
        .map(|c| char::from_digit(*c, 10).unwrap())
        .unwrap()
};

Are there any tricks to help the type system infer the type of pixel without annotating?

Upvotes: 1

Views: 81

Answers (1)

phimuemue
phimuemue

Reputation: 35983

So far, I could not come up with something without annotations, but you could reduce the amount of annotation:

You could leave some holes that are to be filled by type inference:

pub fn solve_part2(input: &[u32]) -> String {
    let color = |pixel: std::iter::StepBy<_>| {
        pixel
            .skip_while(|l: &&_| **l == 2)
            .next()
            .map(|c| char::from_digit(*c, 10).unwrap())
            .unwrap()
    };
    let pixel = |n| input.iter().skip(n).step_by(25 * 6);
    (0..(25 * 6)).map(|px| color(pixel(px))).collect()
}

Alternatively, inline color:

pub fn solve_part3(input: &[u32]) -> String {
    let pixel = |n| input.iter().skip(n).step_by(25 * 6);
    (0..(25 * 6)).map(|px| pixel(px)
            .skip_while(|l| **l == 2)
            .next()
            .map(|c| char::from_digit(*c, 10).unwrap())
            .unwrap()).collect()
}

Alternatively, make color a local fn:

pub fn solve_part3(input: &[u32]) -> String {
    fn color<'a>(pixel: impl Iterator<Item=&'a u32>) -> char {
        pixel
            .skip_while(|l| **l == 2)
            .next()
            .map(|c| char::from_digit(*c, 10).unwrap())
            .unwrap()
    };
    let pixel = |n| input.iter().skip(n).step_by(25 * 6);
    (0..(25 * 6)).map(|px| color(pixel(px))).collect()
}

Upvotes: 4

Related Questions