Ana içeriğe geç

ch03-05-control-flow

Kontrol Akışı

Bir koşulun true olup olmamasına bağlı olarak bazı kodların çalıştırılması ve bir koşul true olduğu sürece bazı kodların tekrar tekrar çalıştırılması, çoğu programlama dilinde temel yapı taşlarıdır. Rust kodunun yürütme akışını kontrol etmenizi sağlayan en yaygın yapılar if ifadeleri ve döngülerdir.

if İfadeleri

Bir if ifadesi, kodunuzu koşullara bağlı olarak dallandırmanızı sağlar. Bir koşul sağlarsınız ve sonra “Bu koşul sağlanıyorsa, bu kod bloğunu çalıştır. Koşul sağlanmıyorsa, bu kod bloğunu çalıştırma.” şeklinde ifade edersiniz.

ipucu

if ifadesini keşfetmek için projects dizininizde branches adında yeni bir proje oluşturun.

src/main.rs dosyasına aşağıdakileri yazın:

Dosya Adı: src/main.rs

{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-26-if-true/src/main.rs}}

Tüm if ifadeleri if anahtar kelimesiyle başlar ve ardından bir koşul gelir. Bu durumda, koşul number değişkeninin 5'ten küçük bir değere sahip olup olmadığını kontrol eder. Koşul true ise çalıştırılacak kod bloğunu süslü parantezler içinde hemen koşulun ardından yerleştiririz. if ifadelerindeki koşullarla ilişkili kod bloklarına bazen kollar denir; bu, “Tahmini Gizli Sayıya Karşı Karşılaştırma” bölümünde tartıştığımız match ifadelerindeki kollar gibi.

İsteğe bağlı olarak, koşul false değerlendiğinde yürütülmesi için programa alternatif bir kod bloğu vermek amacıyla burada seçtiğimiz gibi bir else ifadesi de ekleyebiliriz. Eğer bir else ifadesi sağlamazsanız ve koşul false ise, program sadece if bloğunu atlayacak ve sonraki koda geçecektir.

Bu kodu çalıştırmayı deneyin; aşağıdaki çıktıyı görmelisiniz:

{{#include ../listings/ch03-common-programming-concepts/no-listing-26-if-true/output.txt}}

Bu sefer koşulu false yapacak bir değere number değişkeninin değerini değiştirmeyi deneyelim:

{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-27-if-false/src/main.rs:here}}

Programı tekrar çalıştırın ve çıktıya bakın:

{{#include ../listings/ch03-common-programming-concepts/no-listing-27-if-false/output.txt}}
tehlike

Bu kodda dikkat edilmesi gereken bir diğer nokta, koşulun kesinlikle bir bool olması gerektiğidir. Koşul bir bool değilse, bir hata alırız.

Örneğin, aşağıdaki kodu çalıştırmayı deneyin:

Dosya Adı: src/main.rs

{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/src/main.rs}}

Bu sefer if koşulu 3 değerine değerlendiriliyor ve Rust bir hata veriyor:

{{#include ../listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/output.txt}}

Hata, Rust'ın bir bool beklediğini ancak bir tamsayı aldığını belirtmektedir. Ruby ve JavaScript gibi dillerin aksine, Rust otomatik olarak boole olmayan türleri bir Boole'ye dönüştürmeye çalışmaz.

not

Belirgin olmalısınız ve her zaman if'e koşul olarak bir Boole sağlamalısınız. Örneğin, if kod bloğunun yalnızca bir sayı 0'a eşit olmadığında çalışmasını istiyorsak, if ifadesini aşağıdaki gibi değiştirebiliriz:

Dosya Adı: src/main.rs

{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-29-if-not-equal-0/src/main.rs}}

Bu kod çalıştırıldığında number was something other than zero yazdırır.

else if ile Birden Fazla Koşul Yönetimi

Birden fazla koşulu bir else if ifadesinde if ve else birleştirerek kullanabilirsiniz. Örneğin:

Dosya Adı: src/main.rs

{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-30-else-if/src/main.rs}}

Bu programın dört olası yolu vardır. Çalıştırdıktan sonra aşağıdaki çıktıyı görmelisiniz:

{{#include ../listings/ch03-common-programming-concepts/no-listing-30-else-if/output.txt}}

Bu program çalıştığında, sırasıyla her if ifadesini kontrol eder ve koşul true olarak değerlendirildiği takdirde ilk gövdayı çalıştırır. 6'nın 2 ile bölünebilir olmasına rağmen, number is divisible by 2 çıktısını görmüyoruz, ayrıca number is not divisible by 4, 3, or 2 metnini de else bloğundan görmüyoruz. Bunun nedeni, Rust'ın yalnızca ilk true koşulundaki bloğu çalıştırmasıdır; bir tane bulduğunda, kalanları kontrol dahi etmez.

Aşırı sayıda else if ifadesi kullanmak kodunuzu karıştırabilir, bu nedenle birden fazla varsa kodunuzu gözden geçirmek isteyebilirsiniz. Bölüm 6, bu durumlarda kullanılabilecek güçlü bir Rust dal yapısı olan match ile ilgilidir.

let İfadesinde if Kullanma

if bir ifade olduğundan, onu bir let ifadesinin sağ tarafında kullanarak sonucu bir değişkene atayabiliriz, örneğin Liste 3-2'deki gibi.

{{#rustdoc_include ../listings/ch03-common-programming-concepts/listing-03-02/src/main.rs}}

number değişkeni, if ifadesinin sonucuna dayalı bir değere bağlanacaktır. Bu kodu çalıştırın ve neler olacağını görün:

{{#include ../listings/ch03-common-programming-concepts/listing-03-02/output.txt}}

Kod bloğunun son ifadesi değerlendirildiğini ve sayılar kendi başlarına da ifadeler olduğunu unutmayın. Bu durumda, tüm if ifadesinin değeri hangi kod bloğunun çalıştırıldığına bağlıdır. Bu, if'in her kolunun sonuçlarının aynı türde olması gerektiği anlamına gelir; Liste 3-2'de, if kolunun ve else kolunun sonuçları i32 tam sayılarıydı. Aşağıdaki örnekte olduğu gibi türler birbiriyle uyuşmuyorsa, hata alırız:

Dosya Adı: src/main.rs

{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/src/main.rs}}

Bu kodu derlemeye çalıştığımızda bir hata alırız. if ve else kolları, uyumsuz değer türlerine sahiptir ve Rust, programdaki sorunu tam olarak bulduğunu belirtir:

{{#include ../listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/output.txt}}

if bloğundaki ifade bir tam sayı olarak değerlendiriliyor ve else bloğundaki ifade ise bir dize olarak değerlendiriliyor. Bu çalışmayacaktır çünkü değişkenler tek bir türe sahip olmalıdır ve Rust, derleme zamanında number değişkeninin türünü kesin olarak bilmelidir. number’ın türünü bilmek, derleyicinin, türün number'ı kullandığımız her yerde geçerli olup olmadığını doğrulamasını sağlar. Rust, number’ın türünün yalnızca çalışma zamanında belirlendiği durumlarda bunu yapamayabilir; derleyici daha karmaşık hale gelir ve bir değişken için çok sayıda varsayımsal türü takip etmek zorunda kalırsa, kod hakkında daha az garanti sunacaktır.

Döngülerle Tekrar

Bir kod bloğunu birden fazla kez çalıştırmak sıklıkla yararlıdır. Bu görev için Rust, döngü gövdesinin içindeki kodu sona kadar çalıştıran ve ardından hemen yeniden başlatan birkaç döngü sağlar. Döngülerle denemek için loops adlı yeni bir proje oluşturalım.

Rust'ın üç tür döngüsü vardır: loop, while ve for. Her birini deneyelim.

loop ile Kodu Tekrar Etme

loop anahtar kelimesi Rust'a bir kod bloğunu sonsuz bir döngü şeklinde tekrar tekrar çalıştırmasını söyler veya açıkça durdurmasını istediğinizdeye kadar.

Örneğin, loops dizininizde src/main.rs dosyasını şöyle değiştirin:

Dosya Adı: src/main.rs

{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-32-loop/src/main.rs}}

Bu programı çalıştırdığımızda, again! biçiminde sürekli olarak yeniden yazdırılır ve programı manuel olarak durdurana kadar devam eder. Çoğu terminal, sürekli bir döngüde takılı kalan bir programı kesmek için ctrl-c klavye kısayolunu destekler. Deneyin:

$ cargo run
Compiling loops v0.1.0 (file:///projects/loops)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.08s
Running `target/debug/loops`
again!
again!
again!
again!
^Cagain!

Simge ^C, ctrl-c tuşlarına bastığınız yeri temsil eder. Döngüde kodun ne aşamada olduğunuza bağlı olarak again! kelimesinin ^C'den sonra yazdırılmayabilir.

Neyse ki, Rust, bir döngüden çıkmak için bir yol da sağlar. Döngü içinde break anahtar kelimesini koyarak programa döngü yürütmeye ne zaman son vereceğini söyleyebilirsiniz. Bunu, kullanıcı doğru sayıyı tahmin ettiğinde programı durdurmak için Bölüm 2'de “Doğru Tahminde Sonlandırma” bölümünde yaptığımızı hatırlayın.

Tahmin oyununda kullanılan continue anahtar kelimesini de kullandık; döngüde, programın bu döngü iterasyonundaki herhangi bir kalan kodu atlamasını ve bir sonraki iterasyona geçmesini söyler.

Döngülerden Değer Döndürme

loop'ın en yaygın kullanım alanlarından biri, kesilebileceğini bildiğiniz bir işlemi yeniden denemektir; bir iş parçacığının işini tamamlayıp tamamlamadığını kontrol etmek gibi. Ayrıca bu işlemin sonucunu döngü dışındaki kodun geri kalanına geçmeniz de gerekebilir. Bunu yapmak için, döngüyü durduran break ifadesinden hemen sonra döndürmek istediğiniz değeri ekleyebilirsiniz; bu değer, döngü dışına taşınarak kullanılabilir:

{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-33-return-value-from-loop/src/main.rs}}

Döngüden önce, counter adında bir değişken tanımlar ve başlangıç değerini 0 olarak atarız. Ardından döngüden dönen değeri tutmak için result adında bir değişken tanırız. Döngünün her iterasyonunda, counter değişkenine 1 ekleriz ve ardından counter’ın 10 olup olmadığını kontrol ederiz. 10 olduğunda, break anahtar kelimesi ile counter * 2 değerini kullanırız. Döngüden sonra, sonucu result değişkenine atayan ifadeyi sonlandırmak için bir noktalı virgül kullanırız. Son olarak, result içindeki değeri yazdırırız; bu durumda 20 olacaktır.

Döngü içinde return de yapabilirsiniz. break yalnızca mevcut döngüden çıkarken, return daima mevcut işlevden çıkar.

Birden Fazla Döngü Arasında Ayrım Yapmak için Döngü Etiketleri

Eğer döngülerin içinde döngüleriniz varsa, break ve continue en içteki döngüye uygulanır. İsteğe bağlı olarak, bir döngüde bir döngü etiketi belirtebilirsiniz; ardından bu etiketi break veya continue ile kullanarak bu anahtar kelimelerin etiketlenmiş döngüye uygulanmasını sağlayabilirsiniz. Döngü etiketleri, tek bir tırnakla başlamalıdır. İşte iki iç içe döngüyle ilgili bir örnek:

{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-32-5-loop-labels/src/main.rs}}

Dış döngü, 'counting_up etiketine sahiptir ve 0'dan 2'ye kadar sayacaktır. Etiketsiz iç döngü 10'dan 9'a kadar sayar. Etiket belirtmeyen ilk break yalnızca iç döngüyü terk eder. break 'counting_up; ifadesi dış döngüyü durdurur. Bu kodun çıktısı:

{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-32-5-loop-labels/output.txt}}

while ile Koşullu Döngüler

Bir programın genellikle döngü içinde bir koşulu değerlendirmesi gerekir. Koşul true olduğu sürece döngü çalışır. Koşul true olmaktan çıktığında, program break çağırarak döngüyü durdurur. Bu davranışı, loop, if, else ve break kombinasyonunu kullanarak uygulamak mümkündür; isterseniz şimdi bir programda bunu deneyebilirsiniz. Ancak, bu desen o kadar yaygındır ki Rust'ın bunun için yerleşik bir dil yapısı vardır; buna while döngüsü denir. Liste 3-3'te, koşul true olduğu sürece programı üç kez döngüye sokmakta ve her seferinde geriye doğru sayarak, döngüden sonra bir mesaj yazdırmakta ve çıkmaktadır.

{{#rustdoc_include ../listings/ch03-common-programming-concepts/listing-03-03/src/main.rs}}

Bu yapı, loop, if, else ve break kullandığınızda gerekli olan birçok iç içe girme durumunu elimine eder ve daha net bir yapı sunar. Koşul true değerlendiği sürece kod çalışır; aksi halde döngüyü terk eder.

for ile Bir Koleksiyon Üzerinde Döngü Kurma

Bir koleksiyonun (örneğin bir dizinin) elemanları üzerinde döngü kurmak için while yapısını da kullanabilirsiniz. Örneğin, Liste 3-4'teki döngü, a dizisindeki her bir elemanı yazdırır.

{{#rustdoc_include ../listings/ch03-common-programming-concepts/listing-03-04/src/main.rs}}

Burada, kod dizideki elemanlar üzerinden sayım yapmaktadır. 0 indeksinden başlar ve ardından diziye kadar olan son indekse ulaşana kadar döngü yapar (yani `index

{{#rustdoc_include ../listings/ch03-common-programming-concepts/listing-03-05/src/main.rs}}

Bu kodu çalıştırdığımızda, Liste 3-4’te olduğu gibi aynı çıktıyı göreceğiz. Daha önemlisi, şimdi kodun güvenliğini artırdık ve dizinin sonuna geçmeyi veya yeterince ileri gitmemeyi sağlayacak hatalardan kaçındık.

for döngüsü kullanılarak dizideki değerlerin sayısını değiştirdikçe başka bir kodu değiştirmek zorunda kalmayacaksınız; bu, Liste 3-4'te kullanılan yöntemle karşılaştırıldığında sağlıklı bir avantaj sunar.

for döngülerinin sağladığı güvenlik ve özlük, bunları Rust'ta en yaygın olarak kullanılan döngü yapısı haline getirir. Belirli bir sayıda kodu çalıştırmak istediğiniz durumlarda bile, Liste 3-3'te bir while döngüsü kullanmak yerine çoğu Rust programcısı bir for döngüsü kullanır. Bunu yapmak için, standart kütüphanenin sağladığı, belirli bir sayıdan başlayarak başka bir sayıya ulaşana kadar tüm sayıları sıralayan bir Range kullanabilirsiniz.

İşte geri sayımın bir for döngüsü ve henüz konuşmadığımız bir diğer yöntem olan rev ile ters çevrilmiş hali:

Dosya Adı: src/main.rs

{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-34-for-range/src/main.rs}}

Bu kod biraz daha hoş, değil mi?

Özet

Başardınız! Bu, büyük bir bölümdü: değişkenler, skalar ve karmaşık veri türleri, işlevler, yorumlar, if ifadeleri ve döngüler hakkında bilgi edindiniz!

ipucu

Bu bölümde tartışılan kavramlarla pratik yapmak için, aşağıdakileri yapmaya yönelik programlar oluşturmayı deneyin:

  • Fahrenheit ve Celsius arasında sıcaklıkları dönüştürün.
  • n’inci Fibonacci sayısını üretin.
  • “Yılbaşı Günü” şarkısının sözlerini yazdırın, şarkının tekrarından faydalanın.

Hazır olduğunuzda, Rust'ta yaygın olarak diğer programlama dillerinde bulunmayan bir kavramdan bahsedeceğiz: sahiplik.