/*
* Author: 邹航标 (No. 43)
*
* Useful links:
*
* https://github.com/AmadeusGB/SubstrateClass/blob/master/lesson5/area/src/main.rs
* https://shimo.im/docs/rTJPC8PTpD3xJGVY/read
* https://wj.qq.com/s2/7525430/1f79/
* https://play.rust-lang.org/
*/
// solution 1
#[derive(Debug)]
enum TrafficLight {
Red,
Green,
Yellow,
}
trait Light {
fn duration(&self) -> i32;
}
impl Light for TrafficLight {
fn duration(&self) -> i32 {
return match self {
TrafficLight::Red => 30,
TrafficLight::Green => 5,
TrafficLight::Yellow => 45,
}
}
}
// https://doc.rust-lang.org/book/ch10-02-traits.html#specifying-multiple-trait-bounds-with-the--syntax
// fn display_light<T: Light + std::fmt::Debug>(l: T){
// fn display_light(l: impl Light + std::fmt::Debug){
fn _display_light<T>(light: T) where T: Light + std::fmt::Debug{
println!("{:?} light lasts for {}s", light, light.duration())
}
macro_rules! display_light {
($( $light:expr),* $(,)?) => {{
$( println!("{:?} light lasts for {}s", $light, $light.duration()); )*
}};
}
fn solution1(){
display_light!(
TrafficLight::Red,
TrafficLight::Green,
TrafficLight::Yellow,
)
}
// solution 2
fn sum_u32(xs: &[u32]) -> Option<u32> {
xs.iter().try_fold(0u32, |acc, &x| acc.checked_add(x))
}
fn _display_sum(array: &[u32]){
println!("Sum of {:?} = {:?}", array, sum_u32(array))
}
macro_rules! display_sum {
( $( $array:expr ),* $(,)? ) => {{
$(
let array : &[u32] = $array;
println!("Sum of {:?} = {:?}", array, sum_u32(array));
)*
}};
}
fn solution2(){
display_sum!(
&[],
&[0],
&[1],
&[1, 2, 3, 4],
&[std::u32::MAX],
&[std::u32::MAX, 0],
&[std::u32::MAX, 1],
&[std::u32::MAX, 1, 2, 3, 4],
)
}
// solution 3
trait Shape {
type Output;
fn area(&self) -> Self::Output;
}
#[derive(Debug)]
struct Square<T>(T);
#[derive(Debug)]
struct Circle<T>(T);
#[derive(Debug)]
struct Triangle<T>(T, T);
#[derive(Debug)]
struct Rectangle<T>(T, T);
impl<T: std::ops::Mul<Output = T> + Copy> Shape for Square<T> {
type Output = T;
fn area(&self) -> Self::Output {
self.0 * self.0
}
}
impl<T: std::ops::Mul<Output = T> + Into<f64> + Copy> Shape for Circle<T> {
type Output = f64;
fn area(&self) -> Self::Output {
(self.0 * self.0).into() * std::f64::consts::PI
}
}
impl<T: std::ops::Mul<Output = T> + Copy> Shape for Rectangle<T> {
type Output = T;
fn area(&self) -> Self::Output {
self.0 * self.1
}
}
impl<T: std::ops::Mul<Output = T> + Into<f64> + Copy> Shape for Triangle<T> {
type Output = f64;
fn area(&self) -> Self::Output {
(self.0 * self.1).into() * 0.5
}
}
/*
fn display_shape(s: (impl Shape + std::fmt::Debug)){
println!("{:?}'s area is {}", s, s.area())
}
*/
// https://stackoverflow.com/questions/43143327/how-to-allow-optional-trailing-commas-in-macros
macro_rules! display_shape {
($( $shape:expr),* $(,)?) => {{
$( println!("Area of {:?} = {}", $shape, $shape.area()); )*
}};
}
fn solution3() {
display_shape!(
Square(1),
Square(0.2),
Circle(1),
Rectangle(1, 2),
Rectangle(0.1, 0.2),
Triangle(1, 2),
Triangle(0.1, 0.2),
)
}
fn main(){
println!("\n# solution 1"); solution1();
println!("\n# solution 2"); solution2();
println!("\n# solution 3"); solution3();
}
// https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=363dea3ab64375f51511cf8a60f165c4