Conversion Primitive types can be converted to each other through casting. Rust addresses conversion between custom types (i.e., struct and enum) by the use of traits. The generic conversions will use the From and Into traits. However there...
From and Into The From and Into traits are inherently linked, and this is actually part of its implementation. If you are able to convert type A from type B, then it should be easy to believe that we should be able to convert type B to type...
TryFrom and TryInto Similar to From and Into, TryFrom and TryInto are generic traits for converting between types. Unlike From/Into, the TryFrom/TryInto traits are used for fallible conversions, and as such, return Results. use std::convert...
To and from Strings Converting to String To convert any type to a String is as simple as implementing the ToString trait for the type. Rather than doing so directly, you should implement the fmt::Display trait which automatically provides T...
Expressions A Rust program is (mostly) made up of a series of statements: fn main() { // statement // statement // statement } There are a few kinds of statements in Rust. The most common two are declaring a variable binding, and using a ;...
Flow of Control An integral part of any programming language are ways to modify control flow: if/else, for, and others. Let's talk about them in Rust.
if/else Branching with if-else is similar to other languages. Unlike many of them, the boolean condition doesn't need to be surrounded by parentheses, and each condition is followed by a block. if-else conditionals are expressions, and, all...
loop Rust provides a loop keyword to indicate an infinite loop. The break statement can be used to exit a loop at anytime, whereas the continue statement can be used to skip the rest of the iteration and start a new one. fn main() { let mut...
Nesting and labels It's possible to break or continue outer loops when dealing with nested loops. In these cases, the loops must be annotated with some 'label, and the label must be passed to the break/continue statement. #![allow(unreachab...
Returning from loops One of the uses of a loop is to retry an operation until it succeeds. If the operation returns a value though, you might need to pass it to the rest of the code: put it after the break, and it will be returned by the lo...
while The while keyword can be used to run a loop while a condition is true. Let's write the infamous FizzBuzz using a while loop. fn main() { // A counter variable let mut n = 1; // Loop while `n` is less than 101 while n < 101 { if n % 15...
for loops for and range The for in construct can be used to iterate through an Iterator. One of the easiest ways to create an iterator is to use the range notation a..b. This yields values from a (inclusive) to b (exclusive) in steps of one...
match Rust provides pattern matching via the match keyword, which can be used like a C switch. The first matching arm is evaluated and all possible values must be covered. fn main() { let number = 13; // TODO ^ Try different values for `num...
Destructuring A match block can destructure items in a variety of ways. • Destructuring Tuples • Destructuring Arrays and Slices • Destructuring Enums • Destructuring Pointers • Destructuring Structures See also: The Rust Reference for Dest...
tuples Tuples can be destructured in a match as follows: fn main() { let triple = (0, -2, 3); // TODO ^ Try different values for `triple` println!("Tell me about {:?}", triple); // Match can be used to destructure a tuple match triple { //...
arrays/slices Like tuples, arrays and slices can be destructured this way: fn main() { // Try changing the values in the array, or make it a slice! let array = [1, -2, 6]; match array { // Binds the second and the third elements to the resp...
enums An enum is destructured similarly: // `allow` required to silence warnings because only // one variant is used. #[allow(dead_code)] enum Color { // These 3 are specified solely by their name. Red, Blue, Green, // These likewise tie `u...
pointers/ref For pointers, a distinction needs to be made between destructuring and dereferencing as they are different concepts which are used differently from languages like C/C++. • Dereferencing uses * • Destructuring uses &, ref, and r...
structs Similarly, a struct can be destructured as shown: fn main() { struct Foo { x: (u32, u32), y: u32, } // Try changing the values in the struct to see what happens let foo = Foo { x: (1, 2), y: 3 }; match foo { Foo { x: (1, b), y } =>...
Guards A match guard can be added to filter the arm. #[allow(dead_code)] enum Temperature { Celsius(i32), Fahrenheit(i32), } fn main() { let temperature = Temperature::Celsius(35); // ^ TODO try different values for `temperature` match temp...