# Learn Rust in under 10 mins

## Introduction

How to increase your fluency in a programming language? You have to read a lot of it! Very lot. But how can you read a lot, when you lack the knowledge to understand what you read.

In this article, I try to cover as many keywords and symbols as possible using Rust snippets.


```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
``` 

A semicolon marks the end of a statement:

```rust
let x = 3;
let y = 5;
let z = y + x;
```

This means that statements can span over multiple lines:

```rust
let x = vec![1, 2, 3, 4, 5, 6, 7, 8]
    .iter()
    .map(|x| x + 3)
    .fold(0, |x, y| x + y);
```

`let` introduce a new set of variables into the current scope

```rust
let x;
x = 42;
```

You can write this as a single line:

```rust
let x = 42;
```

Variables in Rust are immutable by default, and require the `mut` keyword to be made mutable.

```rust
let mut x = 42
```

Types can be annotated

```rust
let x: i32;
x = 42;
```

And again, you can write this as a single line

```rust
let x: i32 = 42;
```

**When in doubt: Just use `i32` for everything! `i32` is the default in Rust**


You can declare a name and initialize it later but you can not access uninitialized variables

```rust
let x;
foobar(x); // error: borrow of possibly-uninitialized variable: `x`
x = 42;
```

Doing it this way is completely fine:

```rust
let x;
x = 42;
foobar(x);
```

The underscore `_` is a special symbol. It basically means that something is ignored:

```rust
// this does *nothing* because 42 is a constant
let _ = 42;

// this calls `get_thing` but throws away its result
let _ = get_thing();
```

Rust has tuples, which are a fixed-length collections of values of different types.

```rust
let pair = ('a', 17);
pair.0; // this is 'a'
pair.1; // this is 17
```

We could write, with explicit type annotation:

```rust
let pair: (char, i32) = ('a', 17);
```

Tuples can be destructured when doing an assignment:

```rust
let (some_char, some_int) = ('a', 17);
// now, `some_char` is 'a', and `some_int` is 17
```

This is very useful when a function returns a tuple:

```rust
let (left, right) = slice.split_at(middle);
```

You can use underscore `_`  to throw away a part of it:

```rust
let (_, right) = slice.split_at(middle);
```

To declare a function, you use `fn`.

Here is a void function:

```rust
fn greet() {
    println!("Hi there!");
}
```

And this is a function that returns a 32-bit signed integer. The arrow indicates its return type!

```rust
fn fair_dice_roll() -> i32 {
    4
}
```

Functions can be generic:

```rust
fn foobar<T>(arg: T) {
    // do something with `arg`
}
```

You can have multiple type parameters:

```rust
fn foobar<L, R>(left: L, right: R) {
    // do something with `left` and `right`
}
```

Bracket pairs do declare a block. A block has its own scope:

```rust
// This prints "in", then "out"
fn main() {
    let x = "out";
    {
        // this is a different `x`
        let x = "in";
        println!("{}", x);
    }
    println!("{}", x);
}
```

Keep in mind that Blocks are also expressions. This means they evaluate to a value.

```rust
// this:
let x = 42;

// is equivalent to this:
let x = { 42 };
```

There can be multiple statements inside a block:

```rust
let x = {
    let y = 1; // first statement
    let z = 2; // second statement
    y + z // this is the *tail* - what the whole block will evaluate to
};
```

When you omit the semicolon at the end of a function, it is the same as returning:

```rust
fn fair_dice_roll() -> i32 {
    return 4;
}

fn fair_dice_roll() -> i32 {
    4
}
```

`if` conditions are expressions too:

```rust
fn fair_dice_roll() -> i32 {
    if feeling_lucky {
        6
    } else {
        4
    }
}
```

And a `match` is also an expression and not a statement!

```rust
fn fair_dice_roll() -> i32 {
    match feeling_lucky {
        true => 6,
        false => 4,
    }
}
```

Dots `.` are used to access fields of a value:

```rust
let a = (10, 20);
a.0; // this is 10

let amos = get_some_struct();
amos.nickname; // this is "fasterthanlime"
```

Or to call a method on a value:

```rust
let nick = "fasterthanlime";
nick.len(); // this is 14
```

The double-colon, `::`, is similar, but it operates on namespaces.

In this example, std is a crate (~ a library), cmp is a module (~ a source file), and min is a function:

```rust
let least = std::cmp::min(3, 8); // this is 3
```

A Struct is declared with the struct keyword

```rust
struct Number {
    odd: bool,
    value: i32,
}
```

And they can be initialized using literals

```rust
let one = Number { odd: true, value: 1 };
let two = Number { odd: false, value: 2 };
```

You can declare methods on your own types:

```rust
impl Number {
    fn is_strictly_positive(self) -> bool {
        self.value > 0
    }
}
```

Structs can be generic too:

```rust
struct Pair<T> {
    a: T,
    b: T,
}

fn print_type_name<T>(_val: &T) {
    println!("{}", std::any::type_name::<T>());
}

fn main() {
    let p1 = Pair { a: 3, b: 9 };
    let p2 = Pair { a: true, b: false };
    print_type_name(&p1); // prints "Pair<i32>"
    print_type_name(&p2); // prints "Pair<bool>"
}
```

A vector is a container that stores the values like an array, but it has more advantages than an array data structure. A vector can increase it's size dynamically during runtime. 

It is provided by the standard library and is a generic. 

```rust
fn main() {
    let mut v1 = Vec::new();
    v1.push(1);
    let mut v2 = Vec::new();
    v2.push(false);
    print_type_name(&v1); // prints "Vec<i32>"
    print_type_name(&v2); // prints "Vec<bool>"
}
```

While we talked about Vectors, let's check the `vec!` macro:

```rust
fn main() {
    let v1 = vec![1, 2, 3];
    let v2 = vec![true, false, true];
    print_type_name(&v1); // prints "Vec<i32>"
    print_type_name(&v2); // prints "Vec<bool>"
}
```

All types of `name!()`, `name![]` or `name!{}` are invoking a macro. Macros just expand to regular code.

You already know a famous macro: `println!`

```rust
fn main() {
    println!("{}", "Hello there!");
}
```

This macro expands to:

```rust
fn main() {
    use std::io::{self, Write};
    io::stdout().lock().write_all(b"Hello there!\n").unwrap();
}
```

Rust provides a loop keyword to indicate an infinite loop. 

```rust
loop {
        count += 1;

        if count == 3 {
            println!("three");

            // Skip the rest of this iteration
            continue;
        }

        println!("{}", count);

        if count == 5 {
            println!("OK, that's enough");

            // Exit this loop
            break;
        }
    }
```

Or you can use the `while` loop. As the name stated, this loops runs while a condition is true.

```rust
fn main() {
    // A counter variable
    let mut n = 1;

    // Loop while `n` is less than 101
    while n < 101 {
        if n % 15 == 0 {
            println!("fizzbuzz");
        } else if n % 3 == 0 {
            println!("fizz");
        } else if n % 5 == 0 {
            println!("buzz");
        } else {
            println!("{}", n);
        }

        // Increment counter
        n += 1;
    }
}
```

Anything that is iterable can be used in a `for in` loop. One of the easiest ways to create an iterator is to use the range notation `a..b`. 

```rust
fn main() {
    // `n` will take the values: 1, 2, ..., 100 in each iteration
    for n in 1..101 {
        if n % 15 == 0 {
            println!("fizzbuzz");
        } else if n % 3 == 0 {
            println!("fizz");
        } else if n % 5 == 0 {
            println!("buzz");
        } else {
            println!("{}", n);
        }
    }
}
```

But `for in` it also works with a `Vec`:

```rust
fn main() {
    for i in vec![52, 49, 21] {
        println!("I like the number {}", i);
    }
}
```

Or a slice:

```rust
fn main() {
    for i in &[52, 49, 21] {
        println!("I like the number {}", i);
    }
}
```

Or an actual `iterator`:

```rust
fn main() {
    // note: `&str` also has a `.bytes()` iterator.
    // Rust's `char` type is a "Unicode scalar value"
    for c in "rust".chars() {
        println!("Give me a {}", c);
    }
}
```

You can catch the failure of some parts of your program instead of calling `panic!`. This can be done using the `Option` enum.

The `Option<T>` enum has two variants:

- `None`, to indicate failure or lack of value, and
- `Some(value)`, a tuple struct that wraps a value with type `T`.

```rust
enum Option<T> {
    None,
    Some(T),
}

impl<T> Option<T> {
    fn unwrap(self) -> T {
        // enums variants can be used in patterns:
        match self {
            Self::Some(t) => t,
            Self::None => panic!(".unwrap() called on a None option"),
        }
    }
}

use self::Option::{None, Some};

fn main() {
    let o1: Option<i32> = Some(128);
    o1.unwrap(); // this is fine

    let o2: Option<i32> = None;
    o2.unwrap(); // this panics!
}
```

Sometimes it is important to display why an operation failed. To do this you can use the `Result` enum.

The `Result<T, E>` enum has two variants:

- Ok(value) which indicates that the operation succeeded
- Err(why), which indicates that the operation failed, and wraps why, which explains the cause of the failure.

```rust
use std::fs::File;

fn main() {
    let greeting_file_result = File::open("hello.txt");

    let greeting_file = match greeting_file_result {
        Ok(file) => file,
        Err(error) => println!("Problem opening the file: {:?}", error),
    };
}
```

## Further reading

I hope, I could give a got overview about Rust in under 10 mins. Of course, this is just the beginning of a wonderful journey in the word of Rust. For more Rust material, check out the following links:

1. https://doc.rust-lang.org/rust-by-example/index.html
1. https://doc.rust-lang.org/book/title-page.html
1. https://runrust.miraheze.org/wiki/Main_Page
1. https://gist.github.com/rylev/f76b8e9567a722f1b157a69a4f98f1c1
1. https://learnxinyminutes.com/docs/rust/



