Created
February 14, 2018 01:07
-
-
Save christian-blades-cb/94eb58a2a1b7b41909583ceafef86f29 to your computer and use it in GitHub Desktop.
shapr's bookwords demo in rust
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[allow(unused_variables, dead_code)] | |
fn demo() { | |
let somenumber = 1; // immutable variable | |
let somestring = "somestring"; // also ummutable | |
// with type signature | |
let some_other_string: &str = "some other string"; | |
} | |
#[allow(dead_code)] | |
fn add1(x: isize) -> isize { | |
x + 1 | |
} | |
#[allow(unused_variables, dead_code)] | |
fn demo1() { | |
// anonymous function | |
// note -- in Rust, this is a closure, which has access to the scope in which it was created | |
let add2 = |x: isize| x + 2; | |
} | |
#[allow(dead_code)] | |
/// multi-arg function | |
fn add(x: isize, y: isize) -> isize { | |
x + y | |
} | |
// partial application is not in the standard language | |
#[allow(dead_code)] | |
// sum type | |
enum Temp { | |
Hot, | |
Cold, | |
} | |
#[allow(dead_code)] | |
#[derive(Debug)] | |
// the `derive(Debug)` directive above allows us to format this type as a string | |
// under the covers, a macro creates an implementation of the Debug trait for this enum | |
enum Season { | |
Winter, | |
Spring, | |
Summer, | |
Fall, | |
} | |
#[allow(unused_variables, dead_code)] | |
fn demo2() { | |
let my_season: Season = Season::Summer; | |
} | |
// type aliases | |
#[allow(dead_code)] | |
type Name = String; | |
#[allow(dead_code)] | |
type Age = isize; | |
// more complex types | |
// Product type | |
#[allow(dead_code)] | |
struct People { | |
person: (), | |
name: Name, | |
age: Age, | |
} | |
#[allow(unused_variables, dead_code)] | |
fn demo3() { | |
// maybe? In rust we have the built-in Option type | |
let foo: Option<usize> = Some(12); | |
let bar: Option<usize> = None; | |
// we also have a similar built-in designed for operations which may not be successful | |
// | |
// NOTE: usually Results must be used or the code will fail to | |
// compile. We've disabled this with the allow(unused_variables) | |
// compiler directive. | |
let baz: Result<(), std::io::Error> = Ok(()); | |
} | |
#[allow(dead_code)] | |
// polymorphic data type | |
// | |
// note that the borrow-checker forces us to store references to the | |
// branches, and to make their lifetimes explicit. In this case, we've | |
// defined that the values stored live for the lifetime of the parent. | |
enum Tree<'a, A> | |
where A: 'a | |
{ | |
None, | |
Node(&'a Tree<'a, A>, A, &'a Tree<'a, A>), | |
} | |
#[allow(dead_code)] | |
enum TreeInt<'a> { | |
None, | |
Node(&'a TreeInt<'a>, isize, &'a TreeInt<'a>), | |
} | |
// a more rusty way of defining a tree might look like | |
#[allow(dead_code)] | |
struct RustTree<'a, A> | |
where A: 'a | |
{ | |
value: A, | |
left: Option<&'a RustTree<'a, A>>, | |
right: Option<&'a RustTree<'a, A>>, | |
} | |
#[allow(unused_variables, dead_code)] | |
fn demo4() { | |
// my_tree is a tree of type isize | |
let my_tree = Tree::Node(&Tree::Node(&Tree::None, 12isize, &Tree::None), | |
99isize, | |
&Tree::None); | |
let my_tree_rusty = RustTree { | |
value: 99isize, | |
left: Some(&RustTree { | |
value: 12isize, | |
left: None, | |
right: None, | |
}), | |
right: None, | |
}; | |
// TODO: get this example to compile | |
// fn treesum<'a, A>(branch: &'a Tree<A>) -> A | |
// where A: std::ops::Add + std::default::Default | |
// { | |
// match branch { | |
// &Tree::None => A::default(), | |
// &Tree::Node(left, val, right) => treesum(left) + val + treesum(right), | |
// } | |
// } | |
// assert_eq!(111, treesum(&my_tree)); | |
// pattern matching | |
// note that pattern matching must be exhaustive, or it wlll fail to compile | |
let foo = match my_tree { | |
Tree::None => 0, | |
// an example of destructuring inside a match | |
Tree::Node(&Tree::None, val, &Tree::None) => val, | |
Tree::Node(_, val, &Tree::None) => val, | |
Tree::Node(_, val, _) => val, | |
// _ => 5, // _ matches all, and can be used as the default case | |
}; | |
fn weather(a: Season) -> Temp { | |
match a { | |
Season::Summer => Temp::Hot, | |
_ => Temp::Cold, | |
} | |
} | |
} | |
// Traits are equivalent to Haskell typeclasses, allowing you to perform the same operation on many types | |
impl std::fmt::Display for Temp { | |
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { | |
match *self { | |
Temp::Cold => write!(f, "Cold"), | |
Temp::Hot => write!(f, "Hot"), | |
} | |
} | |
} | |
// no equivalents of guards (yet, there's an RFC) | |
// standard Rust is eagerly evaluated, but there's a crate for making things lazy https://crates.io/crates/lazy |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment