Rust Study
Spend time on studying RUST
, stay hungry and stay foolish.
Never give up, keep climbing~
Reference
https://reberhardt.com/cs110l/spring-2020/
https://course.rs/about-book.html
https://practice.rs/why-exercise.html
https://practice.rs/why-exercise.html
https://www.runoob.com/rust/rust-tutorial.html
Programming a Guessing Game - The Rust Programming Language (rust-lang.org)
Install rust
fix success or fail
After installation, we run rustc -V
and cargo -V
and will see the details of version.
local documents
Run rustup doc
.
When we don’t know how to use the functions, we can find them in API documents
.
Build vscode
run rust code
I have installed and compiled the environment of the vscode with rust.
An example.
1 | fn main() { |
compile, build and run.
Using the command line and run main.exe
, we can also get the output.
install plugins
Some recommended plugins.
- Even Better TOML: support the complete
.toml
- Error Lens: emm, details of the errors. It will impact
sagemath
. so, I uninstall it - One Dark Pro: theme
- CodeLLDB: Debugger
Cargo
compile project
Management about rust.
Run in command line, new the project.
Run cargo run
, it will build and compile the project and print the output finally.
It defaults to debug
mode. If we want to switch to release
mode to optimize the project, we can run cargo run --release
directly.
Use vscode directly, we also achieve the target.
- cargo
cargo run
mode: debugcargo build
mode: debugcargo run --release
mode: releasecargo build --release
mode: releasecargo check
check that the project code can be run if the size of project is too large.
- vscode
- Use according to what you need.
cargo documents
cargo.toml
and cargo.lock
are the core part of cargo. All things about cargo are about these two documents.
cargo.toml
: description of project data, which is import for the rust project.cargo.lock
: detailed manifest of project dependencies, which is mainly depended on the rust project itself.
cargo.toml
is like this. It first shows the details about the project, containing name
/version
/edition
.
Second it shows what it depends on. There are three ways to introduce dependencies.
- based on
crates.io
: specify version information - based on
the url
of the source code of the local repository - based on
the absolute or relative path
of the local repository
Three ways to import dependencies:
1 | [dependencies] |
Hello World
RustProject/greeting
RustProject/advanced_code
test code:
1 | fn greet_world() { |
How to run?
- Vscode, and just
run code
. - Cmd, open a terminal and go to the root of world_hello project. Run
cargo [project_name]
.
Look at the code carefully, we can get:
- Rust natively supports
UTF-8
encode strings. println!
. In Rust, this is the macro operator, and we can currently think of a macro as a special type of function.- We use
{}
, which can automatically recognize the type of the output data. - Rust’s collection types can’t loop directly and need to become iterators.
advanced code
1 | fn main() { |
debug
terminal
1 | cargo run |
cmd
release
terminal
1 | cargo run --release |
cmd
understand code
- Control flow:
for
go withcontinue
- Method syntax: Since Rust has no inheritance, Rust is not an object-oriented language in the traditional sense, but it steals methods from the OO language using
record.trim()
,record.split(',')
, etc. - Lambda function: Functions can be taken as parameters or as return values.
Guess game
RustProject/guessing_game
accept the user’s input
1 | use std::io; |
go over it line by line
1 | use std::io; |
bring the io library which comes from the standard library (std)
1 | fn main(){} |
fn
means a new function
1 | println!("Guessing the number!"); |
state what the game is
request input from the user
1 | let mut guess = String::new(); |
let
statement to create a variable to store the user’s input, to remember that once given it will not change, for example:
1 | let apples = 5; |
Thus, we add mut
before the variable name.
1 | //example |
the ::
in ::new
line indicates that new
is an associated function of the String
type.
let mut guess = String::new();
means that it created a mutable variable that is currently bound to a new, empty instance of a String
.
1 | io::stdin() |
call stdin
function from io
module, which allows us to handle user input
.read_line(&mut guess)
call the read_line
method on the standard input to get input from the user.
pass &mut guess
to read_line
to tell string to store the user’s input
&
indicates that this argument is a reference, no need to copy that data into memory multiple times
1 | .expect("Failed to read line"); |
return a Result
type to encode error-handling information
Result
‘s variants are Ok
and Err
.
If we don’t call expect
, the program will compile, but it will get a warning.
The right way to suppress the warning is to actually write error-handling code, but in our case we just want to crash this program when a problem occurs, so we can use expect
.
PAY ATTENTION ! Expect
NOT Except
!!!
1 | println!("You guessed: {}", guess); |
The line prints the string that now contains the user’s input.
generate a random number
Aim to generate a secret number that we will try to guess.
The random number between 1 and 100.
The rand
crate is a library crate, which contains code that is intended to be used in other programs and can’t be executed on its own.
crate is a term in Rust, meaning a stand-alone library or project
library crate
which means the project contains library code
So we should import it in Cargo.toml
which include the rand
crate as a dependency.
1 | [dependencies] |
contains below:
- crate name
- crate version
run cargo build
after adding the rand crate as a dependency
After updating the registry, Cargo checks the [dependencies]
section and downloads any crates listed that aren’t already downloaded. In this case, although we only listed rand
as a dependency, Cargo also grabbed other crates that rand
depends on to work. After downloading the crates, Rust compiles them and then compiles the project with the dependencies available.
add code to generate a random number:
1 | use rand::Rng; |
go over it line by line
First, add the line use rand::Rng;
. Rng
trait defines methods that random generators implement, and the trait must be in scope for us to use those methods.
Second, we call rand::thread_rng
function that gives us the random generator, and it is local to the current thread of execution and is seeded by the operating system.
Third, gen_range
is a function that define the random number range, which we brought into scope with the rand::Rng;
statement.
The usage is that start..=end
, is inclusive on the lower and upper bounds. For example 1..=100
means request a number between 1 and 100.
You won’t just know which traits to use and which methods and functions to call from a crate, so each crate has documentation with instructions for using it.
ensure reproducible build with the cargo.lock
file
Rust creates the Cargo.lock
file the first time when running cargo build
.
The Cargo.lock
file is important for reproducible builds, and it’s often checked into source control with the rest of the code in your project.
update a crat to get a new version
1 | cargo update |
and the dependencies will change.
The next time you run cargo build
, Cargo will update the registry of crates available and reevaluate your rand
requirements according to the new version you have specified.
Cargo makes it very easy to reuse libraries, so Rustaceans are able to write smaller projects that are assembled from a number of packages.
Rustaceans means users or developers who use the Rust
at this time, the complete code is:
1 | use std::io; //bring the io library which comes from the standard library (std) |
when we run cargo run
, we will see:
However it won’t achieve the aim to generate a secret number and compare it to the guessing number.
compare the guess to the secret number
Step1
make a comparison
1 | use std::cmp::Ordering |
However it return a number comparison and break.
Step2
turn into a loop
Notice the numbers’ usage and the order of using these different numbers.
We ought to generate different guess
to solve out the secret_number
which is generated by the system.
So secret_number
is above loop.
1 | let secret_number = rand::thread_rng().gen_range(1..=100); |
Step3
equal then break
1 | match guess.cmp(&secret_number) { |
complete code
1 | use std::io; |
run cargo run
:
handle invalid input
To further refine the game’s behavior, rather than crashing the program when the user inputs a non-number, let’s make the game ignore a non-number so the user can continue guessing. We can do that by altering the line where guess
is converted from a String
to a u32
, as shown in Listing 2-5.
1 | //let guess: u32 = guess.trim().parse().expect("Please type a number!"); |
go over it line by line
Switch an expect
call to a match
expression to move from crashing on an error to handle the error.
The parse
returns a Result
type and Result
is an enum
that has the variants Ok
and Err
.
We use a match
expression here, same as the Ordering
result if the cmp
method.
- If
parse
is able to turn the string into a number, returnOk
containsresultant number
. The number will end up right where we want it in the newguess
variable we’re creating. - If not, it will return an
Err
value, we justcontinue
and return toloop
to ask for another guess.
Finally ,the program ignores all errors that parse
might encounter.
Common programming concepts
variables and mutability
1 | // fn main() { |