Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Veri Türleri

Rust’taki her değer belirli bir veri türüne (data type) sahiptir; bu bilgi Rust’a ne tür bir veriyle çalıştığını ve o veriyi nasıl işleyeceğini söyler. Bu bölümde iki veri türü alt kümesini inceleyeceğiz: skaler ve bileşik türler.

Rust’ın statik türlemeli (statically typed) bir dil olduğunu unutmayın; yani derleyicinin tüm değişkenlerin türlerini derleme zamanında bilmesi gerekir. Derleyici çoğu durumda değere ve onu nasıl kullandığımıza bakarak hangi türü istediğimizi kendiliğinden çıkarabilir. Ancak Bölüm 2’deki “Tahmini Gizli Sayıyla Karşılaştırmak” kısmında parse metodunu kullanarak bir String değerini sayısal bir türe dönüştürdüğümüzde olduğu gibi pek çok farklı türün mümkün olduğu durumlarda, aşağıdaki gibi açık bir tür bildirimi (type annotation) eklememiz gerekir:

#![allow(unused)]
fn main() {
let tahmin: u32 = "42".parse().expect("Bir sayı değil!");
}

Yukarıdaki kodda gösterilen : u32 tür bildirimini eklemezsek Rust aşağıdaki hatayı görüntüler; bu mesaj, derleyicinin hangi türü kullanmak istediğimizi anlamak için bizden daha fazla bilgiye ihtiyaç duyduğunu gösterir:

$ cargo build
   Compiling no_type_annotations v0.1.0 (file:///projects/no_type_annotations)
error[E0284]: type annotations needed
 --> src/main.rs:2:9
  |
2 |     let tahmin = "42".parse().expect("Bir sayı değil!");
  |         ^^^^^^        ----- type must be known at this point
  |
  = note: cannot satisfy `<_ as FromStr>::Err == _`
  = note: the type must also implement `FromStr`
note: required by a bound in `core::str::<impl str>::parse`
 --> /rustc/58cf8f9c35b355199727627d07ae34a4e2846d67/library/core/src/str/mod.rs:2782:4
help: consider giving `tahmin` an explicit type
  |
2 |     let tahmin: /* Type */ = "42".parse().expect("Bir sayı değil!");
  |               ++++++++++++

For more information about this error, try `rustc --explain E0284`.
error: could not compile `no_type_annotations` (bin "no_type_annotations") due to 1 previous error

Not: Derleyicinin ürettiği error[E0284]: type annotations needed (tür bildirimi gerekiyor) hatası, "42".parse() çağrısının u32, i32, f64 gibi metinden dönüştürülebilen (FromStr trait’ini uygulayan) pek çok farklı türe karşılık gelebileceğini ve tek başına yeterli ipucu bulunmadığını belirtir. Derleyici hatanın altındaki help satırında, değişken adının yanına : /* Type */ biçiminde açık bir tür yazmamızı önerir.

Diğer veri türleri için de farklı tür bildirimleri göreceksiniz.

Skaler Türler

Skaler (scalar) bir tür tek bir değeri temsil eder. Rust’ta dört temel skaler tür bulunur: tam sayılar, kayan noktalı sayılar, Boolean’lar ve karakterler. Bu türleri diğer programlama dillerinden de tanıyor olabilirsiniz. Gelin Rust’ta nasıl çalıştıklarına yakından bakalım.

Tam Sayı Türleri

Tam sayı (integer), kesirli bileşeni olmayan bir sayıdır. Bölüm 2’de tam sayı türlerinden biri olan u32 türünü kullanmıştık. Bu tür bildirimi, ilişkili değerin bellekte 32 bitlik alan kaplayan işaretsiz (unsigned) bir tam sayı olması gerektiğini belirtir (işaretli (signed) tam sayı türleri u yerine i harfiyle başlar). Tablo 3-1, Rust’taki yerleşik tam sayı türlerini gösterir. Bir tam sayı değerinin türünü bildirmek için bu varyantlardan herhangi birini kullanabiliriz.

Tablo 3-1: Rust’taki Tam Sayı Türleri

Uzunlukİşaretliİşaretsiz
8 biti8u8
16 biti16u16
32 biti32u32
64 biti64u64
128 biti128u128
Mimariye bağlıisizeusize

Her tam sayı türünün belirli bir boyutu ve değer aralığı vardır. İşaretli türler negatif sayıları, sıfırı ve pozitif sayıları; işaretsiz türler ise sıfırı ve pozitif sayıları temsil eder. Buradaki “işaret”, sayının kaynak kodda mutlaka + veya - ile yazılması gerektiğini değil, türün negatif değerleri temsil edip edemediğini belirtir. İşaretli sayılar bellekte ikiye tümleyen (two’s complement) temsili kullanılarak saklanır.

Her işaretli varyant, n ilgili varyantın kullandığı bit sayısı olmak üzere, −(2n − 1) ile 2n − 1 − 1 (sınırlar dahil) aralığındaki sayıları saklayabilir. Dolayısıyla bir i8, −(27) ile 27 − 1 aralığındaki, yani −128 ile 127 arasındaki sayıları tutabilir. İşaretsiz varyantlar ise 0 ile 2n − 1 aralığındaki sayıları saklayabilir; örneğin bir u8, 0 ile 28 − 1 aralığındaki, yani 0 ile 255 arasındaki sayıları tutabilir.

Ek olarak isize ve usize türlerinin boyutu, programınızın çalıştığı bilgisayarın mimarisine bağlıdır: 64 bitlik bir mimaride 64 bit, 32 bitlik bir mimaride ise 32 bittir.

Tam sayı sabit değerlerini (integer literals) Tablo 3-2’de gösterilen biçimlerden herhangi biriyle yazabilirsiniz. Birden fazla sayısal türe uyabilen sayı sabit değerlerinin, türü açıkça belirlemek amacıyla 57u8 örneğinde olduğu gibi bir tür son eki (type suffix) alabileceğine dikkat edin. Ayrıca sayı sabit değerlerinde okunabilirliği artırmak için görsel ayırıcı olarak _ karakteri kullanılabilir; örneğin 1_000 yazmak, 1000 yazmakla birebir aynı değere karşılık gelir.

Tablo 3-2: Rust’taki Tam Sayı Sabit Değerleri

Sayı sabit değerleriÖrnek
Onluk98_222
On altılık0xff
Sekizlik0o77
İkilik0b1111_0000
Bayt (yalnızca u8)b'A'

Peki hangi tam sayı türünü kullanacağınızı nasıl bileceksiniz? Emin değilseniz Rust’ın varsayılanları genellikle iyi bir başlangıç noktasıdır: Tam sayı türleri varsayılan olarak i32 kabul edilir. isize veya usize kullanacağınız başlıca durum ise bir koleksiyonu indekslemektir.

Tam Sayı Taşması

Diyelim ki 0 ile 255 arasında değerler tutabilen u8 türünde bir değişkeniniz var. Bu değişkenin değerini bu aralığın dışına çıkaracak bir işlem yaparsanız (örneğin 255 olan değerini 1 artırarak 256 yapmaya çalışırsanız) tam sayı taşması (integer overflow) meydana gelir ve bu durum derleme moduna göre iki farklı davranıştan biriyle sonuçlanır. (Doğrudan let x: u8 = 256; gibi aralık dışı bir sabit değer yazmak ise taşma sayılmaz; derleyici böyle bir satırı daha baştan literal out of range for `u8` hatasıyla reddeder.) Hata ayıklama (debug) modunda derleme yaptığınızda Rust, tam sayı taşmasını yakalayan kontroller ekler ve çalışma zamanında taşma gerçekleşirse programınızın panik yapmasına neden olur. Panikleme (panicking), normal kontrol akışını kesen bir hata mekanizmasıdır; her hata sonucu veya başarısız çıkış bir panik değildir. Panikleri Bölüm 9’daki “panic! ile Kurtarılamayan Hatalar” kısmında daha derinlemesine inceleyeceğiz.

--release bayrağıyla yayın (release) modunda derleme yaptığınızda ise Rust, varsayılan olarak bu tam sayı taşması kontrollerini eklemez. Bu davranış profildeki overflow-checks ayarıyla değiştirilebilir; burada varsayılan profilleri karşılaştırıyoruz. Kontroller kapalıyken taşma meydana gelirse Rust ikiye tümleyen sarması (two’s complement wrapping) uygular. Kısacası, türün tutabileceği en büyük değeri aşan sayılar başa dönerek türün alabileceği en küçük değere “sarılır”. Bir u8 için 256 değeri 0, 257 değeri 1 olur ve bu şekilde devam eder. Program paniklemez ancak değişken büyük olasılıkla beklemediğiniz bir değer alır. Tam sayı taşmasının bu sarma davranışına güvenerek kod yazmak hata olarak kabul edilir.

Taşma olasılığını açıkça ele almak istediğinizde, standart kütüphanenin ilkel sayısal türler için sunduğu şu metot ailelerini kullanabilirsiniz:

  • wrapping_* metotlarıyla tüm derleme modlarında sarma işlemi yapmak (örneğin 255u8.wrapping_add(1) çağrısı 0 döndürür).
  • checked_* metotlarıyla taşma durumunda None değeri döndürmek (örneğin 255u8.checked_add(1) çağrısı None döndürür).
  • overflowing_* metotlarıyla hem sarmalanmış değeri hem de taşma olup olmadığını belirten bir bool değerini birlikte döndürmek (örneğin 255u8.overflowing_add(1) çağrısı (0, true) döndürür).
  • saturating_* metotlarıyla değerin alt veya üst sınırında doygunluğa ulaşarak sabitlenmesini (saturate) sağlamak (örneğin 255u8.saturating_add(1) çağrısı 255 döndürür).

Kayan Noktalı Türler

Rust’ta ayrıca ondalık basamak içeren kayan noktalı sayılar (floating-point numbers) için iki ilkel (primitive) tür bulunur. Rust’ın kayan noktalı türleri sırasıyla 32 bit ve 64 bit boyutundaki f32 ve f64’tür. Varsayılan tür f64’tür; çünkü modern işlemcilerde f32 ile neredeyse aynı hızda çalışırken daha yüksek duyarlılık (precision) sunar. Tüm kayan noktalı türler işaretlidir.

İşte kayan noktalı sayıların kullanımını gösteren bir örnek:

Dosya adı: src/main.rs

fn main() {
    let x = 2.0; // f64

    let y: f32 = 3.0; // f32
}

Kayan noktalı sayılar IEEE-754 standardına göre temsil edilir. f32 türü tek duyarlıklı (single-precision), f64 türü ise çift duyarlıklı (double-precision) bir kayan noktalı sayıdır.

Sayısal İşlemler

Rust, tüm sayı türleri için bekleyeceğiniz temel matematiksel işlemleri destekler: toplama, çıkarma, çarpma, bölme ve kalan (mod alma). Tam sayı bölmesi, sonucu sıfıra doğru en yakın tam sayıya yuvarlar; yani kesirli kısmı atar (truncate). Aşağıdaki kod, her bir sayısal işlemi bir let deyiminde nasıl kullanacağınızı gösterir:

Dosya adı: src/main.rs

fn main() {
    // toplama
    let toplam = 5 + 10;

    // çıkarma
    let fark = 95.5 - 4.3;

    // çarpma
    let carpim = 4 * 30;

    // bölme
    let bolum = 56.7 / 32.2;
    let kesilmis = -5 / 3; // Sonuç -1 olur

    // kalan
    let kalan = 43 % 5;
}

Bu deyimlerdeki her bir ifade matematiksel bir operatör kullanır ve değerlendirilerek tek bir değer üretir; ardından bu değer ilgili değişkene bağlanır. Ek B, Rust’ın sunduğu tüm operatörlerin tam bir listesini içerir.

Not: Rust, farklı sayısal türler arasında örtük (otomatik) dönüşüm yapmaz: i32 türündeki bir değeri i64 türündeki bir değerle doğrudan toplamaya çalışırsanız derleyici cannot add `i64` to `i32` hatası verir. Böyle durumlarda değerleri açıkça ortak bir türe dönüştürmeniz gerekir. Örneğin i32 değerini i64 türüne kayıpsız dönüştürmek için i64::from(x) + y yazabilirsiniz. as ile dönüşüm de mümkündür (x as i64 + y); ancak daraltıcı tam sayı dönüşümleri veri kaybına yol açabilir. Hedef türe sığmayan bir değeri hata olarak ele almak istiyorsanız TryFrom veya TryInto kullanabilirsiniz; bu trait’leri ilerleyen bölümlerde göreceğiz. Ayrıca bir tam sayıyı çalışma zamanında sıfıra bölmek, hem hata ayıklama hem de yayın modunda attempt to divide by zero mesajıyla panik üretir; kayan noktalı sayılarda ise sıfıra bölme paniklemez, IEEE-754 kurallarına göre inf ya da NaN değerini döndürür.

Boolean Türü

Diğer pek çok programlama dilinde olduğu gibi Rust’ta da Boolean türünün iki olası değeri vardır: true ve false. Boolean değerler bellekte bir bayt yer kaplar. Rust’ta Boolean türü bool anahtar kelimesiyle belirtilir. Örneğin:

Dosya adı: src/main.rs

fn main() {
    let t = true;

    let f: bool = false; // açık tür bildirimiyle
}

Boolean değerlerini kullanmanın başlıca yolu if ifadesi gibi koşullu yapılardır. if ifadelerinin Rust’ta nasıl çalıştığını “Kontrol Akışı” bölümünde ele alacağız.

Karakter Türü

Rust’ın char türü, dilin en temel alfabetik veri türüdür. İşte char değerleri tanımlamaya dair birkaç örnek:

Dosya adı: src/main.rs

fn main() {
    let c = 'z';
    let z: char = 'ℤ'; // açık tür bildirimiyle
    let kalp_gozlu_kedi = '😻';
}

Çift tırnak kullanan string sabitlerinin (string literals) aksine, char sabitlerini tek tırnakla belirttiğimize dikkat edin. Rust’ın char türü 4 bayt boyutundadır ve bir Unicode skaler değerini temsil eder; bu sayede yalnızca ASCII karakterlerini değil, çok daha fazlasını ifade edebilir. Aksanlı ve noktalı harfler; Çince, Japonca ve Korece karakterler; emojiler ve sıfır genişlikli boşluklar Rust’ta geçerli birer char değeridir. Unicode skaler değerleri U+0000 ile U+D7FF ve U+E000 ile U+10FFFF (sınırlar dahil) aralıklarını kapsar. Bununla birlikte “karakter” aslında Unicode standardında doğrudan tanımlı bir kavram değildir; dolayısıyla bir “karakterin” ne olduğuna dair günlük sezgimiz Rust’taki char tanımıyla her zaman birebir örtüşmeyebilir. Bu konuyu Bölüm 8’deki “String’lerle UTF-8 Kodlanmış Metin Saklama” kısmında ayrıntılı olarak inceleyeceğiz.

Not: Türkçeye özgü 'ç', 'ğ', 'ı', 'İ', 'ö', 'ş', 'ü' harfleri ve '😻' gibi tek skaler değerden oluşan emojiler geçerli birer char sabitidir; her char değeri, hangi karakteri tuttuğundan bağımsız olarak bellekte 4 bayt yer kaplar. Buna karşılık Bölüm 8’de göreceğimiz UTF-8 kodlamalı String ve &str metinlerinde karakterler değişken uzunlukta saklanır (örneğin ASCII harfler 1 bayt, 'ğ' ve 'ş' gibi Türkçe harfler 2 bayt, '😻' emojisi ise 4 bayt yer kaplar). Ayrıca birden fazla Unicode skaler değerinin birleşimiyle oluşturulan bazı birleşik emojiler (örneğin "👨‍👩‍👧‍👦") tek bir char içine sığmaz.

Bileşik Türler

Bileşik türler (compound types) birden fazla değeri tek bir tür altında gruplayabilir. Rust’ta iki ilkel bileşik tür vardır: demetler (tuples) ve diziler (arrays).

Demet Türü

Demet (tuple), farklı türlerde olabilen bir grup değeri tek bir bileşik tür altında bir araya getirmenin genel bir yoludur. Demetlerin sabit bir uzunluğu vardır: Bir kez bildirildikten sonra boyutları büyüyemez veya küçülemez.

Parantez içine virgülle ayrılmış bir değer listesi yazarak bir demet oluştururuz. Demetteki her konumun kendine ait bir türü vardır ve farklı konumlardaki değerlerin türlerinin aynı olması gerekmez. Aşağıdaki örnekte isteğe bağlı tür bildirimlerini de ekledik:

Dosya adı: src/main.rs

fn main() {
    let tup: (i32, f64, u8) = (500, 6.4, 1);
}

Bir demet tek bir bileşik öğe olarak kabul edildiğinden tup değişkeni demetin tamamına bağlanır. Demetin içindeki tekil değerleri elde etmek için desen eşleştirme (pattern matching) kullanarak bir demet değerini aşağıdaki gibi parçalayabiliriz:

Dosya adı: src/main.rs

fn main() {
    let tup = (500, 6.4, 1);

    let (x, y, z) = tup;

    println!("y'nin değeri: {y}");
}

Bu program önce bir demet oluşturup onu tup değişkenine bağlar. Ardından let ile birlikte bir desen kullanarak tup değerini alır ve üç ayrı değişkene (x, y ve z) ayırır. Tek bir demeti üç parçaya ayırdığı için bu işleme yapı sökümü (destructuring) denir. Son olarak program, 6.4 olan y değerini ekrana yazdırır.

Bir demet elemanına, demetin adından sonra bir nokta (.) ve erişmek istediğimiz değerin indeksini yazarak doğrudan da ulaşabiliriz. Örneğin:

Dosya adı: src/main.rs

fn main() {
    let x: (i32, f64, u8) = (500, 6.4, 1);

    let bes_yuz = x.0;

    let alti_nokta_dort = x.1;

    let bir = x.2;
}

Bu program x demetini oluşturur ve ardından her bir elemanına kendi indeksi üzerinden erişir. Çoğu programlama dilinde olduğu gibi bir demetteki ilk indeks 0’dır.

Hiçbir değer içermeyen boş demetin özel bir adı vardır: birim (unit). Hem bu değer hem de karşılık gelen türü () biçiminde yazılır; boş bir değeri veya boş bir dönüş türünü temsil eder. İfadeler, başka bir değer döndürmediklerinde örtük olarak (implicitly) birim değerini döndürürler.

Not: Birim tür (), C veya Java gibi dillerdeki void kavramına benzer şekilde anlamlı bir değer taşınmadığını belirtir; ancak void’den farklı olarak gerçek ve somut bir türdür. Yalnızca tek bir olası değere (()) sahip olduğundan derleyici onun çalışma zamanında bellekte yer kaplamasına ihtiyaç duymaz (boyutu 0 bayttır). Dönüş türü yazılmayan fonksiyonların gerçek dönüş türü ()’dir.

Dizi Türü

Birden fazla değerden oluşan bir koleksiyon elde etmenin bir diğer yolu da dizi (array) kullanmaktır. Demetten farklı olarak bir dizinin tüm elemanları aynı türde olmalıdır. Diğer bazı dillerdeki dizilerin aksine, Rust’taki diziler sabit uzunlukludur.

Bir dizideki değerleri köşeli parantezler içinde virgülle ayrılmış bir liste hâlinde yazarız:

Dosya adı: src/main.rs

fn main() {
    let a = [1, 2, 3, 4, 5];
}

Diziler, verilerinizin öbek (heap) yerine —şimdiye kadar gördüğümüz diğer türlerde olduğu gibi— yığın (stack) üzerinde ayrılmasını istediğinizde (Bölüm 4’te yığın ve öbeği daha ayrıntılı ele alacağız) veya her zaman sabit sayıda elemana sahip olduğunuzdan emin olmak istediğinizde kullanışlıdır. Ancak bir dizi, vektör (vector) türü kadar esnek değildir. Vektör, standart kütüphane tarafından sağlanan ve içeriği öbek üzerinde tutulduğu için boyutunun büyümesine veya küçülmesine izin verilen benzer bir koleksiyon türüdür. Dizi mi yoksa vektör mü kullanacağınızdan emin değilseniz büyük olasılıkla bir vektör kullanmalısınız. Bölüm 8 vektörleri daha ayrıntılı olarak inceler.

Bununla birlikte, eleman sayısının değişmeyeceğini bildiğiniz durumlarda diziler daha uygundur. Örneğin bir programda ay adlarını kullanıyorsanız, her zaman 12 eleman içereceğini bildiğiniz için büyük olasılıkla vektör yerine bir dizi tercih edersiniz:

#![allow(unused)]
fn main() {
let aylar = ["Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz",
             "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"];
}

Bir dizinin türünü köşeli parantezler içinde her elemanın türünü, ardından bir noktalı virgülü ve dizideki eleman sayısını belirterek yazarız:

#![allow(unused)]
fn main() {
let a: [i32; 5] = [1, 2, 3, 4, 5];
}

Burada i32 her bir elemanın türüdür. Noktalı virgülden sonraki 5 sayısı ise dizinin beş eleman içerdiğini belirtir.

Tüm elemanları aynı değere sahip olacak bir diziyi, köşeli parantez içinde önce başlangıç değerini, ardından noktalı virgülü ve son olarak dizinin uzunluğunu yazarak da başlatabilirsiniz:

#![allow(unused)]
fn main() {
let a = [3; 5];
}

a adındaki bu dizi, başlangıçta tamamı 3 değerine ayarlanmış 5 eleman içerecektir. Bu ifade let a = [3, 3, 3, 3, 3]; yazmakla birebir aynıdır, ancak çok daha özlüdür.

Dizi Elemanlarına Erişim

Bir dizi, yığın üzerinde ayrılabilen, boyutu derleme zamanında bilinen sabit büyüklükte tek parça bir bellek bloğudur. İndeksleme kullanarak bir dizinin elemanlarına şu şekilde erişebilirsiniz:

Dosya adı: src/main.rs

fn main() {
    let a = [1, 2, 3, 4, 5];

    let ilk = a[0];
    let ikinci = a[1];
}

Bu örnekte ilk adlı değişken, dizinin [0] indeksindeki değer olan 1 değerini alır. ikinci adlı değişken ise dizinin [1] indeksindeki 2 değerini alır.

Geçersiz Dizi Elemanlarına Erişim

Bir dizinin sonunu aşan bir indeksle dizi elemanına erişmeye çalışırsanız ne olacağına bakalım. Kullanıcıdan bir dizi indeksi almak için Bölüm 2’deki tahmin oyununa benzer aşağıdaki kodu çalıştırdığınızı düşünelim:

Dosya adı: src/main.rs

use std::io;

fn main() {
    let a = [1, 2, 3, 4, 5];

    println!("Lütfen bir dizi indeksi girin.");

    let mut indeks = String::new();

    io::stdin()
        .read_line(&mut indeks)
        .expect("Satırı okuyamadı!");

    let indeks: usize = indeks
        .trim()
        .parse()
        .expect("Girilen indeks bir sayı değildi!");

    let element = a[indeks];

    println!("{indeks} indeksindeki elemanın değeri: {element}");
}

Bu kod sorunsuzca derlenir. Kodu cargo run ile çalıştırıp 0, 1, 2, 3 veya 4 değerlerinden birini girerseniz program dizide o indekse karşılık gelen değeri ekrana yazdırır. Ancak dizinin sınırlarını aşan bir sayı (örneğin 10) girerseniz şuna benzer bir çıktı görürsünüz:

thread 'main' panicked at src/main.rs:19:19:
index out of bounds: the len is 5 but the index is 10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Program, indeksleme işleminde geçersiz bir değerin kullanıldığı noktada bir çalışma zamanı hatasıyla karşılaştı; bir hata mesajı yazdırarak sonlandı ve en sondaki println! deyimini çalıştırmadı. İndeksleme yoluyla bir elemana erişmeye çalıştığınızda Rust, belirttiğiniz indeksin dizi uzunluğundan küçük olup olmadığını kontrol eder. İndeks dizi uzunluğuna eşit veya ondan büyükse Rust panikler. Özellikle bu örnekte olduğu gibi derleyicinin, kodu daha sonra çalıştıracak kullanıcının hangi sayıyı gireceğini derleme zamanında bilmesi imkânsız olduğundan bu kontrolün çalışma zamanında yapılması gerekir.

Not: Panik çıktısındaki index out of bounds: the len is 5 but the index is 10 mesajı “indeks sınırların dışında: dizinin uzunluğu 5 ama istenen indeks 10” anlamına gelir. Programı çökertmek (panic!) yerine sınır aşımını güvenli biçimde kontrol etmek istediğinizde, Bölüm 6 ve Bölüm 8’de göreceğimiz Option türünü döndüren a.get(indeks) metodunu kullanabilirsiniz.

Bu davranış, Rust’ın bellek güvenliği ilkelerinin iş başındaki somut bir örneğidir. Pek çok alt seviye dilde bu tür bir sınır kontrolü yapılmaz ve yanlış bir indeks verdiğinizde geçersiz bellek bölgelerine erişilebilir. Rust, geçersiz bellek erişimine izin verip çalışmaya devam etmek yerine programı derhal sonlandırarak sizi bu tür güvenlik açıklarına ve belirsiz davranışlara karşı korur. Bölüm 9’da Rust’ın hata yönetimi mekanizmalarını ve ne panikleyen ne de geçersiz bellek erişimine izin veren okunaklı, güvenli kodları nasıl yazabileceğinizi daha ayrıntılı olarak ele alacağız.