https://asquera.de, https://ferrous-systems.com • Rust Programmer and Trainer: https://rust-experts.com • Mozillian • Previously 10 years of Ruby community work 3
y: i32 } fn print_point(p: &Point ) { println!("{:?}" , p) } Point implements Debug The println macro requires the printed value to implement Debug We pass Point as a concrete type 7
S: Debug { println!("{:?}", s) } The function is generic over a type variable S It takes a reference to a value of the type S S can be any type, as long as it implements Debug. This is called a trait bound. 9
{ x: 0, y: 0 }; let s = Square { x: 0, y: 0, width: 0 }; print::<Point>(&p); print::<Square>(&s); } Both functions are actually different and are created on use. A function logically existing and actually being compiled is two things. 11
E: Trait + OtherTrait { } In the where clase, T is an actual type Types can be constrained multiple times Read: ”for every type pair T and E, where T is Send + Sync and E is Send” 13
where F: FnOnce() -> T, { /*...*/ } pub fn spawn(f: &'a i32) -> JoinHandle<&'a i32> pub fn spawn(f: std::slice::Iter<'a, T>) -> JoinHandle<usize> This is the closure I’m cheating a little, this is the closure capture type The compiler checks all potential situations! 21
JoinHandle<T> where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static { //... } This is the closure Send is one of Rust concurrency guards ’static asks for the type to own all data This is not cheating! 22
} fn take_inner<I>(w: Wrapper<I>) -> I where I: Debug { w.inner } This is necessary because the type mandates item, it isn’t useful to the function 23
Self where I: Debug { Wrapper { inner: d } } pub fn inspect(&self) where I: Debug { println!("{:?}", self.inner); } } new ensures that Wrapper only ever can be constructed with Debug types 26
Find<PK, SelectFrom<R>> where R: Relation, Repos: Repository, Repos::Gateway: ExecuteOne<ReturnType, Self::Parameters>, Self: Query<QueryMarker=One, ReturnType=ReturnType> { type FutureType = <<Repos as Repository>::Gateway as ExecuteOne< Self::Parameters>>::Future; fn execute(&self, repos: &Repos) -> Self::FutureType where Repos: Stores<R> { ExecuteOne::execute_query(repos.gateway(), &self) } } These things don’t out of the blue and are frequently changed. 32
next: Loop = initial.transition(); let next: Loop = next.transition(); //next.terminate() //let next: Start = next.transition(); let next: End = next.transition(); next.terminate() } The setup is a little involved, but usage is straight-forward and safe! https://hoverbear.org/2016/10/12/rust-state-machine-pattern/ 39
Storage { fn query<Model>(&self, id: i64) -> Model where Self: Stores<Model> { //.... } } Forcing the implementor to further constrait what the database stores 41