Lecture 4 - Hello Rust!

Quick pulse check

  • Who got Rust installed?
  • Is anyone STILL having github authentication issues?
  • How were the discussions yesterday?
  • On gradescope / grade tracking and updates

How this feels is both normal and not normal

  • What's a SNAFU?

So what's going well?

Think-Pair-Share

  • Something you figured out after being frustrated
  • A time you were able to help someone else
  • An aha moment
  • That you keep showing up

Rust


Learning objectives

By the end of class today you should be able to:

  • Explain what a compiler and a compiled language is
  • Write a simple "hello world" Rust program wiht proper syntax (fn, brackets)
  • Use rustc and cargo to compile and run Rust programs
  • Decide when to use mutable or immutable variables in Rust

Rust in three concepts

  • Compiled
  • Type-safe
  • Memory-safe

What is a compiler?



What is a compiled langauge vs an interpreted one?



What is type-safety?



What is memory-safety?



Comparing to Python

R v P - Basic function writing

fn main() {
    println!("Hello, world!");
}

Key differences from Python:

  • fn keyword for functions (what was it for python?)
  • Braces {} for code blocks (...?)
  • Semicolons ; end statements (...?)
  • println! is a macro (the ! means macro) - more on this later

R v P - Variables, types, and mutability

fn main() {
    let x = 5;          // immutable by default
    let mut y = 10;     // mut makes it mutable
    y = 15;             // this works
    // x = 6;           // this would error!
    // y = "today"     // this would also error!
    
    println!("x is {}, y is {}", x, y);
}

Key differences from Python:

  • Python: everything mutable by default
  • Rust: immutable by default with unchangable types

R vs P Ownership and memory safety

import pandas as pd

def clean_data(df):
    df['score'] = df['score'] * 2  # Double all scores
    return df

# Original data
grades = pd.DataFrame({'name': ['Alice', 'Bob'], 'score': [85, 92]})
print("Original:", grades['score'].tolist())  # [85, 92]

# Clean the data
cleaned = clean_data(grades)
print("Cleaned:", cleaned['score'].tolist())   # [170, 184]

# Wait... what happened to our original data?
print("Original:", grades['score'].tolist())   # [170, 184] - Changed!

In Rust

#![allow(unused)]
fn main() {
// Option 1: Take ownership (original data moves, can't use it anymore)
fn clean_data_move(mut scores: Vec<i32>) -> Vec<i32> {
    for score in &mut scores {
        *score *= 2;
    }
    scores  // Returns modified data, original is gone
}

// Option 2: Borrow mutably (explicitly allows changes)
fn clean_data_borrow(scores: &mut Vec<i32>) {
    for score in scores {
        *score *= 2;
    }
    // Original data is modified, but you were explicit about it
}
}

Key differences from Python:

  • Python: unclear when a variable might be changed -> unexpected behavior
  • Rust: data moves are alwyas explicit

Compiling and running

Python: One Step (Interpreted)

python hello.py
  • Python reads your code line by line and executes it immediately
  • No separate compilation step needed

Rust: Two Steps (Compiled)

# Step 1: Compile (translate to machine code)
rustc hello.rs 

# Step 2: Run the executable
./hello
  • rustc is your compiler
  • rustc translates your entire program to machine code
  • Then you run the executable (why ./?)

Rust with Cargo (two-in-one)

# Set-up steps (one time)
cargo new my_project
cd my_project

# Build and run (compiles automatically)
cargo run
  • Cargo uses rustc under the hood

Activity

Activity 4 link

Some reminders before we look at solutions together

  • Pre-work for Friday
  • I have office hours today
  • Homework due Monday
  • Citing solutions vs breadcrumbs

Let's look at some solutions