# .title[Functional Rust] # An Exploration Lisa Passing - LambdaDays 2018 --- # $ whoami -- Hi, I'm Lisa π -- Berlin based web dev, hobby game dev, wannabe digital artist. -- Co-organizer of [ClojureBridge Berlin](http://clojurebridge-berlin.org/) and various [CryptoParties](https://www.cryptoparty.in/berlin). -- I've spoken at [RustFest Kyiv](http://2017.rustfest.eu/) and [RustFest ZΓΌrich](http://zurich.rustfest.eu/). --- class: center, middle ![Rust logo](img/rust-logo.jpg) --- # Rust is -- - a systems progamming language (like C/ C++) -- - safe, fast and concurrent -- - relatively young (1.0.0 was released in 2015) -- - gaining popularity --- class: center, middle ## Is Rust a functional language? -- No, more like, imperative and multi-paradigm. --- background-image: url(img/shrug2.gif) background-size: cover --- ## Two reasons -- 1. We can still apply functional thinking non-functional languages -- 2. Rust drew inspiration from functional languages -- 3.* Rust will be important and knowing it will be useful .small[`* one-off-error joke`] --- background-image: url(img/humble-1.png) background-size: cover --- background-image: url(img/humble-2.png) background-size: contain --- background-image: url(img/humble-3.png) background-size: contain --- # Disclaimer -- This is not a complete overview of Rust. -- The learning curve can be more like a wall you hit. --- class: center, middle ## Let's get functional --- class: center, middle Ready? --- class: center, middle Ready? --- # Checklist β Immutability β Functions β Types and Traits β Higher Order Functions --- # Immutability -- - per default all variables are immutable -- ```rust fn main() { let a = "hello"; a = "foo"; } ``` -- ```rust error[E0384]: cannot assign twice to immutable variable `a` --> src/main.rs:4:5 | 3 | let a = "Hello"; | - first assignment to `a` 4 | a = "foo"; | ^^^^^^^^^ cannot assign twice to immutable variable error: aborting due to previous error ``` --- # Immutability - per default all variables are immutable -- - you can opt-into mutability -- ```rust fn main() { let mut a = "hello"; a = "foo"; } ``` --- # Immutability - per default all variables are immutable - you can opt-into mutability -- - constants are always immutable ```rust const MAX_POINTS: u32 = 1000; ``` -- - _Sidenote_: type annotation on variable assignment is optional --- # Immutability .small[pt2] -- - Rust does not implement persistent datastructures -- βͺ copying and allocating large quantities of data comes with performance cost -- - there are community implementations ([github.com/bodil/im-rs](https://github.com/bodil/im-r)) -- - Ownership and Borrowing* take care of common pitfalls of mutability .small[`* large topics that are left out in this talk`] --- # Checklist β Immutability β Functions β Types and Traits β Higher Order Functions --- # Functions -- ```rust fn main() { println!("Hello World"); } ``` --- # Functions -- - can have parameters (but not an arbitrary number) -- - if it has params, types must be annotated -- ```rust fn main() { id(7); } fn id(x: u32) { println!("Hello {}", x); } ``` --- # Functions - can have parameters (but not an arbitrary number) - if it has params, types must be annotated -- - if it returns a value, types must be annotated -- ```rust fn main() { println!("Hello {}", id(7)); } fn id(x: u32) -> u32 { x } ``` --- # What does a `fn` return? -- ```rust fn main() { println!("Hello {}", id(7)); } fn id(x: u32) -> u32 { x } ``` --- class: center, middle # ; --- # Statements vs Expressions -- - Statements perform actions - Expressions return values -- - Expressions do not have a trailing semicolon --- # Statements vs Expressions .small[pt2] -- - Function declarations are statements - Function calls are expressions -- - Statements __cannot__ be assigned to variables, expressions __can__ --- # Checklist β Immutability β Functions β Types and Traits β Higher Order Functions --- # Types -- - Rust is statically typed - with type inference --- # Generic Types and Traits -- - `Generics` are stand-ins for concrete types -- - `Traits` abstact implementation of functionality -- - on concrete types -- - on generic types -- ```rust impl Log for
{} ``` --- # Enums and Pattern matching -- - `Enums` are types with enumerated possible values -- - `Enum variants` can hold `generic` Types -- ```rust enum Option
{ Some
, None, } ``` --- # Enums and Pattern matching - `Enums` are types with enumerated possible values - `Enum variants` can hold `generic` Types ```rust fn plus_one(x: Option
) -> Option
{ match x { None => None, Some(i) => Some(i + 1), } } ``` -- ```rust plus_one(Some(5)).unwrap(); ``` --- # Checklist β Immutability β Functions β Types and Traits β Higher Order Functions --- # Higher Order Functions -- - function names are part of a function's type -- βͺ functions with same signature are still different -- βͺ creating functions dynamically and passing them around is not (easily) possible -- - can't capture values from environment --- class: middle, center But there is another way! --- # Closures -- - anonymous functions that can capture values from their environment -- - can be saved in variables and used as arguments -- ```rust let a_closure = |num| { num * num } ``` -- ```rust a_closure(7) ``` --- # Closures - anonymous functions that can capture values from their environment - can be saved in variables and used as arguments - type annotations are optional -- - _Sidenote_: [example implementation of memoization with closures](https://doc.rust-lang.org/book/second-edition/ch13-01-closures.html#storing-closures-using-generic-parameters-and-the-fn-traits) --- # Iterators -- - `Trait` that handles logic to manage the iteration of a sequence -- - `Iterators` are thread-safe -- - `Iterators` are lazy -- ```rust let v1 = vec![1, 2, 3, 4, 5]; let v2 = v1.iter(); ``` -- ```rust for v in v2 { println!("{}", v); } ``` --- # Iterators .small[pt2] - can take closures as argument -- - __consuming adaptors__ use up the `Iterator` -- ```rust let v1 = vec![1, 2, 3, 4]; let v2 = v1.iter().fold(0, |acc, &x| acc + x); ``` -- - __iterator adaptors__ can transform one `Iterator` into another -- ```rust let v1 = vec![1, 2, 3, 4]; let v2 = v1.iter().map(|x| x + 1).fold(0, |acc, x| acc + x); ``` --- ## Implementing the Iterator trait -- ```rust struct Counter { count: u32, } impl Counter { fn new() -> Counter { Counter { count: 0 } } } ``` .small[[Example taken from the book](https://doc.rust-lang.org/book/second-edition/ch13-02-iterators.html#implementing-the-iterator-trait-to-create-our-own-iterators)] --- ## Implementing the Iterator trait .small[pt2] -- ```rust impl Iterator for Counter { type Item = u32; fn next(&mut self) -> Option
{ self.count += 1; if self.count < 6 { Some(self.count) } else { None } } } ``` --- ## Implementing the Iterator trait .small[pt3] -- ```rust fn main() { let counter = Counter::new(); let even_nums: Vec
= counter.filter(|x| { if x % 2 == 0 { true } else { false } }).collect(); println!("Even: {:?}", even_nums); } ``` -- ```bash Even: [2, 4] ``` --- # Checklist β Immutability β Functions β Types and Traits β Higher Order functions --- class: center, middle phew --- class: center, middle ## That's (almost) all, folks! --- class: center, middle # Explore functional Rust yourself! --- ## Special <3 **Florian** ([@argorak](https://twitter.com/Argorak)) and **Andrew** ([@andrewhobden](https://twitter.com/andrewhobden)) for reviewing this talk! **Carol** ([@carols10cents](https://twitter.com/Carols10cents)) for the amazing work on the [2nd edition Rust book](https://doc.rust-lang.org/book/second-edition/)! --- # Thank you! mail[at]lislis[dot]de https://github.com/lislis (Slides) https://lislis.de/talks/fp-rust