【问题标题】:How to help the type inference system infer the type of a closure argument?如何帮助类型推断系统推断闭包参数的类型?
【发布时间】:2020-04-29 15:04:28
【问题描述】:

我有这个闭包color,但类型系统无法推断其pixel 参数的类型。

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()
}

加上注解的类型,就变成了

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()
};

有没有什么技巧可以帮助类型系统在不注解的情况下推断pixel的类型?

【问题讨论】:

  • 如果 color 闭包只使用一次,您可以将它内联移动到 map 调用中。
  • @Dai 这就是我最初拥有它的方式,但为了清楚起见将其移出。它确实内联工作正常。
  • 另一种选择是使用类型别名。您还可以通过将这些类型导入作用域来使其更简洁 - 请记住,Rust 不是 C++,因此您无需避免导入命名空间(与 C++ 中的 using namespace std; 不同):stackoverflow.com/questions/29013617/… - 所以没有任何问题在你的代码中有StepBy&lt;Skip&lt;Itr&lt;u32&gt;&gt;&gt;。
  • 关于为什么在闭包中需要类型注释的部分相关讨论:google.com/amp/s/amp.reddit.com/r/rust/comments/5g6oa0/…
  • 可以是known issue。

标签: rust type-inference


【解决方案1】:

到目前为止,我想不出没有注释的东西,但你可以减少注释的数量:

你可以留下一些需要通过类型推断来填补的漏洞:

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()
}

或者,内联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()
}

或者,将color 设为本地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()
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多