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

Intro to Rust Programming Language

Intro to Rust Programming Language

Rust is a systems programming language focused on three goals: safety, speed, and concurrency. In this talk, you will get a high-level overview of the language, its syntax and semantics, and some code examples.

Rida Al Barazi

February 25, 2016
Tweet

More Decks by Rida Al Barazi

Other Decks in Programming

Transcript

  1. Rust is a systems programming language focused on three goals:

    safety, speed, and concurrency Source: rust-lang.org What is rust
  2. Why and when? • Embedding in other languages • Writing

    low-level code • Small programs with specific space and time requirements
  3. Installation 1.6.0 is the latest major release Came out on

    January 21, 2016 Install your system package from: https://www.rust-lang.org/downloads.html
  4. dependencies versions [dependencies] rand="0.3.0" # This a shorthand for ^0.3.0

    rand=“^0.3.0" # Use any release compatible with this specific version. Semantic Versioning rand=“=0.3.0" # Use only 0.3.0 exactly rand=“*" # Use latest version
  5. dependencies versions ! cargo build Downloading libc v0.2.7 Downloading rand

    v0.3.14 Compiling libc v0.2.7 Compiling rand v0.3.14 Compiling hello_world v0.1.0 (file:/// home/yourname/projects/hello_world)
  6. variable binding let x = 5; // Type inferred as

    i32 let x: i32 = 5; // Explicitly bind with the type i32
  7. variable binding let x = 5; // Type inferred as

    i32 let x: i32 = 5; // Explicitly bound with the type i32 let (x, y) = (1, 2); // Pattern matching
  8. variable binding let x = 5; // Type inferred as

    i32 let x: i32 = 5; // Explicitly bound with the type i32 let (x, y) = (1, 2); // Pattern matching y = 3; // Raises an error. Immutable by default let mut y = 3; // y is now mutable and is bound to 3
  9. scoping and shadowing let x: i32 = 8; { println!("{}",

    x); // Prints "8" let x = 12; println!("{}", x); // Prints "12" } println!("{}", x); // Prints "8" let x = 42; println!("{}", x); // Prints "42"
  10. numeric types let x = 42; // x has type

    i32 let y = 1.0; // y has type f64
  11. arrays let a = [1, 2, 3]; // a: [i32;

    3] let mut m = [1, 2, 3]; // m: [i32; 3]
  12. arrays let a = [1, 2, 3]; // a: [i32;

    3] let mut m = [1, 2, 3]; // m: [i32; 3] // Arrays have type [T; N] let a = [0; 20]; // a: [i32; 20]
  13. arrays let a = [1, 2, 3]; // a: [i32;

    3] let mut m = [1, 2, 3]; // m: [i32; 3] // Arrays have type [T; N] let a = [0; 20]; // a: [i32; 20] // Get the length println!("a has {} elements", a.len()); //> a has 20 elements
  14. arrays let a = [1, 2, 3]; // a: [i32;

    3] let mut m = [1, 2, 3]; // m: [i32; 3] // Arrays have type [T; N] let a = [0; 20]; // a: [i32; 20] // The `len` method yields the size of the array println!("a has {} elements", a.len()); //> a has 20 elements let names = ["Graydon", "Brian", "Niko"]; // names: [&str; 3] println!("The second name is: {}", names[1]); //> The second name is: Brian
  15. tuples let tuple = (1, "hello", "world"); // x: (i32,

    &str, &str) // Indexing let v = tuple.1; println!("v is {}", v); // v is hello
  16. tuples let tuple = (1, "hello", "world"); // x: (i32,

    &str, &str) // Indexing let v = tuple.1; println!("v is {}", v); // v is hello // Deconstructing let (x, y, z) = (1, 2, 3); println!("x is {}", x); // x is 1
  17. structs struct Point { x: i32, y: i32, } fn

    main() { let mut point = Point { x: 0, y: 0 }; point.x = 5; println!("The point is at ({}, {})", point.x, point.y); let point = point; // this new binding can’t change now point.y = 6; // this causes an error }
  18. structs // Tuple Struct struct Inches(i32); let length = Inches(10);

    let Inches(integer_length) = length; println!("length is {} inches", integer_length); //> length is 10 inches // Unit-like Struct struct Electron; let x = Electron; // Empty tuple: ()
  19. enums enum Message { // An `enum` may either be

    `unit-like`, Quit, // like tuple structs, ChangeColor(i32, i32, i32), // or like structures. Move { x: i32, y: i32 }, Write(String), } let m: Message = Message::Write("Hello, world".to_string());
  20. operators // Integer addition println!("1 + 2 = {}", 1

    + 2); // Integer subtraction println!("1 - 2 = {}", 1 - 2);
  21. operators // Integer addition println!("1 + 2 = {}", 1

    + 2); // Integer subtraction println!("1 - 2 = {}", 1 - 2); // Short-circuiting boolean logic println!("true AND false is {}", true && false); println!("true OR false is {}", true || false); println!("NOT true is {}", !true);
  22. operators // Integer addition println!("1 + 2 = {}", 1

    + 2); // Integer subtraction println!("1 - 2 = {}", 1 - 2); // Short-circuiting boolean logic println!("true AND false is {}", true && false); println!("true OR false is {}", true || false); println!("NOT true is {}", !true); // Use underscores to improve readability! println!("One million is written as {}", 1_000_000);
  23. GENERIC FUNCTIONS fn takes_anything<T>(x: T) { // do something with

    x } fn takes_two_things<T, U>(x: T, y: U) { // ... }
  24. GENERIC STRUCTS struct Point<T> { x: T, y: T, }

    let int_origin = Point { x: 0, y: 0 }; let float_origin = Point { x: 0.0, y: 0.0 };
  25. vectors // The `vec!` macro can be used to initialize

    a vector let mut v = vec![1, 2, 3, 4, 5]; // v: Vec<i32>
  26. vectors // The `vec!` macro can be used to initialize

    a vector let mut v = vec![1, 2, 3, 4, 5]; // v: Vec<i32> v.push(4); // Insert new element at the end of the vector
  27. vectors // The `vec!` macro can be used to initialize

    a vector let mut v = vec![1, 2, 3, 4, 5]; // v: Vec<i32> v.push(4); // Insert new element at the end of the vector // The `len` method yields the current size of the vector println!("Vector size: {}", v.len()); //> Vector size: 6 println!("Sixth element: {}", v[5]); //> Sixth element: 4
  28. strings // &str let greeting = "Hello there."; // greeting:

    &'static str = &str // String let mut s = "Hello".to_string(); // mut s: String println!("{}", s); //> "Hello" s.push_str(", world."); println!("{}", s); //> "Hello, World"
  29. strings • They are a sequence of UTF-8 bytes. •

    &str is a string slice. • String is a growable string. • "Hello there" is statically allocated string literal, typed string slice. • str.to_string() creates a new String, which is expensive. • string.as_slice() returns a view of the string, which is cheap.
  30. if let x = 5; if x == 5 {

    println!("x is five!"); } else if x == 6 { println!("x is six!"); } else { println!("x is not five or six :("); }
  31. if let x = 5; if x == 5 {

    println!("x is five!"); } else if x == 6 { println!("x is six!"); } else { println!("x is not five or six :("); } let y = if x == 5 { 10 } else { 15 }; // y: i32
  32. loops loop { println!("Loop forever!"); } let mut x =

    5; loop { x += x - 3; println!("{}", x); if x % 5 == 0 { break; } }
  33. loops let mut x = 5; // mut x: i32

    let mut done = false; // mut done: bool while !done { x += x - 3; println!("{}", x); if x % 5 == 0 { done = true; } }
  34. loops for x in 0..10 { println!("{}", x); // x:

    i32 } for (idx,j) in (5..10).enumerate() { println!("idx = {} and j = {}", i, j); } // idx = 0 and j = 5 // idx = 1 and j = 6 // idx = 2 and j = 7 // idx = 3 and j = 8 // idx = 4 and j = 9
  35. loops 'outer: for x in 0..10 { 'inner: for y

    in 0..10 { if x % 2 == 0 { continue 'outer; } // continues the loop over x if y % 2 == 0 { continue 'inner; } // continues the loop over y println!("x: {}, y: {}", x, y); } }
  36. match let x = 5; match x { 1 =>

    println!("one"), 2 => println!("two"), 3 => println!("three"), 4 => println!("four"), 5 => println!("five"), _ => println!("something else"), }
  37. match enum Message { Quit, ChangeColor(i32, i32, i32), Move {

    x: i32, y: i32 }, Write(String), } fn quit() { /* ... */ } fn change_color(r: i32, g: i32, b: i32) { /* ... */ } fn move_cursor(x: i32, y: i32) { /* ... */ } fn process_message(msg: Message) { match msg { Message::Quit => quit(), Message::ChangeColor(r, g, b) => change_color(r, g, b), Message::Move { x: x, y: y } => move_cursor(x, y), Message::Write(s) => println!("{}", s), }; }
  38. functions fn main() { let x = 5; print_sum(add_one(x), 6);

    // sum is: 12 } fn print_sum(x: i32, y: i32) { println!("sum is: {}", x + y); } fn add_one(x: i32) -> i32 { x + 1 // note that there's no semicolon = `return` }
  39. methods To call a method on an struct instance like:

    `circle.area()`, you have to use `impl` and declare functions that accept a variant of `self`, `&self`, or `&mut self` as their first parameter.
  40. methods struct Circle { x: f64, y: f64, radius: f64,

    } impl Circle { fn area(&self) -> f64 { std::f64::consts::PI * (self.radius * self.radius) } } fn main() { let c = Circle { x: 0.0, y: 0.0, radius: 2.0 }; println!("{}", c.area()); }
  41. methods struct Circle { x: f64, y: f64, radius: f64,

    } impl Circle { // new is an associated function fn new(x: f64, y: f64, radius: f64) -> Circle { Circle { x: x, y: y, radius: radius, } } } fn main() { let c = Circle::new(0.0, 0.0, 2.0);
  42. Methods Rust doesn’t have method overloading, named arguments, or variable

    arguments. Instead you would use the Builder Pattern
  43. Methods struct Circle { x: f64, y: f64, radius: f64,

    } impl Circle { fn area(&self) -> f64 { std::f64::consts::PI * (self.radius * self.radius) } } struct CircleBuilder { x: f64, y: f64, radius: f64, }
  44. Methods impl CircleBuilder { fn new() -> CircleBuilder { CircleBuilder

    { x: 0.0, y: 0.0, radius: 1.0, } } fn x(&mut self, coordinate: f64) -> &mut CircleBuilder { self.x = coordinate; self } fn y(&mut self, coordinate: f64) -> &mut CircleBuilder { self.y = coordinate; self } fn radius(&mut self, radius: f64) -> &mut CircleBuilder { self.radius = radius; self } fn finalize(&self) -> Circle { Circle { x: self.x, y: self.y, radius: self.radius } } }
  45. Methods fn main() { let c = CircleBuilder::new() .x(1.0) .y(2.0)

    .radius(2.0) .finalize(); println!("area: {}", c.area()); println!("x: {}", c.x); println!("y: {}", c.y); }
  46. traits Similar to methods you can add functionality to structs

    by specifying what Traits a struct implements.
  47. traits struct Circle { x: f64, y: f64, radius: f64,

    } trait HasArea { fn area(&self) -> f64; } impl HasArea for Circle { fn area(&self) -> f64 { std::f64::consts::PI * (self.radius * self.radius) } }
  48. ownership let v = vec![1, 2, 3]; let v2 =

    v; println!("v[0] is: {}", v[0]); // error: use of moved value: `v`
  49. ownership let v = 1; let v2 = v; println!("v

    is: {}", v); // v is i32 which is a primitive. // All primitive types implement the `Copy` trait
  50. references and borrowing let v = vec![1, 2, 3]; let

    v2 = &v; println!("v[0] is: {}", v[0]); // v[0] is: 1 println!("v2[1] is: {}", v2[1]); // v2[1] is: 2
  51. references and borrowing let mut x = 5; { let

    y = &mut x; *y += 1; } println!("{}", x);
  52. Syntax and style • Indentation is 4 spaces (no tabs)

    • variable names are underscore lowercased • structs begin with a capital letter and are camel cased
  53. resources • The Rust Programming Language (online book) • https://doc.rust-lang.org/stable/book/

    • Rust by Example • http://rustbyexample.com/index.html • Rust Cheat Sheet • http://clchiou.github.io/2015-01-09/rust- cheat-sheet/ • ConFreaks Rust Talks • http://confreaks.tv/tags/155