geri

std::convert dostumuzdur

05/07/2020

Bugün bahsedeceğim konuya Pascal Hertleif, Writing Idiomatic Libraries in Rust konuşması ile ilham verdi. Youtube’da ciddi miktarda Rust konulu içerik olduğunu farkettiğimden beri vakit buldukça izliyorum ve daha sonra yazmak üzere not alıyorum. Bu yüzden birçok yazımın kaynağı muhtemelen bu videolar olacak.

std::convert modülündeki traitler bir tipten başka bir tipe dönüşüme olanak sağlıyorlar. Örneğin From trait ile bir değerden başka bir değere dönüşüm yapabiliyoruz. Hem de bu traiti gerçeklediğimizde Into trait de bizim için otomatik olarak gerçeklenmiş oluyor. Bu şekilde anlatınca hiçbir şey ifade etmemiş olabilir. Küçük bir örnekle açıklamaya çalışayım.

Point isminde bir veri yapımız olsun, bir noktanın x ve y koordinatlarını tutsun.

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

Yeni bir nokta tanımlamak için normalde aşağıdaki kodu kullanırız.

let p = Point { x: -1, y: 1 };

Diyelim ki elimizde noktanın koordinatlarını tutan iki elemanlı bir dizi var ve bu diziden Point tipinde bir değer yaratmak istiyoruz. Bu durumda From traitini gerçeklememiz yeterli oluyor.

impl From<[i32; 2]> for Point {
    fn from(coords: [i32; 2]) -> Self {
        Point { x: coords[0], y: coords[1] }
    }
}

Rust’in tip sistemi [i32; 2] şeklinde 2 elemanlı integer dizi tanımına izin veriyor. Harika değil mi? Artık iki elemanlı bir diziden aşağıdaki şekilde bir nokta yaratabiliriz.

let p = Point::from([-1, 1]);

From traitini gerçekleyince Into traitinin de otomatik olarak gerçeklendiğinden bahsetmiştim. Böylece aşağıdaki şekilde de bir nokta yaratabiliyoruz. Bence bu hali gerçekten çok temiz oldu.

let p: Point = [-1, 1].into();

Benzer dönüşümleri FromStr ile de yapabiliyoruz. Bu traiti implement edince string üzerinde parse metodunu çağırarak istediğimiz tipi elde edebiliyoruz. Örneğin renk belirten bir enum tanımlayalım.

enum Color {
    Red,
    Green,
    Blue,
}

Color için FromStr traitini gerçeklersek “blue”.parse::<Color>() kodu ile stringden Color tipine dönüşüm mümkün oluyor.

impl FromStr for Color {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "red" => Ok(Color::Red),
            "green" => Ok(Color::Green),
            "blue" => Ok(Color::Blue),
            _ => Err(())
        }
    }
}

Parse işlemi elbette bazen başarısız olabilir. Ben bu örneği basit tutmak adına başarısızlık durumu için düzgün bir hata dönmek yerine unit adı verilen () döndüm.

Yarın başka bir konu ile görüşmek üzere👋

Follow me on Twitter