Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rust Language

Rust Language

Barcamp Bangkok 2016

Manatsawin Hanmongkolchai

October 15, 2016
Tweet

More Decks by Manatsawin Hanmongkolchai

Other Decks in Programming

Transcript

  1. Me • Manatsawin Hanmongkolchai • @awkwin • Software and Knowledge

    Engineering @ KU • Intern @ Wongnai • I've been learning Rust since February
  2. Pattern matching switch(x){ case 1: printf("Hello"); break; case 2: printf("World");

    break; default: printf("Error"); } match x { 1 => println!("Hello"), 2 => println!("World"), _ => println!("Error"), }
  3. Pattern matching match x { Ok(1) => println!("Hello"), Ok(2) =>

    println!("World"), Error => println!("Error"), } enum Result { Ok(i32), Error } error[E0004]: non-exhaustive patterns: `Ok(_)` not covered --> <anon>:8:11 | 8 | match x{ | ^ pattern `Ok(_)` not covered error: aborting due to previous error
  4. What??? $ rustc --explain E0004 This error indicates that the

    compiler cannot guarantee a matching pattern for one or more possible inputs to a match expression. Guaranteed matches are required in order to assign values to match expressions, or alternatively, determine the flow of execution. Erroneous code example: ``` enum Terminator { HastaLaVistaBaby, TalkToMyHand, } let x = Terminator::HastaLaVistaBaby; match x { // error: non-exhaustive patterns: `HastaLaVistaBaby` not covered Terminator::TalkToMyHand => {} } ``` If you encounter this error you must alter your patterns so that every possible value of the input type is matched. For types with a small number of variants (like enums) you should probably cover all cases explicitly. Alternatively, the
  5. No more NullPointerException fn main() { let value: Option<i32> =

    None; println!("{}", value.unwrap()); } thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', ../src/libcore/option.rs:326 note: Run with `RUST_BACKTRACE=1` for a backtrace. You know exactly where panic can occur
  6. Other ways to deal with NPE match value { Some(x)

    => println!("{}", x), None => println!("Nothing"), } value.unwrap_or(5) Pattern matching Use a default value Some(String::from("Barcamp")).map(|s| s.len()); Apply a function
  7. Or do it in JavaScript style Some(x).and(Some(50)) Some(x).or(Some(50)) x &&

    50 === 50 x || 50 === x None.and(Some(50)) null && 50 === null None.or(Some(50)) null || 50 === 50
  8. Traits • Rust have no class • But we have

    struct and traits • Traits can require other traits to be implemented first
  9. Traits • Then we implement the trait impl Shop<Car> for

    CarShop { fn buy(&self) -> Car { Car{} } }
  10. Traits • Traits can be implemented everywhere • You can

    add a trait implementation to everything ◦ Enum ◦ Struct ◦ Primitive types ◦ Other module's enum and struct • Trait must be imported before you can use it
  11. Rust is safe Rule of Rust: 1. A resource have

    one owner let x = vec![1]; let y = x; println!("{}", x.len());
  12. Rust is safe error[E0382]: use of moved value: `x` -->

    <anon>:4:20 | 3 | let y = x; | - value moved here 4 | println!("{}", x.len()); | ^ value used here after move <std macros>:2:27: 2:58 note: in this expansion of format_args! <std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>) <anon>:4:5: 4:29 note: in this expansion of println! (defined in <std macros>) | = note: move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait error: aborting due to previous error
  13. Rust is safe Rule of Rust: 1. A resource have

    one owner 2. Others can borrow it from the owner but the reference must last no longer than the owner let y; if true { let x = vec![1]; y = &x; } println!("{}", y.len());
  14. Rust is safe error: `x` does not live long enough

    --> <anon>:5:14 5 | y = &x; | ^ note: reference must be valid for the block suffix following statement 0 at 2:10... --> <anon>:2:11 2 | let y; | ^ note: ...but borrowed value is only valid for the block suffix following statement 0 at 4:24 --> <anon>:4:25 4 | let x = vec![1]; | ^
  15. Rust is safe Rule of Rust: 1. A resource have

    one owner 2. Others can borrow it from the owner but the borrow must last no longer than the owner 3. Only one mutable reference let mut x = vec![1]; x.push(5); let y = &x; y.push(6);
  16. Rust is safe error: cannot borrow immutable borrowed content `*y`

    as mutable --> <anon>:6:5 | 6 | y.push(6); | ^ error: aborting due to previous error
  17. Rust is safe Rule of Rust: 1. A resource have

    one owner 2. Others can borrow it from the owner but the borrow must last no longer than the owner 3. Only one mutable reference let mut x = vec![1]; x.push(5); let y = &mut x; x.push(6);
  18. Rust is safe error[E0499]: cannot borrow `x` as mutable more

    than once at a time --> <anon>:5:5 | 4 | let y = &mut x; | - first mutable borrow occurs here 5 | x.push(6); | ^ second mutable borrow occurs here 6 | } | - first borrow ends here
  19. Rust is safe What does this prevent? • Use after

    free: Rust use RAII plus lifetime check • Dangling pointers: Prevented by lifetime check
  20. Rust is concurrent • Rust shines in concurrent programming •

    Rust provides ◦ Thread ◦ Reference counted type ◦ Mutex ◦ RwLock ◦ Atomic types ◦ Go-style message passing channel
  21. Rust is concurrent • Thread safely use std::thread; fn main()

    { let mut x = Box::new(5); // allocate 5 in the heap let child = thread::spawn(|| *x += 1); *x += 1; child.join().unwrap(); println!("{}", x); }
  22. Rust is concurrent error[E0373]: closure may outlive the current function,

    but it borrows `x`, which is owned by the current function --> <anon>:5:31 | 5 | let child = thread::spawn(|| *x += 1); | ^^ - `x` is borrowed here | | | may outlive borrowed value `x` | help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword, as shown: | let child = thread::spawn(move || *x += 1);
  23. Rust is concurrent use std::thread; fn main() { let mut

    x = Box::new(5); // allocate 5 in the heap let child = thread::spawn(move || *x += 1); *x += 1; child.join().unwrap(); println!("{}", x); }
  24. Rust is concurrent error[E0382]: use of moved value: `*x` -->

    <anon>:6:5 | 5 | let child = thread::spawn(move || *x += 1); | ------- value moved (into closure) here 6 | *x += 1; | ^^^^^^^ value used here after move | = note: move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
  25. Rust is concurrent use std::thread; use std::sync::Arc; use std::sync::Mutex; fn

    main() { let x = Arc::new(Mutex::new(5)); let y = x.clone(); let child = thread::spawn(move || { *(y.lock().unwrap()) += 1; }); {*(x.lock().unwrap()) += 1;} child.join().unwrap(); println!("{}", *(x.lock().unwrap())); }
  26. Rust is concurrent use std::thread; use std::sync::Arc; use std::sync::Mutex; fn

    main() { let x = Arc::new(Mutex::new(5)); let y = x.clone(); let child = thread::spawn(move || { *(y.lock().unwrap()) += 1; }); {*(x.lock().unwrap()) += 1;} child.join().unwrap(); println!("{}", *(x.lock().unwrap())); }
  27. Rust is concurrent use std::thread; use std::sync::Arc; use std::sync::Mutex; fn

    main() { let x = Arc::new(Mutex::new(5)); let y = x.clone(); let child = thread::spawn(move || { *(y.lock().unwrap()) += 1; }); {*(x.lock().unwrap()) += 1;} child.join().unwrap(); println!("{}", *(x.lock().unwrap())); }
  28. Rust is fast • Borrow check is done during compile

    time • Generic can be dispatched statically (like C++ templates) ◦ Rust has zero-cost abstraction as its core value: pay for only what you use • Rust have no garbage collection • Rust allocate all local variable on the stack