Hello Cargo!

Instead of saving the result of the build in the same directory as our code, Cargo stores it in the target/debug directory.

CommandDesc
cargo newCreate a project
cargo buildBuild a project
cargo build --releaseBuild release ver
cargo runRun a project
cargo checkbuild a project without producing a binary to check for errors using cargo check

Common Programming Concepts

Variables And Mutability

Shadowing & Mutable

  • For same variable name, the former is shadowed by the latter

    fn main() {
        let x = 5;
        let x = x + 1;
        {
            let x = x * 2;
            println!("The value of x in the inner scope is: {x}");
        }
        println!("The value of x is: {x}"); // prints 6
    }
    
  • Shadowed variable can change its type

    fn main() {
        let spaces = "123123123";
        let spaces = spaces.len();  /* type changed */
        println!("{spaces}");
    }
    
  • For reassign the variable, you must use let keyword

    fn main() {
        let x = 5;
        x = x + 1;  // Error, no let keyword on reassign
    }
    
  • let allows type change, let mut disallows type changes

    fn main() {
        let mut spaces = "   ";
        spaces = spaces.len(); /* Error: Disallow type change for mutable */
    } 
    

Data Types

Rust is a statically typed **language, which means that it must know the types of all variables at compile time.

#![allow(unused)]
fn main() {
    /* type annotation (u32) is required */
    let guess: u32 = "42".parse().expect("Not a number!");
}

Rust has two data type subsets: scalar and compound

Scalar Types

  • Integer
  • Integer Literals
  • Floating-Point
  • Numeric
  • Boolean
  • Character
  • Tuple
  • Array

Functions

  • You can define function anywhere(Before/After) within the scope of the caller
  • Parameter type annotation is required
fn main() {
    print_labeled_measurement(5, 'h');
}

fn print_labeled_measurement(value: i32, unit_label: char) {
    println!("The measurement is: {value}{unit_label}");
}

// You can define function anywhere(Before/After) within the scope of the caller

Statements and Expressions

fn main() {
    let x = (let y = 6); // Error: Statement `let y = 6` do not have return value
}
  • Expressions do not include ending semicolons. If you add a semicolon to the end of an expression, you turn it into a statement, and it will then not return a value.
fn main() {
    let y = {
        let x = 3;
        x + 1     // Attention: No semicolon, means this is a expression 	
    };  // returns 4

    println!("The value of y is: {y}");
}

Function with Return Values

fn main() {
    let x = plus_one(5);

    println!("The value of x is: {x}");
}

fn plus_one(x: i32) -> i32 {
    x + 1  // Attention: no semicolon, express with return value
}

Control Flow

  • if Must have boolean type

    fn main() {
        let number = 12;
    
        if number % 4 == 0 {  // only boolean type
            println!("number is divisible by 4");
        } else if number % 3 == 0 {
            println!("number is divisible by 3");
        } else {
            println!("number is not divisible by 4, 3, or 2");
        }
    }
    
  • Use if in a let Statement, but the return values must in same type

    fn main() {
        let condition = true;
    
    		// Do not work because return values are not in same type
    		// let number = if condition { 5 } else { "six" };
        
    		let number = if condition { 5 } else { 6 };
    
        println!("The value of number is: {number}");
    }
    
  • Traditional loop

    fn main() {
        let mut counter = 0;
    
        let result = loop {
            /* loop in statement */
            counter += 1;
    
            if counter == 10 {
                break counter * 2;  /* send the break value as return value */
            }
        };
    
        println!("The result is {result}");
    }
    
  • While Loop

    fn main() {
        let mut number = 3;
    
        while number != 0 {
            println!("{number}!");
    
            number -= 1;
        }
    
        println!("LIFTOFF!!!");
    }
    
  • for...in loop

    fn main() {
        // 1..10  is a Range from 1 to 9
        // 1..=10 is a Range from 1 to 10 
        // (1..=10).rev() is a Range from 10 to 1 
        
        for number in 1..=10 {
            println!("{number}!");
        }
        println!("DONE!!!");
    }