Create a new project using cargo new execution-flow -- lib and open the project in an editor.
Basic conditionals such as ifstatements work just like in any other language, so let's start with those and replace the defaultmod tests { ... }statement in the file:
#[cfg(test)] mod tests { #[test] fn conditionals() { let i = 20; // Rust's if statement does not require parenthesis if i < 2 { assert!(i < 2); } else if i > 2 { assert!(i > 2); } else { assert_eq!(i, 2); } } }
Conditionals in Rust can do much more! Here is an additional test to show what they can do—add it before the last closing parenthesis:
#[test] fn more_conditionals() { let my_option = Some(10);
// If let statements can do simple pattern matching if let Some(unpacked) = my_option { assert_eq!(unpacked, 10); }
let mut other_option = Some(2); // there is also while let, which does the same thing while let Some(unpacked) = other_option {
// if can also return values in assignments other_option = if unpacked > 0 { Some(unpacked - 1) } else { None } } assert_eq!(other_option, None) }
A conditional isn't the only statement that can be used to change the flow of execution. There is, of course, also the loop and its variations. Let's add another test for those as well, starting with a few basics:
#[test] fn loops() {
let mut i = 42; let mut broke = false;
// a basic loop with control statements loop { i -= 1; if i < 2 { broke = true; break; } else if i > 2 { continue; } } assert!(broke);
// loops and other constructs can be named for better readability ... 'outer: loop { 'inner: loop { break 'inner; // ... and specifically jumped out of } break 'outer; }
Next, we will add more code to the test to see that loops are regular statements that can return values and that ranges can be used in for loops as well:
for v in vec![1, 1, 1, 1].iter() { assert_eq!(v, &1); } }
With these three tests prepared, let's run cargo test to see them working:
$ cargo test Compiling execution-flow v0.1.0 (Rust-Cookbook/Chapter01/execution-flow) warning: value assigned to `broke` is never read --> src/lib.rs:20:17 | 20 | let mut broke = false; | ^^^^^ | = note: #[warn(unused_assignments)] on by default = help: maybe it is overwritten before being read?
Finished dev [unoptimized + debuginfo] target(s) in 0.89s Running target/debug/deps/execution_flow-5a5ee2c7dd27585c
running 3 tests test tests::conditionals ... ok test tests::loops ... ok test tests::more_conditionals ... ok
test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Now, let's go behind the scenes to understand the code better.