feat: multiple lessons
This commit is contained in:
103
src/macros.rs
Normal file
103
src/macros.rs
Normal file
@@ -0,0 +1,103 @@
|
||||
// Group functionality with different types
|
||||
// Define special syntac for specific purpose
|
||||
// Variable number of arguments
|
||||
// Different combination of arguments
|
||||
macro_rules! say_hello {
|
||||
() => {
|
||||
println!("Hello world!");
|
||||
};
|
||||
}
|
||||
|
||||
// Types of arguments have designators:
|
||||
// block
|
||||
// expr is used for expressions
|
||||
// ident is used for variable/function names
|
||||
// item
|
||||
// literal is used for literal constants
|
||||
// pat (pattern)
|
||||
// path
|
||||
// stmt (statement)
|
||||
// tt (token tree)
|
||||
// ty (type)
|
||||
// vis (visibility qualifier)
|
||||
macro_rules! generate_function {
|
||||
($func_name:ident) => {
|
||||
fn $func_name() {
|
||||
println!("You called {:?}()", stringify!($func_name));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
generate_function!(foo);
|
||||
|
||||
macro_rules! process_expression {
|
||||
($expression: expr) => {
|
||||
println!("{:?} = {:?}", stringify!($expression), $expression);
|
||||
};
|
||||
}
|
||||
|
||||
// Overload
|
||||
macro_rules! match_block {
|
||||
($left: expr; and $right: expr) => {
|
||||
println!("A: {:?} and {:?}", stringify!($left), stringify!($right))
|
||||
};
|
||||
|
||||
($left: expr; or $right:expr) => {
|
||||
println!(
|
||||
"B: {:?} or {:?} is {:?}",
|
||||
stringify!($left),
|
||||
stringify!($right),
|
||||
$left || $right
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
// Repeat: variable number of args o a type
|
||||
macro_rules! find_max {
|
||||
($x:expr) => ($x);
|
||||
($x:expr, $($y:expr), +) => (std::cmp::max($x, find_max!($($y), +)));
|
||||
}
|
||||
|
||||
// DSLs: Domain Specific Languages
|
||||
// macro_rules allows you to create your own syntax
|
||||
macro_rules! calc {
|
||||
(eval $e:expr) => {
|
||||
println!("{} = {}", stringify!($e), $e);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! calculate {
|
||||
(eval $e: expr) => {
|
||||
{
|
||||
let val: usize = $e; // Force types to be integers
|
||||
println!("{} = {}", stringify!{$e}, val);
|
||||
}
|
||||
};
|
||||
(eval $e: expr, $(eval $y: expr), +) => {{
|
||||
calculate!{eval $e}
|
||||
calculate!{ $(eval $y), + }
|
||||
}};
|
||||
}
|
||||
|
||||
pub fn macros_rule() {
|
||||
foo();
|
||||
say_hello!();
|
||||
process_expression!(1 + 5 * 3);
|
||||
|
||||
match_block!(1i32 + 1 == 2i32; and 2i32 * 2 == 4i32); // Enters first branch
|
||||
match_block!(true; or false); // Enter second branch
|
||||
match_block!(true; and true); // Enters first branch
|
||||
|
||||
println!("Max is {}", find_max!(5, 3 * 8, 4, 9 * 5));
|
||||
|
||||
calc! {
|
||||
eval (1 + 2) * 4
|
||||
}
|
||||
|
||||
calculate! {
|
||||
eval (1 + 2) * 4,
|
||||
eval 1 + 5,
|
||||
eval 7 + 4,
|
||||
eval 3 + 9
|
||||
}
|
||||
}
|
||||
18
src/main.rs
18
src/main.rs
@@ -5,18 +5,8 @@
|
||||
// : /// Doc comment: generate library docs for the following item
|
||||
// : //! Doc comment
|
||||
|
||||
// mod helloworld;
|
||||
// mod primitives;
|
||||
// mod customtypes;
|
||||
//mod variablebindings;
|
||||
// mod types;
|
||||
//mod conversion;
|
||||
// mod controlflow;
|
||||
// mod traits;
|
||||
// mod str_types;
|
||||
// mod functions;
|
||||
// mod exercises;
|
||||
mod concepts;
|
||||
mod macros;
|
||||
use macros::macros_rule;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "./test/basic_test.rs"]
|
||||
@@ -35,5 +25,7 @@ fn main() {
|
||||
// exercises::run_easy();
|
||||
// my_lib::public_function();
|
||||
// functions::functions_module();
|
||||
concepts::box_basics();
|
||||
// concepts::box_basics();
|
||||
// operators::operators_module();
|
||||
macros_rule();
|
||||
}
|
||||
|
||||
24
src/operators.rs
Normal file
24
src/operators.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use std::ops;
|
||||
use std::ops::Add;
|
||||
|
||||
/*
|
||||
* Operators are syntectic sugar for method calls
|
||||
* The + operator calls the add method and so on
|
||||
* */
|
||||
pub fn operators_module() {
|
||||
let a = 3u32.add(3);
|
||||
println!("a is {a}");
|
||||
|
||||
// Operator overloading
|
||||
struct Foo;
|
||||
impl ops::Add<u32> for Foo {
|
||||
type Output = Foo;
|
||||
fn add(self, rhs: u32) -> Self::Output {
|
||||
println!("> add called with {}", rhs);
|
||||
Foo
|
||||
}
|
||||
}
|
||||
|
||||
let foo = Foo;
|
||||
let _too = foo + 3; // > add called with 3
|
||||
}
|
||||
@@ -6,6 +6,8 @@
|
||||
* 4. Extend the trait with a second function and see what happens
|
||||
* */
|
||||
|
||||
use std::thread::current;
|
||||
|
||||
pub trait Move {
|
||||
fn to(&mut self, x: i32, y: i32);
|
||||
}
|
||||
@@ -32,4 +34,91 @@ pub fn traits_exercise() {
|
||||
me.to(10, 20);
|
||||
|
||||
println!("My name is {} and i'm at {:?}", me.name, me.position);
|
||||
|
||||
// Drop trait: called with an object goes out of scope
|
||||
struct Foo;
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {
|
||||
println!("Foo went out of scope...");
|
||||
}
|
||||
}
|
||||
|
||||
let mut counter = 0u32;
|
||||
loop {
|
||||
if counter > 5 {
|
||||
break;
|
||||
}
|
||||
counter += 1;
|
||||
let _foo = Foo;
|
||||
}
|
||||
|
||||
// Iterator traits
|
||||
// Example: Fibonacci
|
||||
struct Fibonacci {
|
||||
current: u32,
|
||||
next: u32,
|
||||
}
|
||||
|
||||
impl Iterator for Fibonacci {
|
||||
type Item = u32;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let current = self.current;
|
||||
self.current = self.next;
|
||||
self.next = self.next + current;
|
||||
Some(current)
|
||||
}
|
||||
}
|
||||
|
||||
let mut fib = Fibonacci {
|
||||
current: 0,
|
||||
next: 1,
|
||||
};
|
||||
|
||||
for _ in 0..21 {
|
||||
println!("Fib {:?}", fib.next());
|
||||
}
|
||||
|
||||
let mut fib = Fibonacci {
|
||||
current: 0,
|
||||
next: 1,
|
||||
};
|
||||
println!("Fib 20 {:?}", fib.nth(20));
|
||||
let fib = Fibonacci {
|
||||
current: 0,
|
||||
next: 1,
|
||||
};
|
||||
println!("Fib skip 20 {:?}", fib.skip(20).next());
|
||||
|
||||
// Disambiguating overlapping traits
|
||||
struct Fee {
|
||||
a: u32,
|
||||
b: String,
|
||||
}
|
||||
|
||||
trait A {
|
||||
fn get(&self) -> u32;
|
||||
}
|
||||
trait B {
|
||||
fn get(&self) -> String;
|
||||
}
|
||||
|
||||
impl A for Fee {
|
||||
fn get(&self) -> u32 {
|
||||
self.a
|
||||
}
|
||||
}
|
||||
impl B for Fee {
|
||||
fn get(&self) -> String {
|
||||
self.b.clone()
|
||||
}
|
||||
}
|
||||
|
||||
let fee = Fee {
|
||||
a: 1234,
|
||||
b: "asdf".to_string(),
|
||||
};
|
||||
|
||||
let a = <Fee as A>::get(&fee);
|
||||
let b = <Fee as B>::get(&fee);
|
||||
println!("The a is {} and the b is {}", a, b);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user