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