我有个很奇怪的疑问
我正在学习rust编程书,在一个章节中,他们建议做一个温度转换器......我实际上做了,问题是我不明白为什么工作。
主要问题出现在我试图复制一段代码时,这段代码允许我比较用户引入的值是否是浮点类型。
当我把代码,我试图编译我得到下一个错误。
Compiling enums v0.1.0 (C:\Users\ruben\Proyectos\Rust\the_rust_programming_language\enums)
error[E0308]: mismatched types
--> src\main.rs:96:35
|
96 | Err(parse_float_error) => {
| ___________________________________^
97 | | println!("Please input a valid value. _{}_", parse_float_error);
98 | | }
| |_________^ expected `f64`, found `()`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `enums` due to previous error
这是生成错误的代码:
use std::io;
fn user_input() -> String {
let mut user_input: String = String::new();
io::stdin()
.read_line(&mut user_input)
.expect("Failed to read line");
return user_input;
}
fn main() {
let fahrenheit: f64 = match user_input().trim().parse() {
Ok(f64) => f64,
Err(parse_float_error) => {
println!("Please input a valid value. _{}_", parse_float_error);
}
};
}
The working full version of the temperature converter could be find here
***最有可能的是,必须有一个更好的方法来构建代码,所以如果你们中的一些人有建议,我很乐意阅读它。
我知道问题是enum
类型的,问题是我真的不知道enums
是如何工作的。
对我来说,以一种简单的方式,当一段数据是enum
中可用的一种或另一种数据时,使用enum
,我得到了一个帮助我以这种方式理解它的例子:枚举。问题是我真的,真的不明白它,这本书也没有帮助。
我知道这是一个非常普遍的问题,但如果有人有一个北方遵循它会有很大帮助。
谢谢你。
2条答案
按热度按时间3vpjnl9f1#
对我来说,用一种简单的方式,当一段数据是枚举中可用的一种或另一种时,就使用枚举
大多数情况下,枚举可以有一个或多个变体,并且每个变体可以(但不是必须)有关联的数据。每个变体的数据类型可以相同或不同。
result
枚举具体有两个变体。Ok
变体表示操作成功。Err
变体表示存在错误。result
是泛型类型,它有两个类型参数,T
表示预期结果的类型,E
表示错误的类型。在这一点上值得注意的是,在rust中推断类型的方式与C、C和许多其他流行语言有很大的不同。在C/C中确定表达式类型的过程是从表达式的最里面部分向外流动的。每个函数调用或操作符都是基于其参数的类型来选择的,并确定其结果的类型。这反过来又成为下一步向外的参数。相比之下,在Rust中,类型推断可以在两个方向上运行。表达式中的类型可以,而且经常是,从您对结果所做的事情中推断出来的。
match表达式允许您分解枚举,并根据您拥有的变量采取不同的操作。
考虑到所有这些,让我们分解您的代码。
我们声明了一个名为
fahrenheit
的变量,并显式地告诉编译器它的类型。当编译器试图解释表达式时,这个类型将驱动类型检查和推理。我们开始匹配表达式。
我们调用一个函数,该函数在任何方面都不是泛型的,因此编译器可以使用另一种类型
String
。我们在String上调用trim方法。同样,这不是泛型,所以我们又有了一个固定的类型
&str
。这里是事情变得更有趣的地方,“parse”是一个泛型函数。它返回一个
result
,但result
的泛型参数不是固定的,它们必须从用户对结果的操作和parse
签名中的限制来推断。如果结果是
Ok
,我们将值展开并返回它。这里使用f64
有点不合适,它看起来像一个类型名,但实际上更像一个变量名。如果您编写了Ok(v) => v,
,您的代码将表现相同,并且更符合习惯无论如何,表达式的这一部分让类型推断完成它的工作。您已经匹配了
Ok
变体并将结果视为f64。因此T
必须是f64
。将其与parse
的签名和f64
的FromStr
的实现相结合,意味着E
必须是ParseFloatError
。这就是我们出错的地方。我们已经打印了一个错误消息,但我们实际上还没有处理这个错误!我们仍然有一个需要f64的表达式,而我们没有!我们需要以一种方式来处理这个错误,要么给我们一个有效的f64,要么向编译器承诺它不需要一个。
有几种方法可以做到这一点。
0.0f64
panic!("foo {}",parse_float_error)
abort()
return
返回break
或continue
unsafe { std::hint::unreachable_unchecked() }
你必须选择其中之一,然后做。
lnvxswe22#
检查字符串是否表示浮点值的最好方法是解析它,这是你的代码正在做的。解析用户输入本身就充满了错误情况,所以你不可避免地要执行大量的错误处理,因为Rust的设计/本质迫使你处理错误。
你的代码真实的是编译器错误。你的
let
...match
arm返回不同的类型:f64
和()
(单元结构体),就像错误消息说的那样。要解决这个问题,从Err臂返回一个f64,就像Ok臂一样: