8. Denetim Yapıları

Bu bölümde Ruby'nin denetim yapılarını açıklayacağız.

case

case deyimini bir dizi koşulu test etmek için kullanırız. Bu yapı, C ve Java 'daki switch'e çok benzer ancak birazdan da göreceğiniz gibi ondan biraz daha güçlüdür.

ruby> i=8
ruby> case i
    | when 1, 2..5
    |   print "1..5\n"
    | when 6..10
    |   print "6..10\n"
    | end
6..10
   nil

2..5, 2 ile 5 arasındaki sayı aralığını ifade eder. Sonraki ifade, i değişkeninin bu aralığa düşüp düşmediğini sınar:

(2..5) === i

case aynı anda birden çok koşulu sınamak için === ilişki işleçini kullanır. Ruby'nin nesneye yönelik yapısını korumak için === işleci nesneye uygun olarak yorumlanır. Örneğin aşağıdaki kodda ilk when'de dizgelerin eşitliği sınanırken ikinci when'de düzenli ifadenin eşleşmesi sınanıyor.

ruby> case 'abcdef'
    | when 'aaa', 'bbb'
    |   print "aaa or bbb\n"
    | when /def/
    |   print "/def/ icerir\n"
    | end
/def/ icerir
   nil
while

Ruby döngü oluşturmak için bir çok yola sahiptir, bununla birlikte ileriki bölümde doğrudan döngü kurmanıza yarayan yineleyicileri göreceksiniz.

while bir tekrarlanmış if'ten başka birşey değildir. while'ı daha önce kelime-tahmin oyunumuzda ve düzenli ifadeler yazılımımızda kullanmıştık (Düzenli İfadeler bölümüne göz atın); while koşul ... end ile çevrilmiş bir kod bloğu koşul doğru olduğu sürece tekrarlanmaktaydı. Ancak while ve if ayrı ifadeler olarak da kullanılabilir:

ruby> i = 0
   0
ruby> print "Sıfır.\n" if i==0
Sıfır.
   nil
ruby> print "Negatif.\n" if i<0
   nil
ruby> print "#{i+=1}\n" while i<3
1
2
3
   nil

Bazen bir sınama koşulunu olumsuzlamak istersiniz. unless bir olumsuzlandırılmış if, until ise olumsuzlandırılmış bir while'dır. Bunları deneyip tecrübe etmeyi size bırakıyoruz.

Bir döngüyü içerden kesmek için dört yol vardır. İlki C'deki gibi, döngüden tamamen çıkmamızı sağlayan break'tir. İkincisi (C'deki continue'ya benzeyen) döngünün başına atlayan next'tir. Üçüncüsü o anki yinelemeyi tekrar çalıştıran redo'dur. Aşağıda break, next ve redo arasındaki farkı açıklayan bir C kodu bulunuyor:

while (koşul) {
 label_redo:
   goto label_next;        /* ruby'nin "next"'i */
   goto label_break;       /* ruby'nin "break"'i */
   goto label_redo;        /* ruby'nin "redo"'su */
   ...
   ...
 label_next:
}
label_break:
...

Bir döngünün içinden çıkmak için dördüncü yol, return'dür. return sadece döngüden değil, döngüyü içeren yöntemden de çıkmamızı sağlar. Eğer bir bağımsız değişken verildiyse, yöntem çağrısına dönecektir; aksi halde nil döndürecektir.

for

C yazılımcıları for döngüsünün nasıl yapıldığını merak edeceklerdir. Ruby'nin for'u tahmin ettiğinizden biraz daha ilginçtir. Aşağıdaki döngü, her eleman için bir kere döner:

for eleman in dizi
  ...
end

Elemanlar bir değer aralığı olabilir (bu, döngü denildiğinde çoğu insanın anladığı şeydir):

ruby> for num in (4..6)
    |    print num,"\n"
    | end
4
5
6
   4..6

Elemanlar dizi gibi başka bir türden değerler olabilir:

ruby> for elt in [100,-9.6,"pickle"]
    |    print "#{elt}\t(#{elt.type})\n"
    | end
100    (Fixnum)
-9.6   (Float)
pickle (String)
   [100, -9.6, "pickle"]

Ancak ilerleme kaydediyoruz. for aslında each'i kullanmanın başka bir yoludur. Aşağıdaki iki biçim de aynı görevi görür:

# Eğer daha önce C ya da Java kullandıysanız aşağıdaki gibi
# birşey tercih edersiniz:
for i in collection
  ...
end

#  Smalltalk yazılımcısıysanız aşağıdaki gibi birşeyi tercih edersiniz:
collection.each {|i|
  ...
}

Yineleyiciler sık sık geleneksel döngülere tercih edilir; bir kere onları kullanmaya alıştığınızda ne kadar kolay olduklarını göreceksiniz.