Chapter 1 Draft
parent
16a59fa4a0
commit
93ed2cd683
@ -0,0 +1,44 @@
|
||||
[package]
|
||||
name = "Chapter1"
|
||||
version = "1.0.0"
|
||||
|
||||
[dependencies]
|
||||
lazy_static = "1"
|
||||
cached = "0.5"
|
||||
metaderive = { path = "metaderive" }
|
||||
|
||||
[[bin]]
|
||||
name = "intro_binding"
|
||||
path = "intro_binding.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "intro_datatypes"
|
||||
path = "intro_datatypes.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "intro_expressions"
|
||||
path = "intro_expressions.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "intro_functions"
|
||||
path = "intro_functions.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "intro_generics"
|
||||
path = "intro_generics.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "intro_iterators"
|
||||
path = "intro_iterators.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "intro_metaprogramming"
|
||||
path = "intro_metaprogramming.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "intro_mixoopfp"
|
||||
path = "intro_mixoopfp.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "intro_patterns"
|
||||
path = "intro_patterns.rs"
|
@ -0,0 +1,71 @@
|
||||
use std::thread;
|
||||
use std::sync::{Mutex, Arc};
|
||||
use std::sync::mpsc::channel;
|
||||
|
||||
fn scoped() {
|
||||
vec![1, 2, 3];
|
||||
}
|
||||
|
||||
fn scoped2() -> Vec<u32> {
|
||||
vec![1, 2, 3]
|
||||
}
|
||||
|
||||
fn scoped3() {
|
||||
let v1 = vec![1, 2, 3];
|
||||
let v2 = v1;
|
||||
//it is now illegal to reference v1,
|
||||
//because ownership has been transferred to v2
|
||||
}
|
||||
|
||||
fn scoped4() {
|
||||
vec![1, 2, 3].clone();
|
||||
"".to_string().clone();
|
||||
}
|
||||
|
||||
fn scoped5() {
|
||||
fn foo(v1: &Vec<u32>){}
|
||||
let v1 = vec![1, 2, 3];
|
||||
foo(&v1);
|
||||
//v1 is still valid, ownership has been returned
|
||||
v1;
|
||||
}
|
||||
|
||||
fn thread1() {
|
||||
let v = vec![1, 2, 3];
|
||||
let handle = thread::spawn(move || {
|
||||
println!("Here's a vector: {:?}", v);
|
||||
});
|
||||
handle.join();
|
||||
}
|
||||
|
||||
fn thread2()
|
||||
{
|
||||
let counter = Arc::new(Mutex::new(0));
|
||||
let mut handles = vec![];
|
||||
for _ in 0..10 {
|
||||
let counter = Arc::clone(&counter);
|
||||
let handle = thread::spawn(move || {
|
||||
let mut num = counter.lock().unwrap();
|
||||
*num += 1;
|
||||
});
|
||||
handles.push(handle);
|
||||
}
|
||||
for handle in handles {
|
||||
handle.join().unwrap();
|
||||
}
|
||||
println!("Result: {}", *counter.lock().unwrap());
|
||||
}
|
||||
|
||||
fn thread3() {
|
||||
let (sender, receiver) = channel();
|
||||
let handle = thread::spawn(move || {
|
||||
//do work
|
||||
let v = vec![1, 2, 3];
|
||||
sender.send(v).unwrap();
|
||||
});
|
||||
handle.join();
|
||||
receiver.recv().unwrap();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
//It can be helpful to create shorthand names for complex types
|
||||
type Name = String;
|
||||
|
||||
//Structs can be repetitive if you just want a way to store multiple values together
|
||||
struct Data1
|
||||
{
|
||||
a: i32,
|
||||
b: f64,
|
||||
c: String
|
||||
}
|
||||
struct Data2
|
||||
{
|
||||
a: u32,
|
||||
b: String,
|
||||
c: f64
|
||||
}
|
||||
|
||||
//Tuples help eliminate redundant struct definitions
|
||||
//no prior type definitions are needed here and the aliases are redundant
|
||||
type Tuple1 = (i32, f64, String);
|
||||
type Tuple2 = (u32, String, f64);
|
||||
|
||||
//Standard operators can be implemented with traits
|
||||
//anyone coming from an ML family language may appreciate
|
||||
use std::ops::Mul;
|
||||
|
||||
//Standard library collections etc. are generic
|
||||
use std::collections::HashMap;
|
||||
type CustomHashMap = HashMap<i32,u32>;
|
||||
|
||||
//Tagged Unions can be used to create typesafe definitions of structures that can't be safely described in pure OOP
|
||||
enum BTree<T>
|
||||
{
|
||||
Branch { val:T, left:Box<BTree<T>>, right:Box<BTree<T>> },
|
||||
Leaf { val:T }
|
||||
}
|
||||
|
||||
//Commonly, Tagged Unions are used for complex data structures with many possible union options
|
||||
enum Term
|
||||
{
|
||||
TermVal { value: String },
|
||||
TermVar { symbol: String },
|
||||
TermApp { f: Box<Term>, x: Box<Term> },
|
||||
TermAbs { arg: String, body: Box<Term> }
|
||||
}
|
||||
|
||||
//Traits are a bit like Object Classes
|
||||
trait Data1Trait
|
||||
{
|
||||
//Traits can define constructors
|
||||
fn new(a: i32, b: f64, c: String) -> Self;
|
||||
|
||||
//Traits can have methods, which reference "self"
|
||||
fn get_a(&self) -> i32;
|
||||
fn get_b(&self) -> f64;
|
||||
fn get_c(&self) -> String;
|
||||
}
|
||||
|
||||
//Traits are also like Data Classes
|
||||
trait BehaviourOfShow
|
||||
{
|
||||
fn show(&self) -> String;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
struct MyStruct {
|
||||
a: u32,
|
||||
b: f32,
|
||||
c: String
|
||||
}
|
||||
|
||||
enum Term {
|
||||
TermVal { value: String },
|
||||
TermVar { symbol: String },
|
||||
TermApp { f: Box<Term>, x: Box<Term> },
|
||||
TermAbs { arg: String, body: Box<Term> }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
let x = {
|
||||
fn f(x: u32) -> u32 {
|
||||
x*x
|
||||
}
|
||||
let y = f(5);
|
||||
y*3
|
||||
};
|
||||
|
||||
let x;
|
||||
if true {
|
||||
x = 1;
|
||||
} else {
|
||||
x = 2;
|
||||
}
|
||||
|
||||
let x = if true { 1 } else { 2 };
|
||||
|
||||
MyStruct {
|
||||
a: 1,
|
||||
b: 1.0,
|
||||
c: "".to_string()
|
||||
};
|
||||
|
||||
(1, 1.0, "".to_string());
|
||||
|
||||
let t = Term::TermVar {
|
||||
symbol: "".to_string()
|
||||
};
|
||||
match t {
|
||||
Term::TermVal { value: v1 } => v1,
|
||||
Term::TermVar { symbol: v1 } => v1,
|
||||
Term::TermApp { f: v1, x: v2 } => "TermApp(?,?)".to_string(),
|
||||
Term::TermAbs { arg: v1, body: v2 } => "TermAbs(?,?)".to_string()
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
fn main() {
|
||||
|
||||
(0..10).map(|x| x*x);
|
||||
|
||||
(0..10).map(|x| {
|
||||
|
||||
fn f(y: u32) -> u32 {
|
||||
y*y
|
||||
}
|
||||
|
||||
let z = f(x+1) * f(x+2);
|
||||
|
||||
z*z
|
||||
|
||||
});
|
||||
|
||||
fn f<T>(g: T, x: u32) -> u32
|
||||
where T: Fn(u32) -> u32
|
||||
{
|
||||
g(x+1) * g(x+2)
|
||||
}
|
||||
f(|x|{x*x}, 2);
|
||||
|
||||
(0..10).map(|x| x*x)
|
||||
.inspect(|x|{ println!("value {}", *x) })
|
||||
.filter(|x| *x<3)
|
||||
.filter_map(|x| Some(x))
|
||||
.fold(0, |x, y| x+y);
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
//Data Type Definitions
|
||||
struct PointU32
|
||||
{
|
||||
x: u32,
|
||||
y: u32
|
||||
}
|
||||
struct PointF32
|
||||
{
|
||||
x: f32,
|
||||
y: f32
|
||||
}
|
||||
|
||||
//can be written with generics
|
||||
struct Point<T>
|
||||
{
|
||||
x: T,
|
||||
y: T
|
||||
}
|
||||
|
||||
//Function Definitions
|
||||
fn foo_u32(x: u32) -> u32
|
||||
{
|
||||
x*x
|
||||
}
|
||||
fn foo_f32(x: f32) -> f32
|
||||
{
|
||||
x*x
|
||||
}
|
||||
|
||||
//can be written with generics
|
||||
fn foo<T>(x: T) -> T
|
||||
where T: std::ops::Mul<Output = T> + Copy
|
||||
{
|
||||
x*x
|
||||
}
|
||||
|
||||
//even functions can be sent to generics
|
||||
//we call these "higher order functions"
|
||||
fn bar<F,T>(f: F, x: T) -> T
|
||||
where F: Fn(T) -> T
|
||||
{
|
||||
f(x)
|
||||
}
|
||||
|
||||
fn main()
|
||||
{
|
||||
PointU32 { x:1, y:1 };
|
||||
PointF32 { x:1.0, y:1.0 };
|
||||
Point { x:1, y:1 };
|
||||
Point { x:1.0, y:1.0 };
|
||||
foo_u32(1);
|
||||
foo_f32(1.0);
|
||||
foo(1);
|
||||
foo(1.0);
|
||||
bar(|x|{x}, 1);
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
fn main() {
|
||||
|
||||
(0..10).chain(10..20);
|
||||
|
||||
(0..10).zip(10..20);
|
||||
|
||||
(0..10).enumerate();
|
||||
|
||||
(0..10).inspect(|x|{ println!("value {}", *x) });
|
||||
|
||||
(0..10).map(|x| x*x);
|
||||
|
||||
(0..10).filter(|x| *x<3);
|
||||
|
||||
(0..10).fold(0, |x,y| x+y);
|
||||
|
||||
for i in (0..10) {}
|
||||
|
||||
let v: Vec<u32> = (0..10).collect();
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
#[macro_use]
|
||||
extern crate metaderive;
|
||||
|
||||
macro_rules! my_vec_macro {
|
||||
( $( $x:expr ),* ) => {
|
||||
{
|
||||
let mut temp_vec = Vec::new();
|
||||
$(
|
||||
temp_vec.push($x);
|
||||
)*
|
||||
temp_vec
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! my_macro_branch
|
||||
{
|
||||
(1 $e:expr) => (println!("mode 1: {}", $e));
|
||||
(2 $e:expr) => (println!("mode 2: {}", $e));
|
||||
}
|
||||
|
||||
enum DSLTerm {
|
||||
TVar { symbol: String },
|
||||
TAbs { param: String, body: Box<DSLTerm> },
|
||||
TApp { f: Box<DSLTerm>, x: Box<DSLTerm> }
|
||||
}
|
||||
|
||||
macro_rules! dsl
|
||||
{
|
||||
( ( $($e:tt)* ) ) => (dsl!( $($e)* ));
|
||||
( $e:ident ) => (DSLTerm::TVar { symbol: stringify!($e).to_string() });
|
||||
( fn $p:ident . $b:tt ) => (DSLTerm::TAbs { param: stringify!($p).to_string(), body: Box::new(dsl!($b)) });
|
||||
( $f:tt $x:tt ) => (DSLTerm::TApp { f: Box::new(dsl!($f)), x: Box::new(dsl!($x)) });
|
||||
}
|
||||
|
||||
pub trait TypeName {
|
||||
fn typename() -> String;
|
||||
}
|
||||
|
||||
#[derive(TypeName)]
|
||||
struct MyStructA
|
||||
{
|
||||
a: u32,
|
||||
b: f32
|
||||
}
|
||||
|
||||
fn main()
|
||||
{
|
||||
|
||||
println!("this is a macro {} {}", 1, 2);
|
||||
|
||||
my_vec_macro!(1, 2, 3);
|
||||
|
||||
my_macro_branch!(1 "abc");
|
||||
my_macro_branch!(2 "def");
|
||||
|
||||
dsl!( a );
|
||||
dsl!( fn a . a );
|
||||
dsl!( f a );
|
||||
dsl!( (f a) );
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
struct MyObject
|
||||
{
|
||||
a: u32,
|
||||
b: f32,
|
||||
c: String
|
||||
}
|
||||
|
||||
trait MyObjectTrait
|
||||
{
|
||||
fn new(a: u32, b: f32, c: String) -> Self;
|
||||
|
||||
fn get_a(&self) -> u32;
|
||||
fn get_b(&self) -> f32;
|
||||
fn get_c(&self) -> String;
|
||||
}
|
||||
|
||||
impl MyObjectTrait for MyObject
|
||||
{
|
||||
fn new(a: u32, b: f32, c: String) -> Self
|
||||
{
|
||||
MyObject { a: a, b: b, c: c }
|
||||
}
|
||||
fn get_a(&self) -> u32
|
||||
{
|
||||
self.a
|
||||
}
|
||||
fn get_b(&self) -> f32
|
||||
{
|
||||
self.b
|
||||
}
|
||||
fn get_c(&self) -> String
|
||||
{
|
||||
self.c.clone()
|
||||
}
|
||||
}
|
||||
|
||||
trait MyObjectApply {
|
||||
fn apply<T,R>(&self, f: T) -> R
|
||||
where T: Fn(u32,f32,String) -> R;
|
||||
}
|
||||
|
||||
impl MyObjectApply for MyObject {
|
||||
fn apply<T,R>(&self, f: T) -> R
|
||||
where T: Fn(u32,f32,String) -> R
|
||||
{
|
||||
f(self.a, self.b, self.c.clone())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
#[macro_use] extern crate cached;
|
||||
#[macro_use] extern crate lazy_static;
|
||||
|
||||
trait Monad<A> {
|
||||
fn return_(t: A) -> Self;
|
||||
//:: A -> Monad<A>
|
||||
|
||||
fn bind<MB,B>(m: Self, f: Fn(A) -> MB) -> MB
|
||||
where MB: Monad<B>;
|
||||
//:: Monad<A> -> (A -> Monad<B>)) -> Monad<B>
|
||||
}
|
||||
|
||||
fn not_curried(p1: u32, p2: u32) -> u32
|
||||
{
|
||||
p1 + p2
|
||||
}
|
||||
|
||||
|
||||
fn curried(p1: u32) -> Box<Fn(u32) -> u32>
|
||||
{
|
||||
Box::new(move |p2: u32| {
|
||||
p1 + p2
|
||||
})
|
||||
}
|
||||
|
||||
cached!{
|
||||
FIB;
|
||||
fn fib(n: u64) -> u64 = {
|
||||
if n == 0 || n == 1 { return n }
|
||||
fib(n-1) + fib(n-2)
|
||||
}
|
||||
}
|
||||
|
||||
fn main()
|
||||
{
|
||||
let fsin = |x: f64| x.sin();
|
||||
let fabs = |x: f64| x.abs();
|
||||
let transform = |x: f64| fabs(fsin(x));
|
||||
|
||||
not_curried(1, 2);
|
||||
curried(1)(2);
|
||||
|
||||
let immutable_v1 = 1;
|
||||
//immutable_v1 = 2; //invalid
|
||||
let mut mutable_v2 = 1;
|
||||
mutable_v2 = 2;
|
||||
|
||||
let x = { println!("side effect"); 1 + 2 };
|
||||
let y = ||{ println!("side effect"); 1 + 2 };
|
||||
|
||||
fib(30);
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "metaderive"
|
||||
version = "1.0.0"
|
||||
|
||||
[dependencies]
|
||||
syn = "0.12"
|
||||
quote = "0.4"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
@ -0,0 +1,25 @@
|
||||
#![crate_type = "proc-macro"]
|
||||
extern crate proc_macro;
|
||||
extern crate syn;
|
||||
#[macro_use] extern crate quote;
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
#[proc_macro_derive(TypeName)]
|
||||
pub fn type_name(input: TokenStream) -> TokenStream {
|
||||
// Parse token stream into input AST
|
||||
let ast = syn::parse(input).unwrap();
|
||||
|
||||
// Generate output AST
|
||||
impl_typename(&ast).into()
|
||||
}
|
||||
|
||||
fn impl_typename(ast: &syn::DeriveInput) -> quote::Tokens {
|
||||
let name = &ast.ident;
|
||||
quote! {
|
||||
impl TypeName for #name {
|
||||
fn typename() -> String {
|
||||
stringify!(#name).to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue