简体   繁体   English

Rust 结果的类型推断

[英]Rust Type Inference for Result

I am new to Rust while going through the documentation for Iterator Trait and running some code I found a strange code behaviour.我是 Rust 的新手,在浏览Iterator Trait 的文档并运行一些代码时,我发现了一个奇怪的代码行为。 I am trying to find some documentation that could explain that (described below).我正在尝试找到一些可以解释这一点的文档(如下所述)。 Could someone please explain or point me to an explanation?有人可以解释或指出我的解释吗?

Problem statement:问题陈述:

When I create a single variable like shown below当我创建如下所示的单个变量时

let testvariable = Ok(1);

I get the error below我收到以下错误

let testvariable = Ok(1);
    ------------   ^^ cannot infer type for type parameter `E` declared on the enum `Result`
    |
    consider giving `testvariable` the explicit type `std::result::Result<i32, E>`, where the type parameter `E` is specified

However, when I create an array as below但是,当我创建如下数组时

let results = [Ok(1), Ok(3)];

There is no error.没有错误。 Somehow Rust has inferred the type of the array to be [std::result::Result<i32, &str>; 2] Rust 以某种方式推断数组的类型为[std::result::Result<i32, &str>; 2] [std::result::Result<i32, &str>; 2]

Edit: Posting code for viewers to try out编辑:发布代码供观众试用

fn main() {
    let testvariable = Ok(1);
    let results = [Ok(1), Ok(3)];
    let result: Result<Vec<_>, &str> = results.iter().cloned().collect();
}

Edit: Rearranged the order of questions to provide clarity on the inquiry.编辑:重新排列问题的顺序以提供清晰的查询。 As I show below, its somewhat clear why &str makes it in the full type of the results array.正如我在下面展示的,它有点清楚为什么&str使它成为results数组的完整类型。 What is not clear is why it does not make it to the type of the testvariable .不清楚的是为什么它没有成为testvariable的类型。

What I am trying to understand is the following:我想了解的是以下内容:

  1. Why does the second case work, while the first case throws an error?为什么第二种情况有效,而第一种情况抛出错误?
  2. How is the type E inferred to be &str in the second case?在第二种情况下,类型E是如何推断为&str的?

Based on my digging around (see below) I could (somewhat) understand how/why the &str type is coming into picture but couldn't explain the difference.根据我的挖掘(见下文),我可以(有点)理解&str类型是如何/为什么出现的,但无法解释其中的区别。

Below I describe some of my efforts to figure this out:下面我描述了我为解决这个问题所做的一些努力:

This seems to be an expected behaviour as shown in the last example here (the type of the results variable should match the above mentioned type).这似乎是预期的行为,如此处最后一个示例所示(结果变量的类型应与上述类型匹配)。

The closest I could get to figuring this out - was the implementation of the ok method on the Result enum here where it assigns the type &str to E in the example below.我最接近解决这个问题的方法是在此处的 Result 枚举上实现 ok 方法,在下面的示例中它将类型&str分配给E

/// let x: Result<u32, &str> = Ok(2);

Post this I am assuming that somehow the variant value of Result::None is being automatically being converted to &str but I couldn't find it.发布这个我假设Result::None的变体值以某种方式被自动转换为 &str 但我找不到它。 Moreover, the comments on the enum keyword in source didn't provide much clues.此外, source中对 enum 关键字的注释并没有提供太多线索。

I assume that your array version is actually this example from the docs :我假设您的数组版本实际上是文档中的这个示例:

let results = [Ok(1), Ok(3)];

let result: Result<Vec<_>, &str> = results.iter().cloned().collect();

// gives us the list of answers
assert_eq!(Ok(vec![1, 3]), result);

The compiler is able to infer that the type for Result::Err is the same for the results array and the result variable.编译器能够推断Result::Err的类型对于results数组和result变量是相同的。 Since the latter is specified to be &str , the compiler also uses it for the array.由于后者被指定为&str ,编译器也将它用于数组。

For your single variable case, if you never use the error variant then the compiler has no way of knowing what it is and complains.对于您的单变量情况,如果您从不使用错误变体,那么编译器将无法知道它是什么并抱怨。

Thanks all who answered.感谢所有回答的人。

My newbie brain took some time before it understood the answer so I am posting a detailed response to this.我的新手大脑花了一些时间才理解答案,所以我发布了对此的详细回复。

Line 1:    fn main() {
Line 2:        let testvariable = Ok(1);
Line 3:        let results = [Ok(1), Ok(3)];
Line 4:        let result: Result<Vec<_>, &str> = results.iter().cloned().collect();
Line 5:    }

Why Line 2 throws an error and Line 3 still works is because the compiler can infer the type of results from usage of results variable in Line 4.为什么第 2 行抛出错误而第 3 行仍然有效,是因为编译器可以根据第 4 行中results变量的使用来推断结果的类型。

I was under the impression that the code that is used for type inference would include only the statement where a variable is defined and beyond that, use the inferred type everywhere else.我的印象是,用于类型推断的代码将仅包括定义变量的语句,除此之外,在其他任何地方都使用推断的类型。

In fact, if we remove the line 4 and try the code snippet below, although the code compiles, the type of results variable changes to error proving that the type of results variable is being inferred due to line 4.事实上,如果我们删除第 4 行并尝试下面的代码片段,虽然代码可以编译,但results变量的类型会更改为error ,证明results变量的类型是由于第 4 行而被推断出来的。

Line 1:    fn main() {
Line 2:        let testvariable = Ok(1);
Line 3:        let results = [Ok(1), Ok(3)];
Line 4:        //let result: Result<Vec<_>, &str> = results.iter().cloned().collect();
Line 5:    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM