From 6ab13bfafa8471e8453387207e1c093f0a5bdd35 Mon Sep 17 00:00:00 2001 From: Braeden Sowinski Date: Tue, 29 Sep 2026 11:57:40 -0700 Subject: [PATCH] lecture 3 stuff --- lectures/03/closures.rs | 29 +++++++++++++++ lectures/03/find.rs | 71 ++++++++++++++++++++++++++++++++++++ lectures/03/pair.rs | 31 ++++++++++++++++ lectures/03/shapes.rs | 35 ++++++++++++++++++ lectures/03/shapes2.rs | 39 ++++++++++++++++++++ lectures/03/square.rs | 15 ++++++++ lectures/03/sum.rs | 62 ++++++++++++++++++++++++++++++++ lectures/03/veciter.rs | 39 ++++++++++++++++++++ lectures/03/veciter2.rs | 79 +++++++++++++++++++++++++++++++++++++++++ 9 files changed, 400 insertions(+) create mode 100644 lectures/03/closures.rs create mode 100644 lectures/03/find.rs create mode 100644 lectures/03/pair.rs create mode 100644 lectures/03/shapes.rs create mode 100644 lectures/03/shapes2.rs create mode 100644 lectures/03/square.rs create mode 100644 lectures/03/sum.rs create mode 100644 lectures/03/veciter.rs create mode 100644 lectures/03/veciter2.rs diff --git a/lectures/03/closures.rs b/lectures/03/closures.rs new file mode 100644 index 0000000..c024057 --- /dev/null +++ b/lectures/03/closures.rs @@ -0,0 +1,29 @@ +fn main() { + let v = vec![3, 2, 7, 6, 8]; + println!("{v:?}"); + let c = || { println!("{v:?}"); }; // Fn + println!("{v:?}"); + c(); + c(); + + let mut v = vec![3, 2, 7, 6, 8]; + println!("{v:?}"); + let mut c = |x| { v.push(x); }; // FnMut + // println!("{v:?}"); + c(1); + c(2); + println!("{v:?}"); + + let v = vec![3, 2, 7, 6, 8]; + let c = || { drop(v); }; // FnOnce + // println!("{v:?}"); + c(); + // c(); // ERROR + + let v = vec![3, 2, 7, 6, 8]; + let c = move || { println!("{v:?}"); }; // v moved in c; c is still Fn + // println!("{v:?}"); + c(); + c(); +} + diff --git a/lectures/03/find.rs b/lectures/03/find.rs new file mode 100644 index 0000000..e78191e --- /dev/null +++ b/lectures/03/find.rs @@ -0,0 +1,71 @@ +// motivation for closures +fn sum(s: &[T]) -> T { + let mut total = s[0]; + + for i in 1..s.len() { + total += s[i]; + } + + total +} + +fn find(s: &[T], f: fn(&T) -> bool) -> Option<&T> { // only works for functions f + for x in s { + if f(x) { + return Some(x); + } + } + None +} + +fn find2(s: &[T], f: F) -> Option<&T> // works for both functions & closures +where F: Fn(&T) -> bool { + for x in s { + if f(x) { + return Some(x); + } + } + None +} + +fn main() { + let v = vec![3, 2, 7, 6, 8]; + println!("{}", sum(&v)); + + let v = vec![3.1, 2.0, 7.3, 6.1, 8.0]; + println!("{}", sum(&v)); + + let v = vec![3, 2, 7, 6, 8]; + fn is_even(x: &i32) -> bool { + x % 2 == 0 + } + + if let Some(r) = find(&v, is_even) { + println!("{r}"); + } + + let divisor = 2; + /* + fn divisible(x: &i32) -> bool { + x % divisor == 0 // ERROR: can't capture divisor + } + */ + + // let divisible = |x: &i32| -> bool { x % divisor == 0 }; // closure; can capture environment + let divisible = |x: &i32| { x % divisor == 0 }; // closure; can capture environment + + /* + if let Some(r) = find(&v, divisible) { // ERROR: A closure is not regular fn + println!("{r}"); + } + */ + + if let Some(r) = find2(&v, divisible) { // OK + println!("{r}"); + } +/* + if let Some(r) = find2(&v, is_even) { // OK, also works for regular function + println!("{r}"); + } +*/ +} diff --git a/lectures/03/pair.rs b/lectures/03/pair.rs new file mode 100644 index 0000000..ef932b3 --- /dev/null +++ b/lectures/03/pair.rs @@ -0,0 +1,31 @@ +struct Pair { + iter: I +} + +impl Pair { + fn new(iter: I) -> Self { + Self { + iter + } + } +} + +impl Iterator for Pair { + type Item = (I::Item, I::Item); + + fn next(&mut self) -> Option { + Some((self.iter.next()?, self.iter.next()?)) + } +} + +use std::collections::HashMap; + +fn main() { + let v = vec!["homer", "25", "bart", "55", "monty", "101"]; + let h: HashMap<_, _> = Pair::new(v.into_iter()).filter_map(|(c, s)| + match s.parse::() { + Ok(score) if score <= 100 => Some((c, score)), + _ => None, + }).collect(); + println!("{h:?}"); +} diff --git a/lectures/03/shapes.rs b/lectures/03/shapes.rs new file mode 100644 index 0000000..4d7426e --- /dev/null +++ b/lectures/03/shapes.rs @@ -0,0 +1,35 @@ +// how can we store circles & rectangles in a container? +// solution 1: use an enum; static dispatch +#[derive(Clone, Copy)] +struct Point(f64, f64); + +// #[derive(Clone, Copy)] +enum Shape { + Circle(Point, f64), + Rectangle(Point, Point), +} + +fn area(s: &Shape) -> f64 { + match *s { + Shape::Circle(_p, r) => std::f64::consts::PI * r * r, + Shape::Rectangle(p1, p2) => ((p1.1 - p2.1) * (p1.0 - p2.0)).abs(), + } +} + +fn total_area(v: &[Shape]) -> f64 { + let mut total = 0.0; + + for s in v { + total += area(s); + } + total +} + +fn main() { + let v: Vec = vec![ + Shape::Circle(Point(0.0, 0.0), 1.0), + Shape::Rectangle(Point(1.0, 1.0), Point(2.0, 3.0)), + ]; + println!("{}", total_area(&v)); +} + diff --git a/lectures/03/shapes2.rs b/lectures/03/shapes2.rs new file mode 100644 index 0000000..611fa73 --- /dev/null +++ b/lectures/03/shapes2.rs @@ -0,0 +1,39 @@ +// how to put different shapes in a container? +// solution 2: use a trait object; late dispatch + +struct Point(f64, f64); +struct Circle(Point, f64); +struct Rectangle(Point, Point); + +trait Shape { + fn area(&self) -> f64; +} + +impl Shape for Circle { + fn area(&self) -> f64 { std::f64::consts::PI * self.1 * self.1 } +} + +impl Shape for Rectangle { + fn area(&self) -> f64 { ((self.1.0 - self.0.0) * (self.1.1 - self.0.1)).abs() } +} + +fn total_area(shapes: &[Box]) -> f64 { + let mut total = 0.0; + + for s in shapes { + total += s.area(); + } + total +} + +fn main() { + // let x = Box::new(42); + + let v: Vec> = vec![ + Box::new(Circle(Point(0.0, 0.0), 1.0)), + Box::new(Rectangle(Point(1.0, 1.0), Point(2.0, 3.0))), + ]; + + println!("{}", total_area(&v)); + println!("{}", total_area(&v)); +} diff --git a/lectures/03/square.rs b/lectures/03/square.rs new file mode 100644 index 0000000..a0d86ea --- /dev/null +++ b/lectures/03/square.rs @@ -0,0 +1,15 @@ +// simple example of extension trait +// how to add square method to i32 +trait Square { + fn square(self) -> Self; +} + +impl Square for i32 { + fn square(self) -> Self { + self * self + } +} + +fn main() { + println!("{}", 32.square()); +} diff --git a/lectures/03/sum.rs b/lectures/03/sum.rs new file mode 100644 index 0000000..454519a --- /dev/null +++ b/lectures/03/sum.rs @@ -0,0 +1,62 @@ +// ensure generic type T has AddAssign/Copy capabilities +fn sum(s: &[T]) -> T { + let mut total = s[0]; + + for i in 1..s.len() { + total += s[i]; + } + + total +} + +fn find(s: &[T], f: fn(&T) -> bool) -> Option<&T> { + for x in s { + if f(x) { + return Some(x); + } + } + None +} + +fn find2(s: &[T], f: F) -> Option<&T> +where + F: Fn(&T) -> bool, +{ + for x in s { + if f(x) { + return Some(x); + } + } + None +} + +fn main() { + let v = vec![3, 2, 6, 7, 8]; + println!("{}", sum(&v)); + + let v = vec![3.1, 2.0, 7.3, 6.1, 8.0]; + println!("{}", sum(&v)); + + let v = vec![3, 2, 7, 6, 8]; + fn is_even(x: &i32) -> bool { + x % 2 == 0 + } + + if let Some(r) = find(&v, is_even) { + println!("{r}"); + } + + let divisor = 2; // ERROR: can't capture divisor + /* + fn divisible(x: &i32) -> bool { + x % divisor == 0 + } + */ + + // closure; can capture environment + let divisible = |x: &i32| -> bool { x % divisor == 0 }; + + if let Some(r) = find2(&v, divisible) { + println!("{r}"); + } +} diff --git a/lectures/03/veciter.rs b/lectures/03/veciter.rs new file mode 100644 index 0000000..52ce1f0 --- /dev/null +++ b/lectures/03/veciter.rs @@ -0,0 +1,39 @@ +// example to show how to implement an iterator +struct VecIntoIter { + v: Vec, + len: usize, + i: usize, +} + +impl VecIntoIter { + fn new(v: Vec) -> VecIntoIter { + Self { + len: v.len(), + v, + i: 0 + } + } +} + +impl Iterator for VecIntoIter { + type Item = i32; + + fn next(&mut self) -> Option { + if self.i >= self.len { + return None; + } + let n = self.i; + self.i += 1; + Some(self.v[n]) + } +} + +fn main() { + let v = vec![1, 2, 3]; + let mut it = VecIntoIter::new(v); + + while let Some(x) = it.next() { + println!("{x}"); + } + // println!("{v:?}"); // v is consumed +} diff --git a/lectures/03/veciter2.rs b/lectures/03/veciter2.rs new file mode 100644 index 0000000..41c0472 --- /dev/null +++ b/lectures/03/veciter2.rs @@ -0,0 +1,79 @@ +// example on how to implement iterators +struct VecIntoIter { + v: Vec, + len: usize, + i: usize, +} + +impl VecIntoIter { + fn new(v: Vec) -> Self { + Self { + len: v.len(), + v, + i: 0 + } + } +} + +struct VecIter<'a, T> { + v: &'a Vec, + len: usize, + i: usize, +} + + +impl<'a, T> VecIter<'a, T> { + fn new(v: &'a Vec) -> Self { + Self { + len: v.len(), + v, + i: 0 + } + } +} + +impl<'a, T> Iterator for VecIter<'a, T> { + type Item = &'a T; + + fn next(&mut self) -> Option { + if self.i >= self.len { + return None; + } + let n = self.i; + self.i += 1; + Some(&self.v[n]) + } +} + + +impl Iterator for VecIntoIter { + type Item = T; + + fn next(&mut self) -> Option { + if self.i >= self.len { + return None; + } + let n = self.i; + self.i += 1; + Some(self.v[n]) + } +} + +fn main() { + let v = vec![1, 2, 3]; + + let mut it = VecIter::new(&v); + + while let Some(x) = it.next() { + println!("{x}"); + } + + println!("{v:?}"); + + let mut it = VecIntoIter::new(v); + + while let Some(x) = it.next() { + println!("{x}"); + } + // println!("{v:?}"); // v is consumed +}