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

Rust Language

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Rust Language

Barcamp Bangkok 2016

Avatar for Manatsawin Hanmongkolchai

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