From 6010b12653126274d7afcf7f0b7ede681027f3ac Mon Sep 17 00:00:00 2001
From: Rowan Torbitzky-Lane <rowan.a.tl@protonmail.com>
Date: Mon, 31 Mar 2025 09:43:16 -0500
Subject: [PATCH] almost done w/ ch13.01

---
 ch13/closures/Cargo.lock  |   7 ++
 ch13/closures/Cargo.toml  |   6 ++
 ch13/closures/src/lib.rs  |  14 +++
 ch13/closures/src/main.rs | 192 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 219 insertions(+)
 create mode 100644 ch13/closures/Cargo.lock
 create mode 100644 ch13/closures/Cargo.toml
 create mode 100644 ch13/closures/src/lib.rs
 create mode 100644 ch13/closures/src/main.rs

diff --git a/ch13/closures/Cargo.lock b/ch13/closures/Cargo.lock
new file mode 100644
index 0000000..adc103d
--- /dev/null
+++ b/ch13/closures/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "closures"
+version = "0.1.0"
diff --git a/ch13/closures/Cargo.toml b/ch13/closures/Cargo.toml
new file mode 100644
index 0000000..2cb7c6f
--- /dev/null
+++ b/ch13/closures/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "closures"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/ch13/closures/src/lib.rs b/ch13/closures/src/lib.rs
new file mode 100644
index 0000000..b93cf3f
--- /dev/null
+++ b/ch13/closures/src/lib.rs
@@ -0,0 +1,14 @@
+pub fn add(left: u64, right: u64) -> u64 {
+    left + right
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn it_works() {
+        let result = add(2, 2);
+        assert_eq!(result, 4);
+    }
+}
diff --git a/ch13/closures/src/main.rs b/ch13/closures/src/main.rs
new file mode 100644
index 0000000..0616cd7
--- /dev/null
+++ b/ch13/closures/src/main.rs
@@ -0,0 +1,192 @@
+// Closures are anonymous functions. Can save in variables or pass
+// to other functions. Closures can capture the values from the scope
+// they're defined in.
+
+use std::thread;
+use std::time::Duration;
+
+#[derive(Debug, PartialEq, Copy, Clone)]
+enum ShirtColor {
+    Red,
+    Blue,
+}
+
+struct Inventory {
+    shirts: Vec<ShirtColor>,
+}
+
+impl Inventory {
+    fn giveaway(&self, user_preference: Option<ShirtColor>) -> ShirtColor {
+        user_preference.unwrap_or_else(|| self.most_stocked())
+    }
+
+    fn most_stocked(&self) -> ShirtColor {
+        let mut num_red = 0;
+        let mut num_blue = 0;
+
+        for color in &self.shirts {
+            match color {
+                ShirtColor::Red => num_red += 1,
+                ShirtColor::Blue => num_blue += 1,
+            }
+        }
+
+        if num_red > num_blue {
+            ShirtColor::Red
+        } else {
+            ShirtColor::Blue
+        }
+    }
+}
+
+#[derive(Debug)]
+struct Rectangle {
+    width: u32,
+    height: u32,
+}
+
+fn main() {
+    let store = Inventory {
+        shirts: vec![ShirtColor::Blue, ShirtColor::Red, ShirtColor::Blue],
+    };
+
+    let user_pref1 = Some(ShirtColor::Red);
+    let giveaway1 = store.giveaway(user_pref1);
+    println!(
+        "The user with preference {:?} gets {:?}",
+        user_pref1, giveaway1
+    );
+
+    let user_pref2 = None;
+    let giveaway2 = store.giveaway(user_pref2);
+    println!(
+        "The user with preference {:?} gets {:?}",
+        user_pref2, giveaway2
+    );
+
+    // closure type inference and annotation
+    let expensive_closure = |num: u32| -> u32 {
+        println!("calculating slowly...");
+        thread::sleep(Duration::from_secs(2));
+        num
+    };
+
+    // similarity between closures and functions
+    fn add_one_v1(x: u32) -> u32 {
+        x + 1
+    }
+    let add_one_v2 = |x: u32| -> u32 { x + 1 };
+
+    // capturing references or moving ownership
+    // closures capture values from env in 3 ways
+    // 1) borrowing immutably
+    // 2) borrowing mutably
+    // 3) taking ownership
+    let list = vec![1, 2, 3];
+    println!("Before defining closure: {list:?}");
+
+    let only_borrows = || println!("From closure: {list:?}");
+
+    println!("Before calling closure: {list:?}");
+    only_borrows();
+    println!("After calling closure: {list:?}");
+
+    // change closure body to push instead of print
+    let mut list = vec![1, 2, 3, 4];
+    println!("Before defining closure: {list:?}");
+
+    let mut borrows_mutably = || list.push(7);
+
+    // println!("Before calling closure: {list:?}");
+    borrows_mutably();
+    println!("After calling closure: {list:?}");
+
+    // If want to force closure to take ownership of values it uses even
+    // tho closure doesn't strictly need ownership, use the `move` keyword
+    let list = vec![1, 2, 3];
+    println!("Before defining closure: {list:?}");
+
+    thread::spawn(move || println!("From thread: {list:?}"))
+        .join()
+        .unwrap();
+
+    // Moving captured values out of the closures and the Fn traits
+    // Once a closure has captured a reference or captured ownership of a value
+    // from the env where closure is defined (affecting what is moved into the
+    // closure), the code in the body of the closure defines what happens to
+    // the references or values when the closure is evaluated later (affecting
+    // what is moved out of the closure). Closure body can do any of the following:
+    // 1) move captured value out of the closure
+    // 2) mutate captured value
+    // 3) neither move nor mutate the value
+    // 4) capture nothing from the env to begin with
+    //
+    // Closures will automatically implement some or all of the following
+    // traits in an additive fashing depending on the closure's body
+    // handles the values
+    // 1) FnOnce applies to all closures that can be called once.
+    //    All closures implement at least this trait. A closure that
+    //    moves captured values out of its body will only implement
+    //    FnOnce and one of the other Fn traits, because it can only
+    //    by called once.
+    // 2) FnMut applies to closures that don't move captured values out
+    //    of their body but might mutate the captured values. These
+    //    closures can't be called more than once.
+    // 3) Fn applies to closures that don't move captured values out of
+    //    their body and that don't mutate captured values, and closures
+    //    that capture nothing from their environment. These closures can
+    //    be called more than once without mutating their environment. This
+    //    is nice for calling a closure multiple times concurrently.
+
+    // sort_by_key uses FnMut
+    let mut list = [
+        Rectangle {
+            width: 10,
+            height: 1,
+        },
+        Rectangle {
+            width: 3,
+            height: 5,
+        },
+        Rectangle {
+            width: 7,
+            height: 12,
+        },
+    ];
+
+    // let mut sort_operations = vec![];
+    // let value = String::from("closure called");
+    let mut num_sort_operations = 0;
+
+    // list.sort_by_key(|r| r.width);
+    list.sort_by_key(|r| {
+        // sort_operations.push(value);
+        num_sort_operations += 1;
+        r.width
+    });
+    println!("{list:#?}");
+
+    // closures must name captured lifetimes
+
+    // Stopped here:
+    // https://rust-book.cs.brown.edu/ch13-01-closures.html#closures-must-name-captured-lifetimes
+}
+
+// from closures must name captured lifetimes
+fn make_a_cloner(s_ref: &str) -> impl Fn() -> String {
+    move || s_ref.to_string()
+}
+
+// The implementation for unwrap_or_else
+// Uses FnOnce
+// impl<T> Option<T> {
+//     pub fn unwrap_or_else<F>(self, f: F) -> T
+//     where
+//         F: FnOnce() -> T,
+//     {
+//         match self {
+//             Some(x) => x,
+//             None => f(),
+//         }
+//     }
+// }