Loading rust_06_organisation...
#[derive(Debug, Clone)] struct Point { x: i32, y: i32, }
fn main() { let p1 = Point { x: 20, y: 50 }; // initialise a struct, with its members let mut p2 = p1.clone(); // this struct implements Clone p2.x += 1; // access individual members ... p2.y -= 1; // ... of this structure println!("p1={:?} p2={:?}", p1, p2); // this struct implements Debug } /* p1=Point { x: 20, y: 50 } p2=Point { x: 21, y: 49 } */
/// A type to filter some values as the average of the last samples. #[derive(Debug, Clone)] struct RollingMean { samples: Vec<f64>, next: usize, }
impl RollingMean { /// Makes a new RollingMean with an average of count samples. fn new(count: usize) -> Self { Self { samples: vec![0.0; count], next: 0, } }
/// Returns the number of samples used by the RollingMean. fn count(&self) -> usize { self.samples.len() }
/// Returns the average of the last samples fn mean(&self) -> f64 { let count = self.count() as f64; self.samples.iter().sum::<f64>() / count }
/// Stores a new sample, getting rid of the oldest one. fn sample( &mut self, value: f64, ) { self.samples[self.next] = value; self.next = (self.next + 1) % self.count(); }
/// Transforms the RollingMean into the vector it contains. fn into_vec(self) -> Vec<f64> { self.samples } }
fn main() { let mut rm = RollingMean::new(4); for i in 3..=9 { let value = (i / 3) as f64; rm.sample(value); let mean = rm.mean(); println!("{:.3} ~~> {:.3} {:?}", value, mean, rm); } let samples = rm.into_vec(); println!("samples={:?}", samples); } /* 1.000 ~~> 0.250 RollingMean { samples: [1.0, 0.0, 0.0, 0.0], next: 1 } 1.000 ~~> 0.500 RollingMean { samples: [1.0, 1.0, 0.0, 0.0], next: 2 } 1.000 ~~> 0.750 RollingMean { samples: [1.0, 1.0, 1.0, 0.0], next: 3 } 2.000 ~~> 1.250 RollingMean { samples: [1.0, 1.0, 1.0, 2.0], next: 0 } 2.000 ~~> 1.500 RollingMean { samples: [2.0, 1.0, 1.0, 2.0], next: 1 } 2.000 ~~> 1.750 RollingMean { samples: [2.0, 2.0, 1.0, 2.0], next: 2 } 3.000 ~~> 2.250 RollingMean { samples: [2.0, 2.0, 3.0, 2.0], next: 3 } samples=[2.0, 2.0, 3.0, 2.0] */
&selfest l'équivalent de
self: &Self, il indique que cette fonction va consulter la valeur indiquée,
&mut selfest l'équivalent de
self: &mut Self, il indique que cette fonction va modifier la valeur indiquée,
selfest l'équivalent de
self: Self, il indique que cette fonction va consommer la valeur transmise.
selfreprésentent ce que nous plaçons avant le point et le nom de la fonction lorsque nous l'invoquons.
rm.count()ou
rm.mean()sont automatiquement comprises comme
(&rm).count()ou
(&rm).mean()afin de prendre une référence partagée (non-mutable) vers la valeur rm,
rm.sample(value)est automatiquement comprise comme
(&mut rm).sample(value)afin de prendre une référence exclusive (mutable) vers la valeur rm,
rm.into_vec()est comprise comme telle afin de déplacer rm.
rustup doc --book“5.1. Defining and Instantiating Structs”
rustup doc --book“5.3. Method Syntax”
rustup doc --rust-by-example“3.1. Structures”
rustup doc --rust-by-example“9.1. Methods”
rustup doc --std 'struct',
rustup doc --std 'impl'
rustup doc --reference“6.6. Structs”
rustup doc --reference“6.12. Implementations, Inherent Implementations”
#[derive(Debug, Clone)] enum Clothing { Scarf, Socks(f32), Trousers { length: i32, size: i32 }, }
fn main() { for cl in [ Clothing::Scarf, Clothing::Socks(7.5), Clothing::Trousers { length: 32, size: 28, }, ] { println!("{:?}", cl); match &cl { Clothing::Scarf => { println!("~~> a scarf, unisize"); } Clothing::Socks(size) => { println!("~~> a pair of socks, size {}", size); } Clothing::Trousers { length: l, size: s } => { println!("~~> a pair of trousers, length {}, size {}", l, s); } } } } /* Scarf ~~> a scarf, unisize Socks(7.5) ~~> a pair of socks, size 7.5 Trousers { length: 32, size: 28 } ~~> a pair of trousers, length 32, size 28 */
/// A 2D point. #[derive(Debug, Clone)] struct Point { x: i32, y: i32, }
/// A 2D shape. #[derive(Debug, Clone)] enum Shape { Empty, Point(Point), Box { corner: Point, width: i32, height: i32, }, }
impl Shape { /// Creates a shape depending upon the available arguments. fn new( point: Option<Point>, size: Option<(i32, i32)>, ) -> Self { if let Some(point) = point { if let Some((w, h)) = size { Self::Box { corner: point, width: w, height: h, } } else { Self::Point(point) } } else { Self::Empty } }
/// Tells if the shape overlaps with the provided point. fn contains_point( &self, point: &Point, ) -> bool { match self { Self::Empty => false, Self::Point(p) => point.x == p.x && point.y == p.y, Self::Box { corner: c, width: w, height: h, } => { point.x >= c.x && point.x <= c.x + w && point.y >= c.y && point.y <= c.y + h } } } }
fn main() { for sh in [ Shape::new(None, None), Shape::new(Some(Point { x: 20, y: 10 }), None), Shape::new(Some(Point { x: 30, y: 10 }), Some((40, 20))), ] { println!("{:?}", sh); for i in 1..3 { let p = Point { x: 20 * i, y: 10 * i, }; if sh.contains_point(&p) { println!(" ~~> contains {:?}", p); } } } } /* Empty Point(Point { x: 20, y: 10 }) ~~> contains Point { x: 20, y: 10 } Box { corner: Point { x: 30, y: 10 }, width: 40, height: 20 } ~~> contains Point { x: 40, y: 20 } */
rustup doc --book“6. Enums and Pattern Matching”
rustup doc --rust-by-example“3.2. Enums”
rustup doc --std 'enum'
rustup doc --reference“6.7. Enumerations”
src ├── main.rs ├── lib.rs ├── person.rs ├── enib.rs └── enib ├── elec.rs ├── info.rs └── meca.rs
// this applications makes use of the « my_project » crate use my_project::{enib, person};
fn main() { // refer to some functions from various modules person::presentation("Maccione", "Aldo"); enib::presentation(); } /* Ciao, mi chiamo Aldo Maccione ENIB • Electronics Department at ENIB • Computer Science Department at ENIB • Mechatronics Department at ENIB */
// root of the « my_project » crate pub mod enib; // tell the compiler that ... pub mod person; // ... these two modules exist
pub fn presentation( name: &str, first_name: &str, ) { println!("Ciao, mi chiamo {} {}", first_name, name); }
pub mod elec; // tell the compiler that ... pub mod info; // ... these three ... pub mod meca; // ... submodules exist
pub fn presentation() { println!("{}", school_name()); // all of these ... println!("• {}", elec::dept_name()); // ... function names ... println!("• {}", info::dept_name()); // ... are relative to ... println!("• {}", meca::dept_name()); // ... the current module }
pub fn school_name() -> String { "ENIB".to_owned() }
pub fn dept_name() -> String { // explicitly name the function in the upper module (super keyword) format!("Electronics Department at {}", super::school_name()) }
// make this name implicit within this context, ... // ... starting from the upper module (super keyword) use super::school_name;
pub fn dept_name() -> String { format!("Computer Science Department at {}", school_name()) }
// make this name implicit within this context, ... // ... starting from the root module (crate keyword) use crate::enib::school_name;
pub fn dept_name() -> String { format!("Mechatronics Department at {}", school_name()); }
rustup doc --book“7.2. Defining Modules to Control Scope and Privacy”
rustup doc --book“7.3. Paths for Referring to an Item in the Module Tree”
rustup doc --book“7.4. Bringing Paths Into Scope with the use Keyword”
rustup doc --book“7.5. Separating Modules into Different Files”
rustup doc --rust-by-example“10.3. The use declaration”
rustup doc --rust-by-example“10.4. super and self”
rustup doc --rust-by-example“10.5. File hierarchy”
rustup doc --std 'mod'
rustup doc --reference“6.1. Modules”
// this applications makes use of the « my_project » crate use my_project::{drawing::{Point, Shape}, stats::RollingMean};
fn main() { let mut rm = RollingMean::new(4); for i in 3..=9 { let value = (i / 3) as f64; rm.sample(value); let mean = rm.mean(); println!("{:.3} ~~> {:.3} {:?}", value, mean, rm); } let samples = rm.into_vec(); println!("samples={:?}", samples); // for sh in [ Shape::new(None, None), Shape::new(Some(Point { x: 20, y: 10 }), None), Shape::new(Some(Point { x: 30, y: 10 }), Some((40, 20))), ] { println!("{:?}", sh); for i in 1..3 { let p = Point { x: 20 * i, y: 10 * i, }; if sh.contains_point(&p) { println!(" ~~> contains {:?}", p); } } } } /* 1.000 ~~> 0.250 RollingMean { samples: [1.0, 0.0, 0.0, 0.0], next: 1 } 1.000 ~~> 0.500 RollingMean { samples: [1.0, 1.0, 0.0, 0.0], next: 2 } 1.000 ~~> 0.750 RollingMean { samples: [1.0, 1.0, 1.0, 0.0], next: 3 } 2.000 ~~> 1.250 RollingMean { samples: [1.0, 1.0, 1.0, 2.0], next: 0 } 2.000 ~~> 1.500 RollingMean { samples: [2.0, 1.0, 1.0, 2.0], next: 1 } 2.000 ~~> 1.750 RollingMean { samples: [2.0, 2.0, 1.0, 2.0], next: 2 } 3.000 ~~> 2.250 RollingMean { samples: [2.0, 2.0, 3.0, 2.0], next: 3 } samples=[2.0, 2.0, 3.0, 2.0] Empty Point(Point { x: 20, y: 10 }) ~~> contains Point { x: 20, y: 10 } Box { corner: Point { x: 30, y: 10 }, width: 40, height: 20 } ~~> contains Point { x: 40, y: 20 } */
//! An incomplete « my_project » crate
pub mod stats; // tell the compiler that ... pub mod drawing; // ... these two modules exist
//! An incomplete module dedicated to statistics
/// A type to filter some values as the average of the last samples. #[derive(Debug, Clone)] pub struct RollingMean { samples: Vec<f64>, next: usize, }
impl RollingMean { /// Makes a new RollingMean with an average of count samples. pub fn new(count: usize) -> Self { Self { samples: vec![0.0; count], next: 0, } }
/// Returns the number of samples used by the RollingMean. pub fn count(&self) -> usize { self.samples.len() }
/// Returns the average of the last samples. pub fn mean(&self) -> f64 { let count = self.count() as f64; self.samples.iter().sum::<f64>() / count }
/// Stores a new sample, getting rid of the oldest one. pub fn sample( &mut self, value: f64, ) { self.samples[self.next] = value; self.next = (self.next + 1) % self.count(); }
/// Transforms the RollingMean into the vector it contains. pub fn into_vec(self) -> Vec<f64> { self.samples } }
//! An incomplete module dedicated to drawing 2D shapes
/// A 2D point. #[derive(Debug, Clone)] pub struct Point { pub x: i32, pub y: i32, }
/// A 2D shape. #[derive(Debug, Clone)] pub enum Shape { Empty, Point(Point), Box { corner: Point, width: i32, height: i32, }, }
impl Shape { /// Creates a shape depending upon the available arguments. pub fn new( point: Option<Point>, size: Option<(i32, i32)>, ) -> Self { if let Some(point) = point { if let Some((w, h)) = size { Self::Box { corner: point, width: w, height: h, } } else { Self::Point(point) } } else { Self::Empty } }
/// Tells if the shape overlaps with the provided point. pub fn contains_point( &self, point: &Point, ) -> bool { match self { Self::Empty => false, Self::Point(p) => point.x == p.x && point.y == p.y, Self::Box { corner: c, width: w, height: h, } => { point.x >= c.x && point.x <= c.x + w && point.y >= c.y && point.y <= c.y + h } } } }
rustup doc --book“7.2. Defining Modules to Control Scope and Privacy”
rustup doc --book“7.3. Paths for Referring to an Item in the Module Tree, Exposing Paths with the pub Keyword”
rustup doc --book“7.3. Paths for Referring to an Item in the Module Tree, Making Structs and Enums Public”
rustup doc --rust-by-example“10.1. Visibility”
rustup doc --rust-by-example“10.2. Struct visibility”
rustup doc --std 'pub'
rustup doc --reference“12.6. Visibility and privacy”
[dependencies] nanorand = "0.7.0" serde_json = "1.0"
use nanorand::{Rng, WyRand}; use serde_json::Value;
fn main() { let mut rng = WyRand::new(); let values = Vec::from_iter((0..5).map(|_| rng.generate_range(0..10_u8))); println!("values={:?}", values); if let Ok(json_str) = serde_json::to_string(&values) { println!("json_str={:?}", json_str); if let Ok(json_values) = serde_json::from_str::<Value>(&json_str) { println!("json_values={:?}", json_values); } } } /* values=[5, 2, 6, 3, 8] json_str="[5,2,6,3,8]" json_values=Array([Number(5), Number(2), Number(6), Number(3), Number(8)]) */
rustup doc --rust-by-example“12.1. Dependencies”