Rust

08.05.2015

Serdar Doğruyol

Lead Backend Developer at Protel, Rubyist, Rustacean

Twitter: @sdogruyol

Github: www.github.com/sdogruyol

Blog: www.serdardogruyol.com

Rust is a systems programming language that runs blazingly fast, prevents almost all crashes, and eliminates data races. 

Tarihçe

  • 2009 yılında Graydon Hoare tarafından geliştirilmeye başlandı.
  • 2010 yılında Mozilla projeye sponsor oldu
  • Tamamen açık kaynak olarak geliştiriliyor ve geliştiricilerin çoğu topluluktan.
  • Cyclone, Haskell, Erlang, Ruby, ML vb. dillerden etkilenilerek geliştirildi.

Neden?

Hızlı
Güvenli
Pratik

Düşük Seviye

Performans

Benchmark

Rust: 69941

Jruby: 27441

Ruby (MRI): 9612

OS,Kernel

C / C++

   

  • zero-cost abstractions
  • move semantics
  • guaranteed memory safety
  • threads without data races
  • trait-based generics
  • pattern matching
  • type inference
  • efficient C bindings
  • cross-platform

15 Mayıs

1.0.0

Kod zamanı!

Hello World

fn main() {
    println!("Hello, world!");
}
rustc hello.rs
./main # or main.exe for windows

Çalıştıralım

Değişkenler

fn main() {
    let x = 5; // Type inference
    let y: i32 = 10; // Type specified
    let (a, b) = (1, 2); // Pattern Matching
}

Değişkenler default olarak immutable

fn main() {
    let x = 5;
    x = 10;
}
error: re-assignment of immutable variable `x`
     x = 10;
     ^~~~~~~

Derlemeye çalıştığınızda compile time hatası alırsınız

Mutable yapmak için

fn main() {
    let mut x = 5;
    x = 10;
}

Fonksiyonlar

fn main() {
}

main fonksiyonu her Rust programında var

fn print_sum(x: i32, y: i32) {
    println!("sum is: {}", x + y);
}
fn add_one(x: i32) -> i32 {
    x + 1
}

Fonksiyon parametlerinde tip olmak zorunda

Dönüş tipi -> şeklinde belirtilir

If

let x = 5;

if x == 5 {
    println!("x is five!");
} else {
    println!("x is not five :(");
}
let x = 5;

let y = if x == 5 {
    10
} else {
    15
};

Tipik bir programlama dilinde olduğu gibi

Hatta şu şekilde yazılabilir.

let x = 5;

let y = if x == 5 { 10 } else { 15 }; // y: i32

Aslında If bir expression ( Ruby gibi)

For

for x in 0..10 {
    println!("{}", x); // x: i32
}
for var in expression {
    code
}

Dinamik bir programlama diline benziyor.

Şart bir expression olabilir

While

let mut x = 5; // mut x: u32
let mut done = false; // mut done: bool

while !done {
    x += x - 3;

    println!("{}", x);

    if x % 5 == 0 {
        done = true;
    }
}
let mut x = 5;

loop {
    x += x - 3;

    println!("{}", x);

    if x % 5 == 0 { break; }
}

Struct

struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let origin = Point { x: 0, y: 0 }; // origin: Point

    println!("The origin is at ({}, {})", origin.x, origin.y);
}

C'deki ile benzer.

Kompleks veri yapılarını Struct sayesinde modelliyoruz.

Ownership

{
    int *x = malloc(sizeof(int));

    // we can now do stuff with our handle x
    *x = 5;

    free(x);
}
{
    let x = Box::new(5);
}

Rust

C

Rust bizim için memory alloc ve dealloc işini hallediyor. Dolayısı ile unutma ihtimalimiz sıfır.

Ownership

fn main() {
    let x = Box::new(5);

    add_one(x);

    println!("{}", x);
}

fn add_one(mut num: Box<i32>) {
    *num += 1;
}
error: use of moved value: `x`
   println!("{}", x);
                  ^

Peki nasıl çözeceğiz?

Compiler derlememize izin vermiyor.

Ownership

fn main() {
    let x = Box::new(5);

    let y = add_one(x);

    println!("{}", y);
}

fn add_one(mut num: Box<i32>) -> Box<i32> {
    *num += 1;

    num
}

Ownership geri veriliyor

Borrowing

fn main() {
    let mut x = 5;

    add_one(&mut x);

    println!("{}", x);
}

fn add_one(num: &mut i32) {
    *num += 1;
}

Box oluşturulmadan değer fonksiyona ödünç veriliyor ve çalışma bittikten sonra geri veriliyor.

Lifetime

  1. I acquire a handle to some kind of resource.
  2. I lend you a reference to the resource.
  3. I decide I'm done with the resource, and deallocate it, while you still have your reference.
  4. You decide to use the resource.

SEGFAULT

Lifetime

fn add_one(num: &mut i32) {
    *num += 1;
}
fn add_one<'a>(num: &'a mut i32) {
    *num += 1;
}

Lifetime elision

struct Foo<'a> {
    x: &'a i32,
}

fn main() {
    let y = &5; 
    let f = Foo { x: y };

    println!("{}", f.x);
}

Struct with Lifetime

Lifetime

struct Foo<'a> {
    x: &'a i32,
}

fn main() {
    let x;                    // -+ x goes into scope
                              //  |
    {                         //  |
        let y = &5;           // ---+ y goes into scope
        let f = Foo { x: y }; // ---+ f goes into scope
        x = &f.x;             //  | | error here
    }                         // ---+ f and y go out of scope
                              //  |
    println!("{}", x);        //  |
} 

Compile time error

Lifetime Ellision

  • Each elided lifetime in a function's arguments becomes a distinct lifetime parameter.

  • If there is exactly one input lifetime, elided or not, that lifetime is assigned to all elided lifetimes in the return values of that function.

  • If there are multiple input lifetimes, but one of them is &self or &mut self, the lifetime of self is assigned to all elided output lifetimes.

Shared Ownership

struct Car {
    name: String,
}

struct Wheel {
    size: i32,
    owner: Car,
}

fn main() {
    let car = Car { name: "DeLorean".to_string() };

    for _ in 0..4 {
        Wheel { size: 360, owner: car };
    }
}
error: use of moved value: `car`
    Wheel { size: 360, owner: car };
                              ^~~
note: `car` moved here because it has type `Car`, which is non-copyable
    Wheel { size: 360, owner: car };

Shared Ownership

use std::rc::Rc;

struct Car {
    name: String,
}

struct Wheel {
    size: i32,
    owner: Rc<Car>,
}

fn main() {
    let car = Car { name: "DeLorean".to_string() };

    let car_owner = Rc::new(car);

    for _ in 0..4 {
        Wheel { size: 360, owner: car_owner.clone() };
    }
}

..ve daha fazlası

Lifetime

Generics

Traits

Macros

Unsafe

Inline Assembly

Kaynaklar

Sorular?

Teşekkürler

@sdogruyol

Rust

By Serdar Dogruyol