lecture 3 stuff
This commit is contained in:
9 files changed
+400
No files matched your search
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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}");
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -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:?}");
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
@@ -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}");
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in new issue
Block a user