Değişkenler ve Değişkenlik

“Değişkenlerle Değerleri Saklama” bölümünde belirtildiği gibi, varsayılan olarak değişkenler değişmezdir. Bu, Rust'ın size sunduğu güvenlik ve kolay eşzamanlılıktan yararlanarak kodunuzu yazmanız için size verdiği birçok dürtüden biridir. Ancak yine de değişkenlerinizi değiştirilebilir yapma seçeneğiniz vardır. Rust'ın sizi değişmezliği tercih etmeye nasıl ve neden teşvik ettiğini ve bazen neden vazgeçmek isteyebileceğinizi keşfedelim.

Bir değişken değişmez olduğunda, bir değer bir ada bağlandıktan sonra bu değeri değiştiremezsiniz. Bunu örneklemek için, cargo new variables komutunu kullanarak proje dizininizde variables adında yeni bir proje oluşturalım.

Ardından, yeni variables dizininizde bulunan src/main.rs dosyasını açın ve kodunu aşağıdaki kodla değiştirin. Bu kod henüz derlenmeyecek, bundan dolayı önce değişmezlik hatasını inceleyeceğiz.

Dosya adı: src/main.rs

fn main() {
    let x = 5;
    println!("The value of x is: {x}");
    x = 6;
    println!("The value of x is: {x}");
}

cargo run komutunu kullanarak programı kaydedin ve çalıştırın. Bu çıktıda gösterildiği gibi bir hata mesajı almalısınız:

$ cargo run
   Compiling variables v0.1.0 (file:///projects/variables)
error[E0384]: cannot assign twice to immutable variable `x`
 --> src/main.rs:4:5
  |
2 |     let x = 5;
  |         -
  |         |
  |         first assignment to `x`
  |         help: consider making this binding mutable: `mut x`
3 |     println!("The value of x is: {x}");
4 |     x = 6;
  |     ^^^^^ cannot assign twice to immutable variable

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

Bu örnek, derleyicinin programlarınızdaki hataları bulmanıza nasıl yardımcı olduğunu gösterir. Derleyici hataları can sıkıcı olabilir, ancak gerçekte bunlar yalnızca programınızın henüz yapmak istediğiniz şeyi güvenli bir şekilde yapmadığı anlamına gelir; iyi bir programcı olmadığınız anlamına gelmezler! Deneyimli Rustseverler hala derleyici hataları alıyor.

Hata mesajı, hatanın nedeninin, değişmez x değişkenine ikinci bir değer atamaya çalıştığınız için değişmez "x" değişkenine ikinci kez atayamamanız olduğunu gösterir.

Değişmez olarak belirlenmiş bir değeri değiştirmeye çalıştığımızda derleme zamanı hataları almamız önemlidir çünkü bu durum hatalara yol açabilir. Kodumuzun bir kısmı, bir değerin asla değişmeyeceği varsayımıyla çalışıyorsa ve kodumuzun başka bir kısmı bu değeri değiştiriyorsa, kodun ilk kısmının tasarlandığı şeyi yapmaması olasıdır. Bu tür bir hatanın nedenini, özellikle ikinci kod parçası değeri yalnızca bazen değiştirdiğinde, olaydan sonra bulmak zor olabilir. Rust derleyicisi, bir değerin değişmeyeceğini belirttiğinizde, gerçekten değişmeyeceğini garanti eder, bu nedenle onu kendiniz takip etmek zorunda kalmazsınız. Bu nedenle kodunuzun akıl yürütmesi daha kolaydır.

Ancak değişebilirlik çok faydalı olabilir ve kod yazmayı daha uygun hale getirebilir. Değişkenler yalnızca varsayılan olarak değişmezdir; Bölüm 2'de yaptığınız gibi, değişken adının önüne mut ekleyerek bunları değiştirilebilir yapabilirsiniz. mut eklemek ayrıca kodun diğer bölümlerinin bu değişkenin değerini değiştireceğini belirterek kodun gelecekteki okuyucularına niyet iletir.

Örneğin, src/main.rs'yi aşağıdaki şekilde değiştirelim:

Dosya adı: src/main.rs

fn main() {
    let mut x = 5;
    println!("The value of x is: {x}");
    x = 6;
    println!("The value of x is: {x}");
}

Programı şimdi çalıştırdığımızda şunu görürüz:

$ cargo run
   Compiling variables v0.1.0 (file:///projects/variables)
    Finished dev [unoptimized + debuginfo] target(s) in 0.30s
     Running `target/debug/variables`
The value of x is: 5
The value of x is: 6

mut kullanıldığında x'e bağlı değeri 5'ten 6'ya değiştirmemize izin verilir. Nihayetinde, mut kullanıp kullanmamaya karar vermek size bağlıdır.

Sabitler

Değişmez değişkenler gibi, sabitler de bir ada bağlı ve değişmesine izin verilmeyen değerlerdir, ancak sabitler ve değişkenler arasında birkaç fark vardır.

İlk olarak, mut'u sabitlerle kullanamazsınız. Sabitler yalnızca varsayılan olarak değişmez değildir, her zaman değişmezdirler. Sabitleri let anahtar sözcüğü yerine const anahtar sözcüğünü kullanarak bildirirsiniz ve değerin türü verilmiş olmalıdır. Bir sonraki “Veri Türleri” bölümünde türleri ve tür ek açıklamalarını ele alacağız, bu nedenle şu anda ayrıntılar için endişelenmeyin. Her zaman türe değer vermeniz gerektiğini bilin. Sabitler, global kapsam da dahil olmak üzere herhangi bir kapsamda bildirilebilir, bu da onları kodun birçok bölümünün bilmesi gereken değerler için faydalı kılar. Son fark olarak, sabitlerin çalışma zamanında hesaplanabilecek bir değerin sonucu olarak değil, yalnızca sabit bir ifadeye ayarlanabilmesidir. İşte bir sabit bildirim örneği:


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

Sabitin adı THREE_HOURS_IN_SECONDS'dır ve değeri 60 (bir dakikadaki saniye sayısı) ile 60 (bir saatteki dakika sayısı) ile 3 (bu programda saymak istediğimiz saat sayısı) çarpılmasının sonucuna ayarlanır. Rust'ın sabitler için adlandırma kuralı, sözcükler arasında alt çizgi ile tüm büyük harfleri kullanmaktır. Derleyici, derleme zamanında sınırlı bir dizi işlemi değerlendirebilir; bu, bu sabiti 10,800 değerine ayarlamak yerine, bu değeri anlaşılması ve doğrulanması daha kolay bir şekilde yazmayı seçmemize olanak tanır. Sabitleri bildirirken hangi işlemlerin kullanılabileceği hakkında daha fazla bilgi için Rust Reference’ın sabitleri hesaplama bölümüne bakın. Sabitler, bir programın çalıştığı tüm süre boyunca, bildirildikleri kapsam dahilinde geçerlidir. Bu özellik, sabitleri, uygulama etki alanınızdaki, herhangi bir maksimum nokta sayısı gibi, programın birden fazla bölümünün bilmesi gerekebilecek değerler için kullanışlı hale getirir. Programınız boyunca kullanılan sabit kodlanmış değerleri sabitler olarak adlandırmak, bu değerin anlamını kodun gelecekteki koruyucularına iletmede faydalıdır. Ayrıca, gelecekte sabit kodlanmış değerin güncellenmesi gerekiyorsa değiştirmeniz gereken kodunuzun yalnızca bir bölümü olacaktır.

Gölgeleme

Bölüm 2'deki tahmin oyununda gördüğünüz gibi, önceki değişkenle aynı ada sahip yeni bir değişken bildirebilirsiniz. Rustseverler, ilk değişkenin ikinci tarafından gölgelendiğini söylüyor, bu da ikinci değişkenin, değişkenin adını kullandığınızda derleyicinin göreceği şey olduğu anlamına geliyor. Gerçekte, ikinci değişken birinciyi gölgede bırakır ve değişken adının herhangi bir kullanımını kendisi gölgelenene veya kapsam sona erene kadar kendisine alır. Aynı değişkenin adını kullanarak ve let anahtar sözcüğünü aşağıdaki gibi tekrarlayarak bir değişkeni gölgeleyebiliriz:

Dosya adı: src/main.rs

fn main() {
    let x = 5;

    let x = x + 1;

    {
        let x = x * 2;
        println!("The value of x in the inner scope is: {x}");
    }

    println!("The value of x is: {x}");
}

Bu program önce x'e 5 değerini atar, sonra let x ='i tekrar ederek, orijinal değeri alıp 1 ekleyerek yeni bir x değişkeni oluşturur, böylece x değeri 6 olur. Parantez içindeki üçüncü let ifadesi de x'i gölgeler ve x'e 12 değerini vermek için önceki değeri 2 ile çarparak yeni bir değişken oluşturur. Bu kapsam sona erdiğinde, iç gölgeleme sona erer ve x, 6'ya döner. Bu programı çalıştırdığımızda, aşağıdaki çıktıyı verecektir:

$ cargo run
   Compiling variables v0.1.0 (file:///projects/variables)
    Finished dev [unoptimized + debuginfo] target(s) in 0.31s
     Running `target/debug/variables`
The value of x in the inner scope is: 12
The value of x is: 6

Gölgeleme, bir değişkeni mut olarak işaretlemekten farklıdır çünkü let anahtar sözcüğünü kullanmadan yanlışlıkla bu değişkene yeniden atamaya çalışırsak derleme zamanı hatası alırız. let kullanarak, bir değer üzerinde birkaç dönüşüm gerçekleştirebiliriz, ancak bu dönüşümler tamamlandıktan sonra değişkenin değişmez olmasını sağlayabiliriz.

mut ve shadowing arasındaki diğer fark, let anahtar sözcüğünü tekrar kullandığımızda etkin bir şekilde yeni bir değişken oluşturduğumuz için, değerin türünü değiştirebilir ancak aynı adı yeniden kullanabiliriz. Örneğin, programımızın bir kullanıcıdan boşluk karakterleri girerek bazı metinler arasında kaç boşluk istediğini göstermesini istediğini ve ardından bu girişi bir sayı olarak saklamak istediğimizi varsayalım:

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

İlk spaces değişkeni bir dize türüdür ve ikinci spaces değişkeni bir sayı türüdür. Böylece gölgeleme, bizi space_str ve space_num gibi farklı isimler kullanmaktan kurtarır; bunun yerine, daha basitçe spaces adını yeniden kullanabiliriz. Ancak, burada gösterildiği gibi bunun için mut kullanmaya çalışırsak, bir derleme zamanı hatası alırız:

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

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

$ cargo run
   Compiling variables v0.1.0 (file:///projects/variables)
error[E0308]: mismatched types
 --> src/main.rs:3:14
  |
2 |     let mut spaces = "   ";
  |                      ----- expected due to this value
3 |     spaces = spaces.len();
  |              ^^^^^^^^^^^^ expected `&str`, found `usize`

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

Artık değişkenlerin nasıl çalıştığını anladığımıza göre, sahip olabilecekleri daha fazla veri türüne bakalım.