๐Ÿฆ€ Functional Rust
๐ŸŽฌ Rust Ownership in 30 seconds Visual walkthrough of ownership, moves, and automatic memory management.
๐Ÿ“ Text version (for readers / accessibility)

โ€ข Each value in Rust has exactly one owner โ€” when the owner goes out of scope, the value is dropped

โ€ข Assignment moves ownership by default; the original binding becomes invalid

โ€ข Borrowing (&T / &mut T) lets you reference data without taking ownership

โ€ข The compiler enforces: many shared references OR one mutable reference, never both

โ€ข No garbage collector needed โ€” memory is freed deterministically at scope exit

104: Borrowing Mutable

Difficulty: Intermediate Category: Ownership Concept: `&mut T`: exclusive mutable reference Key Insight: Only one &mut T at a time โ€” this prevents data races at compile time, a guarantee no other mainstream language offers
// 104: Mutable Borrowing โ€” &mut T
// Exclusive writer: only ONE &mut at a time

fn increment(x: &mut i32) {
    *x += 1;
}

fn push_doubled(v: &mut Vec<i32>, val: i32) {
    v.push(val * 2);
}

fn swap_first_last(v: &mut [i32]) {
    if v.len() >= 2 {
        let last_idx = v.len() - 1;
        v.swap(0, last_idx);
    }
}

// This won't compile โ€” demonstrates the rule:
// fn bad_example() {
//     let mut v = vec![1, 2, 3];
//     let r1 = &mut v;
//     let r2 = &mut v; // ERROR: second mutable borrow
//     r1.push(4);
//     r2.push(5);
// }

// Also can't mix &mut and &:
// fn bad_example2() {
//     let mut v = vec![1, 2, 3];
//     let r1 = &v;     // shared borrow
//     let r2 = &mut v; // ERROR: can't borrow as mutable
//     println!("{:?}", r1);
// }

fn main() {
    let mut x = 0;
    increment(&mut x);
    increment(&mut x);
    println!("x = {}", x);

    let mut v = vec![1, 2, 3];
    push_doubled(&mut v, 4);
    println!("v = {:?}", v);

    swap_first_last(&mut v);
    println!("swapped: {:?}", v);
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_increment() {
        let mut x = 0;
        increment(&mut x);
        increment(&mut x);
        assert_eq!(x, 2);
    }

    #[test]
    fn test_push_doubled() {
        let mut v = vec![1, 2];
        push_doubled(&mut v, 3);
        assert_eq!(v, vec![1, 2, 6]);
    }

    #[test]
    fn test_swap() {
        let mut v = vec![1, 2, 3, 4, 5];
        swap_first_last(&mut v);
        assert_eq!(v, vec![5, 2, 3, 4, 1]);
    }
}
(* 104: Mutable Borrowing *)
(* OCaml: mutable fields, but no borrow checker *)

(* Approach 1: Mutable ref *)
let increment r = r := !r + 1

let demo_mut () =
  let x = ref 0 in
  increment x;
  increment x;
  !x

(* Approach 2: Mutable array โ€” aliasing is possible! *)
let demo_alias () =
  let arr = [|1; 2; 3|] in
  let alias = arr in  (* same array! *)
  alias.(0) <- 99;
  arr.(0)  (* returns 99 โ€” aliased mutation! *)

(* In Rust, the borrow checker prevents this aliasing *)

(* Tests *)
let () =
  assert (demo_mut () = 2);
  assert (demo_alias () = 99);  (* OCaml allows this! *)
  Printf.printf "โœ“ All tests passed\n"

๐Ÿ“Š Detailed Comparison

Core Insight

Only one &mut T at a time โ€” this prevents data races at compile time, a guarantee no other mainstream language offers

OCaml Approach

  • See example.ml for implementation

Rust Approach

  • See example.rs for implementation

Comparison Table

FeatureOCamlRust
Seeexample.mlexample.rs