🦀 Functional Rust
🎬 Error Handling in Rust Option, Result, the ? operator, and combinators.
📝 Text version (for readers / accessibility)

• Option represents a value that may or may not exist — Some(value) or None

• Result represents success (Ok) or failure (Err) — no exceptions needed

• The ? operator propagates errors up the call stack concisely

• Combinators like .map(), .and_then(), .unwrap_or() chain fallible operations

• The compiler forces you to handle every error case — no silent failures

📖 [View on hightechmind.io →](https://hightechmind.io/rust/005-reverse-list) ---

005-reverse-list — Reverse List

See [hightechmind.io/rust/005-reverse-list](https://hightechmind.io/rust/005-reverse-list) for the full explanation, OCaml comparison, and tests.

Quick Start

cargo test

Files

// 005: Reverse a List

// Approach 1: Built-in (in-place)
fn reverse_inplace(v: &mut Vec<i32>) {
    v.reverse();
}

// Approach 2: Iterator-based (new Vec)
fn reverse_iter(v: &[i32]) -> Vec<i32> {
    v.iter().rev().copied().collect()
}

// Approach 3: Fold-based (accumulator pattern)
fn reverse_fold(v: &[i32]) -> Vec<i32> {
    v.iter().fold(vec![], |mut acc, &x| {
        acc.insert(0, x);
        acc
    })
}

// Approach 3b: Recursive
fn reverse_recursive(v: &[i32]) -> Vec<i32> {
    if v.is_empty() {
        vec![]
    } else {
        let mut rest = reverse_recursive(&v[1..]);
        rest.push(v[0]);
        rest
    }
}

fn main() {
    let v = vec![1, 2, 3, 4, 5];
    println!("reverse_iter = {:?}", reverse_iter(&v));
    println!("reverse_fold = {:?}", reverse_fold(&v));
    let mut m = v.clone();
    reverse_inplace(&mut m);
    println!("reverse_inplace = {:?}", m);
}

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

    #[test]
    fn test_reverse_inplace() {
        let mut v = vec![1, 2, 3, 4, 5];
        reverse_inplace(&mut v);
        assert_eq!(v, vec![5, 4, 3, 2, 1]);
    }

    #[test]
    fn test_reverse_iter() {
        assert_eq!(reverse_iter(&[1, 2, 3, 4, 5]), vec![5, 4, 3, 2, 1]);
        assert_eq!(reverse_iter(&[]), Vec::<i32>::new());
    }

    #[test]
    fn test_reverse_fold() {
        assert_eq!(reverse_fold(&[1, 2, 3]), vec![3, 2, 1]);
    }

    #[test]
    fn test_reverse_recursive() {
        assert_eq!(reverse_recursive(&[1, 2, 3, 4, 5]), vec![5, 4, 3, 2, 1]);
        assert_eq!(reverse_recursive(&[42]), vec![42]);
        assert_eq!(reverse_recursive(&[]), Vec::<i32>::new());
    }
}
(* 005: Reverse a List *)

(* Approach 1: Built-in *)
let reverse_builtin lst = List.rev lst

(* Approach 2: Naive recursive — O(n^2) *)
let rec reverse_naive = function
  | [] -> []
  | x :: xs -> reverse_naive xs @ [x]

(* Approach 3: Tail-recursive with accumulator — O(n) *)
let reverse_acc lst =
  let rec aux acc = function
    | [] -> acc
    | x :: xs -> aux (x :: acc) xs
  in
  aux [] lst

(* Tests *)
let () =
  assert (reverse_builtin [1; 2; 3; 4; 5] = [5; 4; 3; 2; 1]);
  assert (reverse_builtin [] = []);
  assert (reverse_naive [1; 2; 3] = [3; 2; 1]);
  assert (reverse_acc [1; 2; 3; 4; 5] = [5; 4; 3; 2; 1]);
  assert (reverse_acc [] = []);
  assert (reverse_acc [42] = [42]);
  Printf.printf "✓ All tests passed\n"

📊 Detailed Comparison

Core Insight

Reversing a list reveals the importance of accumulator patterns. The naive approach (reverse tail, append head) creates O(n²) work. The tail-recursive approach (prepend to accumulator) achieves O(n).

OCaml Approach

  • `List.rev` — standard library, O(n)
  • Naive: `rev xs @ [x]` — O(n²)
  • Tail-recursive: accumulator pattern with `x :: acc`

Rust Approach

  • `.reverse()` — in-place mutation, O(n)
  • `.iter().rev().collect()` — creates new reversed Vec
  • Manual fold: `.fold(vec![], |acc, x| ...)`

Comparison Table

ApproachOCamlRust
Built-in`List.rev``.reverse()` / `.rev()`
Naive recursive`rev tail @ [head]``rec_reverse(&v[1..]).push(v[0])`
Tail-recursive`aux (x::acc) xs`loop with accumulator
Complexity (good)O(n)O(n)