lecture 3 stuff

This commit is contained in:
SowinskiBraeden committed 2026-09-29 11:57:40 -07:00
1 parent d54c1aa04a
commit 6ab13bfafa
9 files changed
+400

No files matched your search

+29
View File
@@ -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();
}
+71
View File
@@ -0,0 +1,71 @@
// motivation for closures
fn sum<T: std::ops::AddAssign + Copy>(s: &[T]) -> T {
let mut total = s[0];
for i in 1..s.len() {
total += s[i];
}
total
}
fn find<T>(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<T, F>(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}");
}
*/
}
+31
View File
@@ -0,0 +1,31 @@
struct Pair<I> {
iter: I
}
impl<I> Pair<I> {
fn new(iter: I) -> Self {
Self {
iter
}
}
}
impl<I: Iterator> Iterator for Pair<I> {
type Item = (I::Item, I::Item);
fn next(&mut self) -> Option<Self::Item> {
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::<u8>() {
Ok(score) if score <= 100 => Some((c, score)),
_ => None,
}).collect();
println!("{h:?}");
}
+35
View File
@@ -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<Shape> = 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));
}
+39
View File
@@ -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<dyn Shape>]) -> f64 {
let mut total = 0.0;
for s in shapes {
total += s.area();
}
total
}
fn main() {
// let x = Box::new(42);
let v: Vec<Box<dyn Shape>> = 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));
}
+15
View File
@@ -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());
}
+62
View File
@@ -0,0 +1,62 @@
// ensure generic type T has AddAssign/Copy capabilities
fn sum<T: std::ops::AddAssign + Copy>(s: &[T]) -> T {
let mut total = s[0];
for i in 1..s.len() {
total += s[i];
}
total
}
fn find<T>(s: &[T], f: fn(&T) -> bool) -> Option<&T> {
for x in s {
if f(x) {
return Some(x);
}
}
None
}
fn find2<T, F>(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}");
}
}
+39
View File
@@ -0,0 +1,39 @@
// example to show how to implement an iterator
struct VecIntoIter {
v: Vec<i32>,
len: usize,
i: usize,
}
impl VecIntoIter {
fn new(v: Vec<i32>) -> VecIntoIter {
Self {
len: v.len(),
v,
i: 0
}
}
}
impl Iterator for VecIntoIter {
type Item = i32;
fn next(&mut self) -> Option<Self::Item> {
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
}
+79
View File
@@ -0,0 +1,79 @@
// example on how to implement iterators
struct VecIntoIter<T> {
v: Vec<T>,
len: usize,
i: usize,
}
impl<T> VecIntoIter<T> {
fn new(v: Vec<T>) -> Self {
Self {
len: v.len(),
v,
i: 0
}
}
}
struct VecIter<'a, T> {
v: &'a Vec<T>,
len: usize,
i: usize,
}
impl<'a, T> VecIter<'a, T> {
fn new(v: &'a Vec<T>) -> 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<Self::Item> {
if self.i >= self.len {
return None;
}
let n = self.i;
self.i += 1;
Some(&self.v[n])
}
}
impl<T: Copy> Iterator for VecIntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
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
}