๐Ÿฆ€ 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

103: Borrowing Shared

Difficulty: Intermediate Category: Ownership Concept: `&T`: shared references (multiple readers) Key Insight: Shared borrows allow multiple simultaneous readers โ€” the compiler guarantees no one writes during shared access
// 103: Shared Borrowing โ€” &T
// Multiple readers, no writers

fn sum(data: &[i32]) -> i32 {
    data.iter().sum()
}

fn count(data: &[i32]) -> usize {
    data.len()
}

fn average(data: &[i32]) -> f64 {
    // Multiple shared borrows simultaneously โ€” perfectly safe
    let s = sum(data);   // &data borrow 1
    let c = count(data); // &data borrow 2 โ€” fine!
    s as f64 / c as f64
}

fn first_and_last(data: &[i32]) -> Option<(i32, i32)> {
    if data.is_empty() { None }
    else { Some((data[0], data[data.len() - 1])) }
}

// Multiple shared references can coexist
fn demonstrate_multiple_borrows() {
    let data = vec![1, 2, 3, 4, 5];
    let r1 = &data;
    let r2 = &data;
    let r3 = &data;
    // All three references valid simultaneously
    println!("r1={:?}, r2={:?}, r3={:?}", r1[0], r2[1], r3[2]);
}

fn main() {
    let data = vec![1, 2, 3, 4, 5];
    println!("average: {}", average(&data));
    println!("first_last: {:?}", first_and_last(&data));
    demonstrate_multiple_borrows();
}

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

    #[test]
    fn test_average() {
        assert!((average(&[1, 2, 3, 4, 5]) - 3.0).abs() < 0.001);
    }

    #[test]
    fn test_first_and_last() {
        assert_eq!(first_and_last(&[10, 20, 30]), Some((10, 30)));
        assert_eq!(first_and_last(&[]), None);
    }

    #[test]
    fn test_multiple_borrows() {
        let v = vec![1, 2, 3];
        let r1 = &v;
        let r2 = &v;
        assert_eq!(r1.len(), r2.len());
    }
}
(* 103: Shared Borrowing *)
(* OCaml: immutable by default, no borrow checker needed *)

(* Approach 1: Multiple "readers" โ€” always safe in OCaml *)
let sum_list lst = List.fold_left ( + ) 0 lst
let count_list lst = List.length lst

let multiple_readers () =
  let data = [1; 2; 3; 4; 5] in
  let s = sum_list data in      (* "borrow" 1 *)
  let c = count_list data in    (* "borrow" 2 โ€” no problem *)
  let avg = float_of_int s /. float_of_int c in
  avg

(* Approach 2: Passing by reference (mutable structures) *)
let read_array_twice arr =
  let first = arr.(0) in
  let last = arr.(Array.length arr - 1) in
  (first, last)

(* Tests *)
let () =
  assert (abs_float (multiple_readers () -. 3.0) < 0.001);
  assert (read_array_twice [|10; 20; 30|] = (10, 30));
  Printf.printf "โœ“ All tests passed\n"

๐Ÿ“Š Detailed Comparison

Core Insight

Shared borrows allow multiple simultaneous readers โ€” the compiler guarantees no one writes during shared access

OCaml Approach

  • See example.ml for implementation

Rust Approach

  • See example.rs for implementation

Comparison Table

FeatureOCamlRust
Seeexample.mlexample.rs