您的位置:首页 > 财经 > 产业 > 怎样在手机上建立自己的网站_长沙房产政务信息网_如何推广公众号_简单的seo

怎样在手机上建立自己的网站_长沙房产政务信息网_如何推广公众号_简单的seo

2024/12/24 2:50:58 来源:https://blog.csdn.net/qq_37387199/article/details/144634589  浏览:    关键词:怎样在手机上建立自己的网站_长沙房产政务信息网_如何推广公众号_简单的seo
怎样在手机上建立自己的网站_长沙房产政务信息网_如何推广公众号_简单的seo

题目来自:https://practice-zh.course.rs/result-panic/result.html

1


// 填空并修复错误
use std::num::ParseIntError;fn multiply(n1_str: &str, n2_str: &str) -> __ {let n1 = n1_str.parse::<i32>();let n2 = n2_str.parse::<i32>();Ok(n1.unwrap() * n2.unwrap())
}fn main() {let result = multiply("10", "2");assert_eq!(result, __);let result = multiply("t", "2");assert_eq!(result.__, 8);println!("Success!")
}

当你在IDE里敲下如上代码的时候,第一个问题就解决了:
IDE 中的错误显示
unwrap意味着遇到错误不再返回错误,而是当场panic,因此我们不能让它出现错误。

use std::num::ParseIntError;fn multiply(n1_str: &str, n2_str: &str) -> Result<i32, ParseIntError> {let n1 = n1_str.parse::<i32>();let n2 = n2_str.parse::<i32>();Ok(n1.unwrap() * n2.unwrap())
}fn main() {let result = multiply("10", "2");assert_eq!(result, Ok(20));let result = multiply("4", "2");assert_eq!(result.unwrap(), 8);println!("Success!")
}

2


use std::num::ParseIntError;// 使用 `?` 来实现 multiply
// 不要使用 unwrap !
fn multiply(n1_str: &str, n2_str: &str) -> __ {
}fn main() {assert_eq!(multiply("3", "4").unwrap(), 12);println!("Success!")
}

?unwrap 非常像,但是 ? 会返回一个错误,而不是直接 panic.

fn multiply(n1_str: &str, n2_str: &str) -> Result<i32, ParseIntError> {let n1 = n1_str.parse::<i32>()?;let n2 = n2_str.parse::<i32>()?;Ok(n1 * n2)
}fn main() {assert_eq!(multiply("3", "4"), Ok(12));println!("Success!")
}

问号在C++中大多用于三元表达式,Rust删除了这一功能。此外,Rust的这个问号设计显然借鉴了一些现代的语言(比如Kotilin用问号代表变量可能为空,让编译器放弃空指针检查)

3


use std::fs::File;
use std::io::{self, Read};fn read_file1() -> Result<String, io::Error> {let f = File::open("hello.txt");let mut f = match f {Ok(file) => file,Err(e) => return Err(e),};let mut s = String::new();match f.read_to_string(&mut s) {Ok(_) => Ok(s),Err(e) => Err(e),}
}// 填空
// 不要修改其它代码
fn read_file2() -> Result<String, io::Error> {let mut s = String::new();__;Ok(s)
}fn main() {assert_eq!(read_file1().unwrap_err().to_string(), read_file2().unwrap_err().to_string());println!("Success!")
}

其实就是将上面的写法转成问号表达式:

fn read_file2() -> Result<String, io::Error> {let mut s = String::new();let f = File::open("hello.txt")?.read_to_string(&mut s)?;Ok(s)
}

另外这个unwrap_err,网上甚至都搜不到(Rust的普及还是任重道远),我看了下源代码的介绍,很有意思。

Returns the contained [Err] value, consuming the self value.
Panics if the value is an [Ok], with a custom panic message provided by the [Ok]'s value.

源代码如下:

    #[inline]#[track_caller]#[stable(feature = "rust1", since = "1.0.0")]pub fn unwrap_err(self) -> EwhereT: fmt::Debug,{match self {Ok(t) => unwrap_failed("called `Result::unwrap_err()` on an `Ok` value", &t),Err(e) => e,}}

unwrap刚好相反,unwrap_err的调用者如果是Ok(msg),会panicmsg传入panic打印出来;如果是Err(msg),则返回msg
示例如下:

let x: Result<u32, &str> = Ok(2);
x.unwrap_err(); // panics with `2`
let x: Result<u32, &str> = Err("emergency failure");
assert_eq!(x.unwrap_err(), "emergency failure");

4

use std::num::ParseIntError;// 使用两种方式填空: map, and then
fn add_two(n_str: &str) -> Result<i32, ParseIntError> {n_str.parse::<i32>().__
}fn main() {assert_eq!(add_two("4").unwrap(), 6);println!("Success!")
}

map

map的源代码如下:

    #[inline]#[stable(feature = "rust1", since = "1.0.0")]pub fn map<U, F: FnOnce(T) -> U>(self, op: F) -> Result<U, E> {match self {Ok(t) => Ok(op(t)),Err(e) => Err(e),}}

用于在方法和返回Result之间执行某些操作。这些操作只会对正确的结果执行。
答案如下:

fn add_two(n_str: &str) -> Result<i32, ParseIntError> {n_str.parse::<i32>().map(|num| num+2)
}

and_then

and_then的源代码如下:

    #[inline]#[stable(feature = "rust1", since = "1.0.0")]#[rustc_confusables("flat_map", "flatmap")]pub fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> Result<U, E> {match self {Ok(t) => op(t),Err(e) => Err(e),}}

相比于mapand_then需要自行构造返回值,而map可以直接使用调用者的返回值。比如这里map直接返回num+2,相当于一种“替换”操作,返回的时候会自动加壳Ok;而and_then不再使用调用者的返回值了,需要自行构造Ok。这样会更加灵活,比如,也许你不需要Result,需要一个自定义的结构啥的。

fn add_two(n_str: &str) -> Result<i32, ParseIntError> {n_str.parse::<i32>().and_then(|num| Ok(num + 2))
}

5

use std::num::ParseIntError;// 使用 Result 重写后,我们使用模式匹配的方式来处理,而无需使用 `unwrap`
// 但是这种写法实在过于啰嗦..
fn multiply(n1_str: &str, n2_str: &str) -> Result<i32, ParseIntError> {match n1_str.parse::<i32>() {Ok(n1)  => {match n2_str.parse::<i32>() {Ok(n2)  => {Ok(n1 * n2)},Err(e) => Err(e),}},Err(e) => Err(e),}
}// 重写上面的 `multiply` ,让它尽量简洁
// 提示:使用 `and_then` 和 `map`
fn multiply1(n1_str: &str, n2_str: &str) -> Result<i32, ParseIntError> {// 实现...
}fn print(result: Result<i32, ParseIntError>) {match result {Ok(n)  => println!("n is {}", n),Err(e) => println!("Error: {}", e),}
}fn main() {let twenty = multiply1("10", "2");print(twenty);// 下面的调用会提供更有帮助的错误信息let tt = multiply("t", "2");print(tt);println!("Success!")
}

这个例子用and_then和map就很勉强了,降低了一点啰嗦,但是没完全去除:

fn multiply1(n1_str: &str, n2_str: &str) -> Result<i32, ParseIntError> {n1_str.parse::<i32>().and_then(|n1| {n2_str.parse::<i32>().map(|n2|{n1*n2})})
}

最简单的办法还是之前提到的问号表达:

fn multiply1(n1_str: &str, n2_str: &str) -> Result<i32, ParseIntError> {let n1: i32 = n1_str.parse()?;let n2: i32 = n2_str.parse()?;Ok(n1 * n2)
}

6

use std::num::ParseIntError;// 填空
type __;// 使用上面的别名来引用原来的 `Result` 类型
fn multiply(first_number_str: &str, second_number_str: &str) -> Res<i32> {first_number_str.parse::<i32>().and_then(|first_number| {second_number_str.parse::<i32>().map(|second_number| first_number * second_number)})
}// 同样, 这里也使用了类型别名来简化代码
fn print(result: Res<i32>) {match result {Ok(n)  => println!("n is {}", n),Err(e) => println!("Error: {}", e),}
}fn main() {print(multiply("10", "2"));print(multiply("t", "2"));println!("Success!")
}

有点类似C的typedef和C++的using

type Res<i32> = Result<i32, ParseIntError>;

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com