IS 4010: Application Development with Artificial Intelligence

Week 09: Welcome to Rust

Brandon M. Greenwell

Session 1: why Rust?

Welcome to a new frontier

  • For the next few weeks, we are shifting from Python to our second language, Rust
  • Rust is a modern, compiled language focused on three primary goals: performance, reliability, and safety
  • It has a steeper learning curve than Python, but it supports high-performance, memory-efficient programs for domains such as systems programming, game development, and scientific computing
  • Created by Graydon Hoare at Mozilla Research in 2006, first stable release in 2015

Why Rust matters

Compiled and interpreted languages

  • Python is commonly executed by an interpreter and virtual machine. Its dynamic runtime makes experimentation convenient but adds overhead for some workloads
  • Rust is a compiled language. A compiler translates your entire program into machine code (the raw instructions the computer’s CPU understands) before you run it
  • This ahead-of-time compilation is a major reason for Rust’s high performance. It catches errors early and optimizes the code for speed
  • Bonus: Compiled Rust programs don’t need a runtime or interpreter installed to run

Meet cargo, your Rust build tool

  • cargo is Rust’s official build system and package manager, and it’s one of the language’s best features
  • It handles creating new projects, compiling your code, running your application, and managing external libraries (called “crates” in Rust)
  • Think of it as Python’s uv + pytest + formatter + type checker rolled into one tool!
  • Cargo provides one interface for the build, test, run, and dependency workflows used in this course

Essential Cargo commands

Project management: - cargo new project_name: creates a new “Hello, world!” project - cargo init: initialize Cargo in an existing directory

Building and running: - cargo build: compiles your code (debug mode) - cargo run: compiles and runs in one command - cargo build --release: optimized production build

Development workflow: - cargo check: fast compile check (no executable) - cargo test: run all tests - cargo clean: delete build artifacts

Cargo tools: Clippy and rustfmt

cargo clippy - your personal Rust mentor: - Catches common mistakes and suggests better approaches - Over 500 lints for code quality, performance, and style - Provides automated feedback based on established Rust lints - Example: “you can simplify this code” or “this might panic”

cargo fmt - automatic code formatting: - Formats your code to match Rust community style - No more debates about spacing, indentation, or style - Run before every commit - keeps code consistent - Like Python’s black formatter

Your Rust development workflow

Use this repeatable development loop:

  1. Write code in your editor
  2. cargo check - fast compilation check while coding
  3. cargo clippy - catch issues and learn better patterns
  4. cargo test - verify your code works correctly
  5. cargo fmt - format code before committing
  6. cargo run - try out your program

Practice: Use cargo check for quick compiler feedback, then run the full required checks before submitting.

Rust Playground: try before you install

  • Before installing anything, you can experiment with Rust in your browser at play.rust-lang.org
  • The Rust Playground lets you write, compile, and run Rust code instantly
  • Useful for testing small examples, sharing snippets, and learning syntax
  • Every code example in these slides has a clickable Playground link - try them all!
  • You’ll use the Playground extensively in this week’s practice exercises

Live demo: your first Rust code

Open: play.rust-lang.org

Follow along:

  1. Click “Run” - see “Hello, world!” in the output
  2. Edit the message - change it to your name
  3. Click “Run” again - see your personalized greeting!
  4. Click “Share” - get a permanent link to save your work

Challenge: Can you make it print TWO lines with different messages?

Hello, Rust

  • When you run cargo new hello_rust, it creates a simple project structure for you
  • The main source code lives in src/main.rs
  • The fn main() function is the entry point for a standard Rust binary
  • println! is a macro (not a function, note the !) that prints text to the console
// Inside src/main.rs
fn main() {
    println!("Hello, Rust!");
}

Try it yourself: ▶ Run in Rust Playground

Your turn: Modify the message and add a second println! line!

Session 2: Rust basics

Variables and mutability

  • We declare variables using the let keyword
  • A core concept in Rust is that variables are immutable by default. Once a value is bound to a name, you can’t change it. This helps us write safer code
  • To make a variable mutable, you must explicitly use the let mut keyword
  • This is the opposite of Python, where everything is mutable by default!
let x = 5;        // immutable
let mut y = 10;   // mutable
y = 15;           // this is allowed
// x = 6;         // this would cause a compiler error!

Try it yourself: ▶ Experiment in Playground

Challenge: Uncomment the x = 6; line. What error do you get? Read it carefully!

Scalar data types

  • Rust is a statically typed language, meaning the type of every variable must be known at compile time
  • It has four primary scalar (single value) types:
    • Integers: signed (i32, i64) or unsigned (u8, u32). The number is the bits of space it takes up. i32 is the default
    • Floating-point numbers: f32 (single-precision) and f64 (double-precision). f64 is the default
    • Booleans: bool with values true or false
    • Characters: char, for a single Unicode character, denoted with single quotes

Compound data types

  • Rust has two primary built-in compound types for grouping multiple values
  • The tuple is a fixed-size collection of values of different types. Once declared, a tuple’s size cannot change
  • The array is a fixed-size collection where every element must have the same type
  • For dynamic sizing, we’ll learn about Vectors and HashMaps later
// A tuple with different types
let my_tuple: (i32, f64, u8) = (500, 6.4, 1);

// An array with five elements of the same type
let my_array: [i32; 5] = [1, 2, 3, 4, 5];

Try it yourself: ▶ Run in Playground

Challenge: Try accessing my_tuple.0 and my_array[0]. What do you get?

Functions in Rust

  • We define functions using the fn keyword
  • You must declare the type of each function parameter
  • If the function returns a value, you must declare its type after an arrow ->
  • The final expression in a function is automatically returned; you don’t need the return keyword if it’s at the end
  • This is called an expression-based language - expressions return values, statements don’t
fn add(num1: i32, num2: i32) -> i32 {
    // No semicolon means this is an expression, and it's returned
    num1 + num2
}

Try it yourself: ▶ Run in Playground

Challenge: Add a semicolon after num1 + num2. What error appears? Why?

How do we know our code works?

  • In the Python section, we used the pytest library to run our tests
  • Rust includes a test harness integrated with Cargo
  • We can write tests for our code and run them from the command line using a simple, built-in command: cargo test
  • No need to install separate testing libraries - testing is first-class in Rust!

The anatomy of a Rust test

  • Tests are just functions marked with a #[test] attribute
  • By convention, they are placed in a special module named tests inside the same file as the code they are testing
  • The #[cfg(test)] attribute tells Rust to only compile and run this code when we execute cargo test
fn add_two(a: i32) -> i32 {
    a + 2
}

#[cfg(test)]
mod tests {
    use super::*; // Brings `add_two` into scope

    #[test]
    fn it_adds_two() {
        assert_eq!(add_two(2), 4);
    }
}

Assertion macros

  • How do we actually check if our code is correct inside a test? We use assertion macros
  • A test passes if the function completes without the macro “panicking” (crashing)
  • The most common macros are:

Our workflow for Rust labs

  • For the Rust labs, we will provide the test suite for you
  • Your workflow should be:
    1. Open the supplied Week 09 Cargo project and implement each todo!() in src/main.rs
    2. Do not modify the supplied test module
    3. Run cargo test, cargo fmt, and cargo clippy -- -D warnings
    4. Once all checks pass, commit week09/, push, and inspect the Week 09 badge
  • This gives you instant feedback without having to wait for the CI/CD pipeline
  • Green tests = you’re ready to submit!

Introducing Lab 09

  • This week’s lab is your first hands-on introduction to Rust
  • Install the Rust toolchain using rustup if it is not already installed
  • Open the supplied week09 Cargo project
  • Implement arithmetic, string, slice, and vector functions in src/main.rs
  • Run the required Cargo test, format, and lint commands
  • Full instructions are in week09/lab09.md
  • Don’t forget the Rust Playground exercises for extra practice!

Resources for learning Rust