Table of contents
3.2 Use esle if to handle multiple conditions
3.4 Repeat execution using loops
Use loop to execute code repeatedly
Loop labels: disambiguating between multiple loops
Use for to iterate through a collection
1. Function
functions are very common in Rust code. You've already seen one of the most important functions in a language: the main
function, which is the entry point for many programs. You've also seen the fn
keyword, which is used to declare new functions.
Function and variable names in Rust code use snake case standard style, that is, snake-shaped naming convention, which is the same as python language . In the snake case, all letters are lowercase and underscores are used to separate words. Here is a program with an example function definition:
An example looks like this:
fn hello_world() {
println!("hello world !")
}
fn main() {
println!("main ......");
hello_world()
}
Note, hello_world function is defined after
main
function ; It can also be defined before . Rust doesn't care where the function is defined, as long as the function is called within a scope that is visible to the caller. It is a static language and unlike other dynamic languages (JavaScript), it is executed from top to bottom, so the corresponding function will not be found.
We can use the above method to see the results, as shown below:
parameter
We can define it as having parameters (parameters) For functions, parameters are special variables that are part of the function signature. When a function has parameters (formal parameters), it can provide specific values (actual parameters) for those parameters. Technically, these specific values are called arguments (arguments).
In the hello_world function above, we added a parameter:
fn hello_world(p: i64) {
println!("hello world {p}!")
}
fn main() {
println!("main ......");
hello_world(1024)
}
Running the above program, the results are as follows:
In a function signature,must declare the type of each parameter. This was a carefully considered decision in the design of Rust: requiring that type specifications be provided in function definitions means that the compiler no longer needs you to indicate your intent by annotating types elsewhere in your code. Also, knowing what types a function requires, the compiler can give more useful error messages.
When defining multiple parameters, separate them with commas, like this:
fn hello_world(c: &str,p: i64,) {
println!("hello world {c} {p}!")
}
fn main() {
println!("main ......");
hello_world("程序员的", 1024)
}
Run the code as shown below:
statements and expressions
The function body consists of a series of statements and an optional ending expression. So far, the functions we've mentioned don't contain trailing expressions, but you've seen expressions as part of statements. Because Rust is an expression-based language, this is an important distinction to understand (from other languages). Other languages don't make this distinction, so let's look at how statements differ from expressions and how these differences affect function bodies.
Statements (Statements) are instructions that perform some operations but do not return a value. Expressions (Expressions) evaluates and produces a value. Let's look at some examples.
fn main() {
let x = 12345;
println!("========={x}========");
}
let x = 12345; This is a statement. The 12345 after the equal sign is an expression.
function with return value
The function can return a value to the code that calls it. We don't name the return value, but declare its type after the arrow (->
). In Rust, the return value of a function is equal to the value of the last expression in the function body. Using the return
keyword and specifying a value, you can return early from the function; but most functions implicitly return the last expression.
Here is an example of a function that returns a value:
fn main() {
let y = y();
println!("数字是:{y}")
}
fn y() -> i32 {
12345
}
Run the above code as shown below:
The y function has no parameters and defines a return value type, but the function body only has a single 12345 and no semicolon, because this is An expression whose value we want to return. If you add a semicolon, it is a statement, and an error will be reported.
fn main() {
let y = y();
println!("数字是:{y}")
}
fn y() -> i32 {
12345;
}
Running the above code will report the following error:
The main error message, "mismatched types", reveals the core problem with the code. The definition of function y indicates that it should return a value of type i32
, but the statement does not return a value. Use < /span> ()
means no value is returned. An error occurs because not returning a value conflicts with the function definition. In the output, Rust provides a message that might help correct the error: it suggests removing the semicolon, which will fix the error.
2. Comments
All programmers strive to make their code easy to understand, but sometimes additional explanation is needed. In this case, the programmer leaves comments(comments), the compiler will ignore them, but people reading the code may find them useful.
Here's a simple annotation:
// 返回一个数字
fn y() -> i32 {
12345
}
Documentation comments
Rust also has a specific type of comments for documentation, often called Documentation comments ( documentation comments), which generate HTML documentation. This HTML displays the contents of public API documentation comments, which are intended to allow programmers interested in the library to understand how to be used.
Here is an example:
/// 返回一个数字(i32)
/// 参数:p 类型i32
/// message:......
/// 这是一个返回一个数字的函数
///
fn y(p:i32) -> i32 {
p
}
Multi-line comments
Like other languages, you can also write multi-line comments, as shown below:
/**
* 这是一个返回整数的方法
* params: p(i32)
* return: i32
*/
fn y(p:i32) -> i32 {
p
}
3. Control flow
3.1 if expression
if
Expressions allow different branches of code to be executed based on conditions. You provide a condition and say "If the condition is met, run this code; if the condition is not met, don't run this code."
Here is an example:
fn main() {
let y = 1234;
if y > 1024 {
println!("满足条件!")
} else {
println!("不满足条件!")
}
}
It is worthnoting that the conditions in the code must Is bool
value. If the condition is not a bool
value, we will get an error. For example, try running the following code:
fn main() {
let y = 1234;
if y {
println!("满足条件!")
} else {
println!("不满足条件!")
}
}
This error indicates that Rust expected an bool
but got an integer instead. As a static language, Rust does not undergo dynamic conversion like the JavaScript language.
3.2 Use esle if to handle multiple conditions
You can use if and else if to handle multiple conditions. The following is an example:
fn main() {
let y = 1234;
if y > 1000 {
println!("大于1000!")
} else if y > 100 {
println!("大于100!")
} else if y > 10 {
println!("大于10!")
} else {
println!("小于于10!")
}
}
3.3 Using if in let statement
Because if
is an expression, we can use it on the right side of the let
statement, here is an example:
fn main() {
let y = true;
let res = if y {0} else {1};
println!("res: {res}")
}
if
The possible return values of each branch must be of the same type, otherwise an error will be reported. Change the code as follows:
fn main() {
let y = true;
let res = if y {0} else {false};
println!("res: {res}")
}
3.4 Repeat execution using loops
Rust has three kinds of circulation:loop
, while
和 for
.
Use loop to execute code repeatedly
loop
The keyword tells Rust to execute a block of code over and over again until you explicitly ask it to stop.
fn main() {
loop {
println!("res:")
}
}
When running this program, we will see continuous and repeated printing again!
until we manually stop the program. Most terminals support a shortcut key, ctrl-c, to terminate a program that is stuck in an infinite loop.
Return value from loop
Through the loop loop, we can interrupt the loop through the break statement and return the result. An example is as follows:
fn main() {
let mut i = 0;
let res = loop {
i += 1;
if i == 5 {
break i * i;
}
};
println!("res: {res}")
}
Loop labels: disambiguating between multiple loops
If there are nested loops, break
and continue
apply to the innermost loop at that time. You can optionally specify a loop label on a loop (loop label ), then use the tags with break
or continue
so that these keywords apply to the marked loop instead of the innermost loop.
Here is an example:
fn main() {
let mut i = 0;
'first: loop {
i += 1;
loop {
if i % 2 == 0 {
i += 1;
break 'first;
} else {
break;
}
}
}
println!("res: {i}")
}
The variable variable i=0 defined first; when entering the first loop, i+1, the result of i is 1. When entering the second loop, it is judged whether the remainder of i to 2 is equal to 0. If the result is not equal, enter the else statement block. , a break statement appears in the else statement block, jumps out of the current loop, and enters the position of i += 1. At this time, i is equal to 2, and then enters the second loop again. The remainder of i to 2 is equal to 0, and the result of i is equal to 0. Add 1 operation, at this time i is equal to 3, then jump to the position of the label loop, and then execute the print result: "res: 3".
while conditional loop
It is also very common to calculate the conditions of loops in programs. When the condition is true
, execute the loop. When the condition is no longer true
, call break
to stop the loop. This loop type can be achieved by combining loop
, if
, else
and break
; a>
Here is an example:
fn main() {
let mut i = 0;
while i < 10 {
i += 1;
println!("res: {i}")
}
}
Use for to iterate through a collection
for
The safety and simplicity of loops make them the most used loop construct in Rust.
The following is an example of using a for
loop:
fn main() {
let numbers = [10, 20, 30, 40, 50];
for i in numbers {
println!("{i}")
}
}