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

Değişkenler ve Değiştirilebilirlik (Mutability)

“Değerleri Değişkenlerle Saklamak” bölümünde bahsedildiği gibi, değişkenler varsayılan olarak değiştirilemezdir. Bu, kodunuzu Rust’ın sunduğu güvenlik ve kolay eşzamanlılık (concurrency) avantajlarından yararlanacak şekilde yazmanız için Rust’ın size verdiği birçok küçük dürtmeden biridir. Ancak yine de değişkenlerinizi değiştirilebilir yapma seçeneğiniz vardır. Rust’ın sizi neden değiştirilemezliği tercih etmeye teşvik ettiğini ve neden bazen bundan vazgeçmek isteyebileceğinizi keşfedelim.

Bir değişken değiştirilemez olduğunda, bir değere bir isim bağlandığında, o değeri bir daha değiştiremezsiniz. Bunu göstermek için, cargo new degiskenler komutunu kullanarak projects dizininizde degiskenler adında yeni bir proje oluşturun.

Ardından, yeni degiskenler dizininizde src/main.rs dosyasını açın ve kodunu henüz derlenmeyecek olan şu kodla değiştirin:

Dosya adı: src/main.rs

fn main() {
    let x = 5;
    println!("x'in değeri: {x}");
    x = 6;
    println!("x'in değeri: {x}");
}

Programı kaydedin ve cargo run kullanarak çalıştırın. Aşağıdaki çıktıda gösterildiği gibi, değiştirilemezlik (immutability) hatasıyla ilgili bir hata mesajı almalısınız:

$ cargo run
   Compiling variables v0.1.0 ($PROJE/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable)
error[E0384]: cannot assign twice to immutable variable `x`
 --> src/main.rs:4:5
  |
2 |     let x = 5;
  |         - first assignment to `x`
3 |     println!("x'in değeri: {x}");
4 |     x = 6;
  |     ^^^^^ cannot assign twice to immutable variable
  |
help: consider making this binding mutable
  |
2 |     let mut x = 5;
  |         +++

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

Bu örnek derleyicinin programlarınızdaki hataları bulmanıza nasıl yardımcı olduğunu gösterir. Derleyici hataları sinir bozucu olabilir, ancak aslında yalnızca programınızın sizin istediğiniz şeyi henüz güvenli bir şekilde yapmadığı anlamına gelirler; sizin iyi bir programcı olmadığınız anlamına gelmezler! Deneyimli Rustacean’lar bile hâlâ derleyici hataları almaktadır.

cannot assign twice to immutable variable `x` (x değiştirilemez değişkenine ikinci kez atama yapılamaz) hata mesajını aldınız çünkü değiştirilemez x değişkenine ikinci bir değer atamaya çalıştınız.

Değiştirilemez olarak belirlenmiş bir değeri değiştirmeye çalıştığımızda derleme zamanı (compile-time) hataları almamız önemlidir, çünkü bizzat bu durum hatalara (bug) yol açabilir. Kodumuzun bir kısmı bir değerin asla değişmeyeceği varsayımıyla çalışırsa ve kodumuzun başka bir kısmı o değeri değiştirirse, kodun ilk kısmının tasarlandığı şeyi yapmaması mümkündür. Bu tür bir hatanın nedenini oluştuktan sonra takip etmek zor olabilir, özellikle de kodun ikinci parçası değeri yalnızca bazen değiştiriyorsa. Rust derleyicisi, bir değerin değişmeyeceğini belirttiğinizde gerçekten değişmeyeceğini garanti eder, bu nedenle bunu kendiniz takip etmek zorunda kalmazsınız. Böylece kodunuzun mantığını anlamak daha kolaydır.

Ancak değiştirilebilirlik (mutability) çok faydalı olabilir ve kod yazmayı daha kullanışlı hale getirebilir. Değişkenler varsayılan olarak değiştirilemez olsa da, Bölüm 2’de yaptığınız gibi değişken adının önüne mut ekleyerek onları değiştirilebilir yapabilirsiniz. mut eklemek aynı zamanda kodun diğer kısımlarının bu değişkenin değerini değiştireceğini belirterek, kodu gelecekte okuyacak kişilere niyetinizi iletir.

Örneğin, src/main.rs dosyasını şu şekilde değiştirelim:

Dosya adı: src/main.rs

fn main() {
    let mut x = 5;
    println!("x'in değeri: {x}");
    x = 6;
    println!("x'in değeri: {x}");
}

Şimdi programı çalıştırdığımızda şunu elde ederiz:

$ cargo run
   Compiling variables v0.1.0 ($PROJE/listings/ch03-common-programming-concepts/no-listing-02-adding-mut)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.13s
     Running `target/debug/variables`
x'in değeri: 5
x'in değeri: 6

mut kullanıldığında x’e bağlı olan değeri 5’ten 6’ya değiştirmemize izin verilir. Nihayetinde, değiştirilebilirliği kullanıp kullanmamaya karar vermek size bağlıdır ve o belirli durumda neyin en açık (anlaşılır) olduğunu düşündüğünüze göre değişir.

Sabitleri Bildirmek (Constants)

Değiştirilemez değişkenler gibi, sabitler de bir isme bağlı olan ve değiştirilmesine izin verilmeyen değerlerdir, ancak sabitler ile değişkenler arasında birkaç fark vardır.

İlk olarak, sabitlerle birlikte mut kullanmanıza izin verilmez. Sabitler sadece varsayılan olarak değiştirilemez değildirler; onlar her zaman değiştirilemezdirler. Sabitleri let anahtar kelimesi yerine const anahtar kelimesini kullanarak bildirirsiniz (declare) ve değerin türü mutlaka belirtilmelidir (annotated). Türleri ve tür bildirimlerini (type annotations) bir sonraki bölüm olan “Veri Türleri” kısmında ele alacağız, bu yüzden şu anda ayrıntılar için endişelenmeyin. Sadece her zaman türü belirtmeniz gerektiğini bilin.

Sabitler, küresel kapsam (global scope) da dahil olmak üzere herhangi bir kapsamda bildirilebilirler; bu durum onları, kodun birçok parçasının bilmesi gereken değerler için kullanışlı hale getirir.

Son fark ise sabitlerin, sadece çalışma zamanında hesaplanabilecek bir değere değil, yalnızca sabit bir ifadeye (constant expression) ayarlanabilmesidir.

İşte bir sabit bildirimi örneği:

#![allow(unused)]
fn main() {
const SANIYE_CINSINDEN_UC_SAAT: u32 = 60 * 60 * 3;
}

Sabitin adı SANIYE_CINSINDEN_UC_SAAT’tir (THREE_HOURS_IN_SECONDS) ve değeri, 60 (bir dakikadaki saniye sayısı), 60 (bir saatteki dakika sayısı) ve 3’ün (bu programda saymak istediğimiz saat sayısı) çarpılması sonucuna ayarlanmıştır. Rust’ın sabitler için adlandırma geleneği, tüm harfleri büyük yazmak ve kelimeler arasında alt çizgi kullanmaktır. Derleyici, derleme zamanında sınırlı bir dizi işlemi değerlendirebilir; bu da sabiti doğrudan 10.800 değerine ayarlamak yerine, bu değeri anlaması ve doğrulaması daha kolay bir şekilde yazmayı seçmemizi sağlar. Sabitleri bildirirken hangi işlemlerin kullanılabileceği hakkında daha fazla bilgi için Rust Referansı’nın sabit değerlendirme bölümüne bakın.

Sabitler, bildirildikleri kapsam içinde, program çalıştığı süre boyunca geçerlidirler. Bu özellik, bir oyundaki herhangi bir oyuncunun kazanabileceği maksimum puan sayısı veya ışık hızı gibi, programın birden fazla bölümünün bilmesi gerekebilecek uygulama alanınızdaki (application domain) değerler için sabitleri yararlı kılar.

Programınız boyunca kullanılan sabit (hardcoded) değerleri const (sabit) olarak adlandırmak, bu değerin anlamını kodun gelecekteki bakımcılarına iletmek açısından faydalıdır. Ayrıca, sabit kodlanmış değerin gelecekte güncellenmesi gerektiğinde kodunuzda değiştirmeniz gereken yalnızca bir yer olmasına da yardımcı olur.

Gölgelendirme (Shadowing)

Bölüm 2’deki tahmin oyunu eğitiminde gördüğünüz gibi, önceki bir değişkenle aynı isimde yeni bir değişken bildirebilirsiniz (declare). Rust geliştiricileri (Rustaceans) ilk değişkenin ikincisi tarafından gölgelendiğini (shadowed) söyler; bu, değişkenin adını kullandığınızda derleyicinin göreceği şeyin ikinci değişken olduğu anlamına gelir. Aslında ikinci değişken, kendisi gölgelenene veya kapsam sona erene kadar değişken adının tüm kullanımlarını kendine alarak ilkini gölgede bırakır (overshadows). Bir değişkeni aynı değişkenin adını kullanarak ve let anahtar kelimesinin kullanımını tekrarlayarak aşağıdaki gibi gölgelendirebiliriz:

Dosya adı: src/main.rs

fn main() {
    let x = 5;

    let x = x + 1;

    {
        let x = x * 2;
        println!("İç kapsamdaki x'in değeri: {x}");
    }

    println!("x'in değeri: {x}");
}

Bu program önce x’i 5 değerine bağlar. Ardından, let x = komutunu tekrarlayarak yeni bir x değişkeni oluşturur, orijinal değeri alır ve 1 ekler, böylece x’in değeri 6 olur. Sonra, süslü parantezlerle (curly brackets) oluşturulan bir iç kapsamda (inner scope), üçüncü let ifadesi de x’i gölgelendirir ve önceki değeri 2 ile çarparak x’e 12 değerini veren yeni bir değişken oluşturur. O kapsam sona erdiğinde iç gölgelendirme biter ve x tekrar 6 olur. Bu programı çalıştırdığımızda şu çıktıyı verecektir:

$ cargo run
   Compiling variables v0.1.0 ($PROJE/listings/ch03-common-programming-concepts/no-listing-03-shadowing)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.15s
     Running `target/debug/variables`
İç kapsamdaki x'in değeri: 12
x'in değeri: 6

Gölgelendirme, bir değişkeni mut olarak işaretlemekten farklıdır; çünkü let anahtar kelimesini kullanmadan kazara bu değişkene yeniden atama (reassign) yapmaya çalışırsak derleme zamanı (compile-time) hatası alırız. let kullanarak, bir değer üzerinde birkaç dönüştürme (transformation) işlemi gerçekleştirebiliriz, ancak bu dönüştürmeler tamamlandıktan sonra değişkenin değiştirilemez kalmasını sağlayabiliriz.

mut ve gölgelendirme arasındaki diğer fark ise şudur: let anahtar kelimesini tekrar kullandığımızda etkili bir şekilde yeni bir değişken oluşturduğumuz için, değerin türünü değiştirebilir ancak aynı ismi yeniden kullanabiliriz. Örneğin, programımızın bir kullanıcıdan biraz metin arasına ne kadar boşluk istediğini boşluk karakterleri girerek göstermesini istediğini, ve ardından bu girdiyi bir sayı olarak saklamak istediğimizi varsayalım:

fn main() {
    let bosluklar = "   ";
    let bosluklar = bosluklar.len();
}

İlk bosluklar değişkeni bir metin (string) türüdür ve ikinci bosluklar değişkeni bir sayı türüdür. Gölgelendirme böylece bizi bosluklar_str ve bosluklar_sayi gibi farklı isimler bulmak zorunda kalmaktan kurtarır; bunun yerine daha basit olan bosluklar ismini yeniden kullanabiliriz. Ancak, burada gösterildiği gibi bunun için mut kullanmaya çalışırsak, derleme zamanı (compile-time) hatası alırız:

fn main() {
    let mut bosluklar = "   ";
    bosluklar = bosluklar.len();
}

Hata, bir değişkenin türünü değiştirmemize (mutate) izin verilmediğini söylüyor:

$ cargo run
   Compiling variables v0.1.0 ($PROJE/listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types)
error[E0308]: mismatched types
 --> src/main.rs:4:17
  |
3 |     let mut bosluklar = "   ";
  |                         ----- expected due to this value
4 |     bosluklar = bosluklar.len();
  |                 ^^^^^^^^^^^^^^^ expected `&str`, found `usize`

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

Artık değişkenlerin nasıl çalıştığını keşfettiğimize göre, sahip olabilecekleri daha fazla veri türüne (data types) bakalım.