races - Generics - Traits - Minimal runtime - C bindings - Strongly typed, but with type inference - Excepcional standard library, many zero-cost abstractions, including concurrency primitives Rust: the good 5
mutable because it is also borrowed as immutable borrow.rs:8 v.push("world"); ^ borrow.rs:6:11: 6:12 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends borrow.rs:6 let w = &v[0]; ^ borrow.rs:11:2: 11:2 note: previous borrow ends here borrow.rs:1 fn main() { ... borrow.rs:11 } ^ error: aborting due to previous error 11
logical: bool = true; let a_float: f64 = 1.0; // Regular annotation let an_integer = 5i32; // Suffix annotation // Or a default will be used. let default_float = 3.0; // `f64` let default_integer = 7; // `i32` let tuple = (1u8, 2u16, 3u32, 4u64, -1i8, -2i16, -3i32, -4i64, 0.1f32, 0.2f64, 'a', true); // Values can be extracted from the tuple using tuple indexing println!("long tuple first value: {}", long_tuple.0); } Primitives 13
= [1, 2, 3, 4, 5]; // All elements can be initialized to the same value let ys: [i32; 500] = [0; 500]; println!("first element of the array: {}", xs[0]); println!("array size: {}", xs.len()); // Arrays can be automatically borrowed as slices println!("borrow the whole array as a slice"); analyze_slice(&xs); println!("borrow a section of the array as a slice"); analyze_slice(&ys[1 .. 4]); // borrow a section of the slice! } fn analyze_slice(slice: &[i32]) { println!("first element of the slice: {}", slice[0]); println!("the slice has {} elements", slice.len()); } Arrays and slices 14
(like C) Skinny, Fat, // like tuple structs, Height(i32), Weight(i32), // or like structures. Info { name: String, height: i32 } } fn main() { let person = Person::Height(18); let danny = Person::Weight(10); let dave = Person::Info {name: "Dave".to_owned(), height: 72}; let john = Person::Fat; let larry = Person::Skinny; } Structs and enums 16
if are expressions! let n_less_than_0 = if n < 0 { true }; // while and for/range while n < 0 { // do stuff! } for i in range 1..100 { // do 100 stuffs! } loop { // infinite loop } Flow control 17
// match single 2 | 3 | 5 | 7 | 11 => println!("This is a prime"), // match OR 13...19 => println!("A teen"), // match range _ => println!("Ain't special"), // rest of cases } let boolean = true; // match is an expression too! let binary: u8 = match boolean { false => 0, true => 1, }; let pair = (0, -2); // match works with tuples, enums, structs, etc aswell (destructuring) match pair { (0, y) => println!("First is `0` and `y` is `{:?}`", y), (x, 0) => println!("`x` is `{:?}` and last is `0`", x), } Flow control: pattern matching 18
when no ";", this will be returned } struct Point { x: f64, y: f64, } impl Point { fn new(x: f64, y: f64) -> Point { Point { x: x, y: y } } fn do_something(&mut self) -> bool { self.x = 10; return true; // can also use "return" } } let point = Point::new(); point.do_something() sample_function("", point); Functions and methods 19
Result<String, i32> { if some_condition { Ok("Here is your data".to_string()) } else { Err(100) } } match my_function() { Ok(v) => println!("{}", v), Err(e) => println!("This is a disaster: {}", e), } // also try! this will panic when Err is found! let my_ok_value = try!(my_function()); Result 26
// Box will be destroyed out of the scope here fn main() { let a = Box::new(100); println!("a contains: {}", a); let b = a; // now b owns the Box println!("a contains: {}", a); // ERROR destroy_box(b); // moving Box to the function println!("b contains: {}", b); // ERROR } Move semantics 28
layer of indirection // copied to the stack! let raw_data = *boxed_data; } // I'm cleaned here std: Box 32 • Heap allocated data • Like “unique_ptr<T>” in C++ • Memory automatically freed when out-of-scope
shared_numbers = Arc::new(numbers); for _ in 0..10 { let child_numbers = shared_numbers.clone(); // move 'child_numbers' to the thread, work locally thread::spawn(move || { let local_numbers = &child_numbers[..]; }); } std::sync 33 • Multiple sync primitives: Arc, Barrier, Mutex, Once, etc. • Also mpsc (channels)
let (tx, rx) = channel(); thread::spawn(move|| { tx.send(10).unwrap(); }); assert_eq!(rx.recv().unwrap(), 10); std::mpsc (channels) 34 • Multi-producer, single-consumer FIFO queue communication primitives • Like Go but a little bit more syntax
• std::cmp, comparisons: Eq, PartialEq, etc. • IO: std::io, std::net (TcpListener, etc.) • Iterators: Chain, Cycle, Once, Map, etc. • Processes: std::process, run command, pipes, etc. • Most of these expose traits, so you can extend your structures this way!