Rust学习——TRPL-Part3

The Rust Programming Language

系列文章学习 Part 3

Programming a Guessing Game

通过具体例子来学习let, match, methods, associated functions等概念。

1
2
3
4
5
6
7
8
9
10
11
12
13
use std::io;

fn main() {
println!("Guess the number!");
println!("Please input your guess.");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Failed to read line");

println!("You guessed: {}",guess);

}

Procesing a Guess

一些细节讲解,

引入标准的io库

1
use std::io

通过变量储存值

1
let mut guess = String::new();

let声明用于创建变量比如

1
let apples = 5;

mutable and immutable

In Rust, variables are immutable by default. We'll be discussing this concept in detail in the ("Variables and Mutability") section in Chapter 3. The following example shows how to use mut before the variable name to make a variable mutable:

1
2
let apples = 5; // immutable
let mut bananas = 5; // mutable

有关 :: ,注意关联方法(associated function)都是实现在类型上的。io::stdin() 也会放映一个对应类型std::io::Stdin

The :: syntax in the ::new line indicates that new is an associated function of the String type. An associated function is implemented on a type, in this case String.

有关&,引用,和变量一样,也是默认immutable。

Handling Potential Failure with the Result Type

例子的最后一个方法(除了打印)是expect,这简单体现了Rust里面的故障处理功能。前面的read_line不仅接受类型为String的参数,同时还会返回一个值,io::Result。Rust的标准库中具有很多名为Result的类型,一个通用抽象的Result以及各子模块提供的确切的版本,比如io::Result

Result

一个io::Result有名为expect的方法,检测返回值。如果不使用expect会出现如下的warning

1
2
3
4
5
6
7
8
9
10
11
12
13
 eddy@Edwardzcn  ~/rust_projects/guessing_game   master  cargo run
Compiling guessing_game v0.1.0 (/home/eddy/rust_projects/guessing_game)
warning: unused `Result` that must be used
--> src/main.rs:7:5
|
7 | / io::stdin()
8 | | .read_line(&mut guess);
| |___________________________^
|
= note: `#[warn(unused_must_use)]` on by default
= note: this `Result` may be an `Err` variant, which should be handled

warning: 1 warning emitted

Generating a Secret number

Rust 当前标准库中不具备随机数功能。不过我们可以通过使用外部的 crate。

Using a Crate to Get More Functionality

Cargo支持 Semantic Versioning(SemVer).

另外,Cargo 构建时会监测源代码和依赖库的变动,当依赖不进行更新已经编译完成时,Cargo知悉并只重新编译修改的源代码。

About Cargo.lock file

When you build a project for the first time, Cargo figures out all the versions of the dependencies that fit the criteria and then writes them to the Cargo.lock file. When you build your project in the future, Cargo will see that the Cargo.lock file exists and use the versions specified there rather than doing all the work of figuring out versions again. This lets you have a reproducible build automatically. In other words, your project will remain at 0.8.3 until you explicitly upgrade, thanks to the Cargo.lock file.

Updating a Crate to Get a New Version

确实需要更新依赖时,Cargo提供了另一个指令update。Cargo会fetch最新的版本,并且在更新完成后将新版本写入Cargo.lock

注意0.8.x 不会更新大版本至0.9.x系列,除非手动修改Cargo.toml中的依赖信息。

Generating a Random Number

Comparing the guess to the Secret Number

涉及到比较,需要引入标准库里的比较(类型)?std::cmp::OrderingResult类似,Ordering 也是一个枚举类型,值有Less, GreaterEqual

Mismatched Types and Type Inference.

Rust has a strong, static type system. However, it also has type inference. When we wrote let mut guess = String:new(),Rust was able to infer that guess should be a String and didn't make us write the type.

在试图用String类型的猜测数和Random获得的number type随机数比较时,编译器会报mismatched types错误。

Allowing Multiple Guesses with Looping

Quitting After a Correct Guess

loop 关键字可以创建一个infinite loop,同时添加退出方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
loop {
println!("Please input your guess.");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Failed to read line");


let guess: u32 = guess.trim().parse().expect("Please type a number!");
println!("You guessed: {}", guess);
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
};
}

Handling Invalid Input

guess 转换的Result进行匹配。

原来转换

1
let guess: u32 = guess.trim().parse().expect("Please type a number!");

更改后

1
2
3
4
5
6
7
let guess: u32 = match guess.trim().parse() {
Ok(number) => number,
Err(_) => {
println!("Please type a number!");
continue;
}
};

Summary

At this point, you’ve successfully built the guessing game. Congratulations!

This project was a hands-on way to introduce you to many new Rust concepts: let, match, functions, the use of external crates, and more. In the next few chapters, you’ll learn about these concepts in more detail. Chapter 3 covers concepts that most programming languages have, such as variables, data types, and functions, and shows how to use them in Rust. Chapter 4 explores ownership, a feature that makes Rust different from other languages. Chapter 5 discusses structs and method syntax, and Chapter 6 explains how enums work.


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!