rust-scicomp.github.io/rust-intro/

An introduction to Rust

Ignacia Fierro Piccardo & Matthew Scroggs

Plan for today

  1. Hello world
  2. Basic Rust syntax
    • variables
    • if, else
    • functions
    • loops
    • vectors
  3. Reasons to like Rust
An introduction to Rust (rust-scicomp.github.io/rust-intro)

Getting started

  • In terminal:
    • cargo init
    • cargo run
  • Can instead do cargo init --lib to initialise a library
An introduction to Rust (rust-scicomp.github.io/rust-intro)

Getting started

  • cargo init creates:
    • Cargo.toml
      • You can add dependencies to this file
    • src/main.rs with Hello World code in it
    • By default, it also initialises a git repo in your folder, creating .git/ and .gitignore
An introduction to Rust (rust-scicomp.github.io/rust-intro)

Basic syntax

An introduction to Rust (rust-scicomp.github.io/rust-intro)

Basic syntax #1: variables

let n = 5;
println!("n is {n}");
An introduction to Rust (rust-scicomp.github.io/rust-intro)

Basic syntax #1: variables

Note: all variables are constant by default. This will give a compiler error:

let n = 5;
n += 1;
println!("n is {n}");

Instead, you must use the mut keyword to make the variable mutable:

let mut n = 5;
n += 1;
println!("n is {n}");
An introduction to Rust (rust-scicomp.github.io/rust-intro)

Basic syntax #2: if, else

if sides == 1 {
    panic!("A polygon cannot have 1 side");
} else if sides == 2 {
    panic!("A polygon cannot have 2 sides");
} else {
    println!("Creating a polygon with {sides} sides")
}
  • No () around conditions (like Python)
  • {} around code blocks and ; at ends of lines (like C++)
  • Indentation is for style (unlike Python
An introduction to Rust (rust-scicomp.github.io/rust-intro)

Basic syntax #3: functions

You can do either:

fn one_more(n: i32) -> i32 {
    return n + 1;
}

Or:

fn one_more(n: i32) -> i32 {
    n + 1
}

When making a library, the keyword pub can be used before fn to define public functions.

An introduction to Rust (rust-scicomp.github.io/rust-intro)

Activity

Write a function that takes the number of sides as an input and returns the size
of an angle in a regular polygon with that number of sides.


Hint: f64 and f32 are the Rust types for 64 and 32 bit floats


Reminder: If a regular polygon has n sides, one of its internal angles (in degrees) is 180×(n - 2)/n.

An introduction to Rust (rust-scicomp.github.io/rust-intro)

Basic syntax #4: loops

  • while loop:
    while condition {
        println!("Print this");
    }
    
  • for loop:
    for n in 0..5 {
        println!("The next number is {n}")
    }
    
    
An introduction to Rust (rust-scicomp.github.io/rust-intro)

Basic syntax #4: loops

  • loop loops forever:
    loop {
        println!("Still going...");
    }
    
An introduction to Rust (rust-scicomp.github.io/rust-intro)

Basic syntax #5: Vec

  • A Vec is similar to a Python list. They can be created using vec!:
    let ten_zeros = vec![0.0; 10];
    println!("{ten_zeros:?}");
    let mut odds = vec![1, 3, 5, 7, 9];
    println!("{odds:?}");
    
  • [] can be used to get an item:
    println!("{}", odds[1]);
    
  • push adds an item to the end of a Vec:
    odds.push(11);
    println!("{odds:?}");
    
An introduction to Rust (rust-scicomp.github.io/rust-intro)

Basic syntax #5: Vec

  • Functions can return a Vec:
    fn f(number_of_zeros: usize) -> Vec<f64> {
        vec![0.0; number_of_zeros]
    }
    
An introduction to Rust (rust-scicomp.github.io/rust-intro)

Basic syntax #5: Maths functions

  • The f32 and f64 types support lots of common functions:
    let angle = 2.0;
    println!("{}", f64::sin(angle));
    println!("{}", angle.sin());
    
    println!("{}", f32::sqrt(2.0));
    println!("{}", f64::sqrt(2.0));
    
    println!("{}", std::f64::consts::PI);
    
An introduction to Rust (rust-scicomp.github.io/rust-intro)

Activity

Write a function that takes the number of sides as an input and output the coordinates
of the vertices of a regular polygon with that number of sides.


Hint: The coordinates of these vertices could be (cos(a),sin(a)) with a being equally spaced angles between 0 and 360 degrees (or 0 and 2π radians).

An introduction to Rust (rust-scicomp.github.io/rust-intro)

Reasons to like Rust

An introduction to Rust (rust-scicomp.github.io/rust-intro)

Reasons to like Rust #1: traits

A trait is use to define an abstract interface that could be implemented. For example:

/// Any polygon
trait Polygon {
    /// Number of vertices
    fn vertex_count(&self) -> int;

    /// The area of the polygon
    fn area(&self) -> f64;

    /// The perimeter of the polygon
    fn perimeter(&self) -> f64;
}

These traits can them be implemented for a struct

An introduction to Rust (rust-scicomp.github.io/rust-intro)

Reasons to like Rust #2: &impl Trait

Functions can use "any item that implements this trait" as an input type:

struct Prism {
}

fn make_prism(&impl Polygon) -> Prism {
    todo!();
}

This means your function can be used for objects in someone else's library as long as the other person has implemented your Polygon trait.

An introduction to Rust (rust-scicomp.github.io/rust-intro)

Reasons to like Rust #3: package management

Adding dependencies is easy (Cargo.toml):

[dependencies]
quadraturerules = "0.9.0"
itertools = "0.14.*"
rlst = { version = "0.6" }
mpi = { version = "0.8.0", optional = true }
serde = { version = "1", features = ["derive"], optional = true }

cargo publish can be used to make your crate available on crates.io.

An introduction to Rust (rust-scicomp.github.io/rust-intro)

Reasons to like Rust #4: enums can hold values

pub enum Transformation {
    /// An identity transformation
    Identity,
    /// A permutation
    Permutation(Vec<usize>),
}
An introduction to Rust (rust-scicomp.github.io/rust-intro)

Reasons to like Rust #5: break 'a

' can used to label a loop then tell break which loop to break.

'a: for i in 2..100 {
    for j in 2..100 {
        if i * j == 56 {
            println!("{i} {j}");
            break 'a;
        }
    }
}
An introduction to Rust (rust-scicomp.github.io/rust-intro)

Reasons to like Rust #6: Borrowing

Every item in Rust has an owner. If an item is passed into a function, the function takes ownership

let a = vec![0, 1];
function(a);

// This will cause a compiler error
println!("{:?}", a);
An introduction to Rust (rust-scicomp.github.io/rust-intro)

Reasons to like Rust #6: Borrowing

& can be used to "borrow" items to let a function use them without taking ownership:

let a = vec![0, 1];
function(&a);

// This will NOT cause a compiler error
println!("{:?}", a);

&mut can be used to let functions have a mutable borrow.

An introduction to Rust (rust-scicomp.github.io/rust-intro)

Reasons to like Rust #7: Memory safety

The compiler checks that at any time, any item has either:

  • one mutable borrow
  • one or more non-mutable borrow

This is an important part of how the compiler enforces memory safety.

An introduction to Rust (rust-scicomp.github.io/rust-intro)

Reasons to like Rust #8: cargo fmt and cargo clippy

  • Code formatting and linting out of the box
An introduction to Rust (rust-scicomp.github.io/rust-intro)

Reasons to like Rust #9: (Reasonably) simple Python wrapping

An introduction to Rust (rust-scicomp.github.io/rust-intro)

Where to learn more

An introduction to Rust (rust-scicomp.github.io/rust-intro)
An introduction to Rust (rust-scicomp.github.io/rust-intro)

Thanks for coming!

rust-scicomp.github.io/rust-intro

An introduction to Rust (rust-scicomp.github.io/rust-intro)