Rust 闭包真的不需要类型注释吗?

Thö*_*rni 2 closures rust

我目前正在阅读 Rust 书,刚刚进入主题closures。\n一个让我惊讶的细节是 Rust 书说:

\n
\n

闭包 don\xe2\x80\x99t 要求您注释参数的类型

\n
\n

我立即对此进行了测试,因为它看起来与 Rust 通常的工作方式确实违反直觉。因此,我准确地复制了他们使用的闭包,将其粘贴到我的代码中,然后......出现错误:

\n
fn some_closure() {\n    let expensive_closure = |num| {\n        println!("calculating slowly...");\n        thread::sleep(Duration::from_secs(2));\n        num\n    };\n}\n
Run Code Online (Sandbox Code Playgroud)\n
error[E0282]: type annotations needed\n  --> src/main.rs:14:30\n   |\n14 |     let expensive_closure = |num| {\n   |                              ^^^ consider giving this closure parameter a type\n\nerror: aborting due to previous error\n
Run Code Online (Sandbox Code Playgroud)\n

我确实知道该错误的含义,但我仍然对此感到困惑,因为不仅书籍,而且参考文献都指定不需要注释,但我却收到此错误。

\n

这只是最近的更改尚未记录,还是我误解了什么?

\n

seb*_*etz 5

编译器需要能够以某种方式推断出参数的类型,这可以通过显式类型注释来实现,如上下文信息num: i32或通过上下文信息,例如

fn use_some_closure() {
    let expensive_closure = |num| {
        println!("calculating slowly...");
        thread::sleep(Duration::from_secs(2));
        num
    };
    expensive_closure(42);
}
Run Code Online (Sandbox Code Playgroud)

如果没有注释或用法,就无法弄清楚是什么num

操场


Mas*_*inn 5

这本书,而且参考文献都指定不需要注释,但我收到了这个错误。

不是,书的关键词和参考文献是必填的,这和needed是不一样的。即使通常不需要某些东西,也可能根据上下文需要。

对于闭包,区别与“静态函数”( fn)相反,“静态函数”() 中的注释是语法要求:如果不提供类型注释,则无法编写有效的静态函数,而一般来说,您可以在不提供类型注释的情况下编写闭包。

然而,编译器仍然需要知道闭包的具体类型,这需要能够推断参数和返回类型。如果因为没有足够的约束而不能,它会抱怨并需要显式指定类型。

在您的示例中,没有任何限制 的类型num,因此 rustc 无法知道 的具体类型num是什么,因此无法推断闭包的具体类型应该是什么。

但在大多数情况下有例如

let it = repeat(5).map(|x| x+1);
Run Code Online (Sandbox Code Playgroud)

编译器对此感到满意,因为闭包的输入和输出类型必然是map提供的,即Repeat::Item,在本例中是i32(因为这是整数文字默认禁止其他约束的类型)。