A half-hour to learn Rust - fasterthanli.me

 
 
Jan 27, 2020 · 51 minute read · rust
In order to increase fluency in a programming language, one has to read a lot of it. But how can you read a lot of it if you don't know what it means?
In this article, instead of focusing on one or two concepts, I'll try to go through as many Rust snippets as I can, and explain what the keywords and symbols they contain mean.
Ready? Go!
 
let introduces a variable binding:
let x; // declare "x" x = 42; // assign 42 to "x"
 
This can also be written as a single line:
let x = 42;
 
You can specify the variable's type explicitly with :, that's a type annotation:
let x: i32; // `i32` is a signed 32-bit integer x = 42; // there's i8, i16, i32, i64, i128 // also u8, u16, u32, u64, u128 for unsigned
 
This can also be written as a single line:
let x: i32 = 42;
 
If you declare a name and initialize it later, the compiler will prevent you from using it before it's initialized.
let x; foobar(x); // error: borrow of possibly-uninitialized variable: `x` x = 42;
 
However, doing this is completely fine:
let x; x = 42; foobar(x); // the type of `x` will be inferred from here
 
The underscore _ is a special name - or rather, a "lack of name". It basically means to throw away something:
// this does *nothing* because 42 is a constant let _ = 42; // this calls `get_thing` but throws away its result let _ = get_thing();
 
Names that start with an underscore are regular names, it's just that the compiler won't warn about them being unused:
// we may use `_x` eventually, but our code is a work-in-progress // and we just wanted to get rid of a compiler warning for now. let _x = 42;
 
Separate bindings with the same name can be introduced - you can shadow a variable binding:
let x = 13; let x = x + 3; // using `x` after that line only refers to the second `x`, // the first `x` no longer exists.
 
Rust has tuples, which you can think of as "fixed-length collections of values of different types".
let pair = ('a', 17); pair.0; // this is 'a' pair.1; // this is 17
 
If we really we wanted to annotate the type of pair, we would write:
let pair: (char, i32) = ('a', 17);
 
Tuples can be destructured when doing an assignment, which means they're broken down into their individual fields:
let (some_char, some_int) = ('a', 17); // now, `some_char` is 'a', and `some_int` is 17
 
This is especially useful when a function returns a tuple:
let (left, right) = slice.split_at(middle);
 
Of course, when destructuring a tuple, _ can be used to throw away part of it:
let (_, right) = slice.split_at(middle);
 
The semi-colon marks the end of a statement:
let x = 3; let y = 5; let z = y + x;
 
Which means statements can span multiple lines:
let x = vec![1, 2, 3, 4, 5, 6, 7, 8] .iter() .map(|x| x + 3) .fold(0, |x, y| x + y);
 
(We'll go over what those actually mean later).
fn declares a function.
Here's a void function: