Örneklere Dönüş

Şimdi eski örneklere tekrar göz atalım.

Aşağıdakini daha önce Basit Örnekler kısmında görmüştük.

def fact(n)
  if n == 0
    1
  else
    n * fact(n-1)
  end
end
print fact(ARGV[0].to_i), "\n"

Bu bizim ilk örneğimiz olduğu için her satırı teker teker açıklayalım.

Faktöriyeller

def fact(n)  

İlk satırda bir işlev (ya da daha özel olarak bir yöntem; yöntemin ne olduğunu ileriki kısımlarda göreceğiz) tanımlamak için def deyimini kullanıyoruz. Burada işlevimiz fact'ın n adında tek bir argüman aldığını görüyoruz.

if n == 0

if bir denetim deyimidir. Eğer koşul sağlanıyorsa onu takip eden kod değerlendirilir, aksi taktide else kısmına geçilir.

1

Eğer koşul sağlandıysa if'in değeri 1 olacaktr.

else

Sağlanmadıysa, bu deyimle başlayan end ile biten kod parçası değerlendirilir.

n * fact(n-1)

Yani, eğer koşul sağlanmamışsa sonuç n kere fact(n-1) olacaktır.

end

İlk end, if deyimini kapatmak için kullanılır.

end

İkinci end def ifadesini kapatmak için kullanılır.

print fact(ARGV[0].to_i), "\n"  

Bu bizim komut satırından fact() işlevini çalıştırmamızı ve sonuçları ekranda görmemizi sağlar.

ARGV komut satırı argümanlarını içeren özel bir dizidir. ARGV dizisinin tüm elemanları dizgeler olduğu için, to_i yöntemiyle tamsayıya dönüştürmek zorundayız. Ruby Perl'deki gibi dizgeleri tamsayılara kendiliğinden dönüştürmez.

Hmmm... Eğer bu yazılıma negatif bir sayı girersek ne olur? Sorunu görebildiniz mi? Peki düzeltebilir misiniz?

Dizgeler

Dizgeler bölümündeki bulmaca örneğimizi tekrar inceleyelim. Bu sefer biraz daha uzun, kolaylık açısından satırları numaralandırdık.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
words = ['kestane', 'gurgen', 'palamut']
secret = words[rand(3)]

print "tahmin et? "
while guess = STDIN.gets
  guess.chop!
  if guess == secret
    print "Bildin!\n"
    break
  else
    puts "Üzgünüm kaybettin.\n"
  end
  print "tahmin et? "
end
puts "Kelime ", secret, ".\n"

Bu yazılımda yeni bir denetim yapısı gördük: while. Verilen koşul doğru olduğu sürece while ve end arasındaki kod tekrar tekrar çalıştırılacaktır.

2. satırdaki rand(3) işlevi 0 ile 2 arasında rastgele sayı üretir. Bu rastgele sayı words dizisinin elemanlarından birini çıkarmak için kullanılır.

5. satırda STDIN.gets yöntemiyle standart girdiden bir satır okuduk. Eğer satırı alırken EOF (end of file) karakterine rastlanırsa gets işlevi nil değerini döndürecektir. while ile ilişkilendirilmiş kod ^D (ya da DOS altında ^Z) görene kadar tekrarlanacaktır.

6. satırdaki guess.chop! işlevi guess değişkeninin sonundaki satırsonu karakterini temizlemeye yarar.

15. satırda gizli kelimeyi yazdırıyoruz. Bunu üç argümanla birlikte bir yazdırma deyimi olarak kullandık (birbiri ardına yazdırılarak) ancak bunu daha verimli hale getirmek için secret yerine bir tek argüman alan #(secret) yöntemini tanımlayabilirdik:

puts "Kelime #{secret}.\n"   

Birçok yazılımcı, bu yolun çıktı vermek için daha açık olduğunu düşünürler. Tek bir dizge oluşturur ve bu dizgeyi puts'a tek bir argüman gibi sunar.

Standart betik çıktısında puts kullanma düşüncesini işledik, ancak bu betik 4. ve 13. satırlarda print'i de kullanır. Bu ikisi aynı şey değildir. print dizgeyi kendisine verildiği gibi çıktılarken, puts; aynı zamanda çıktı satırının sonlanmasını sağlar. 4. ve 13. satırlarda print kullanıldığı için, işleç bir sonraki satırın başlangıcına geçeceği yerde, işleci ekrana çıktılanan dizgenin yanında bırakır. Bu durum kullanıcı girdisi için tanınabilir bir durumdur. Aşağıdaki dört çıktı çağrısı da aynı sonucu verir:

#satırsonu karakteri yoksa, puts tarafından eklenir:
puts  "Tasi delen suyun kuvveti degil, damlalarin sürekliligidir."

#satırsonu karakteri print komutuna verilmelidir:
print "Tasi delen suyun kuvveti degil, damlalarin sürekliligidir.\n"

#çıktıyı + ile birleştirebilirsiniz:
print 'Tasi delen suyun kuvveti degil, damlalarin sürekliligidir.'+"\n"

# ya da birden fazla dizge vererek birleştirebilirsiniz:
print 'Tasi delen suyun kuvveti degil, damlalarin sürekliligidir.', "\n"

Düzenli İfadeler

Son olarak Düzenli İfadeler bölümündeki yazılımı inceleyeceğiz.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
st = "\033[7m"
en = "\033[m"

while TRUE
  print "str> "
  STDOUT.flush
  str = gets
  break if not str
  str.chop!
  print "pat> "
  STDOUT.flush
  re = gets
  break if not re
  re.chop!
  str.gsub! re, "#{st}\\&#{en}"
  print str, "\n"
end
print "\n"

4. satırda while'ın koşulu sonsuz döngüyü sağlamak için true yapılmıştır. Ancak döngüden çıkabilmek için 8. ve 13. satırlarda break kullandık. Bu iki break aynı zamanda if deyiminin niteleyicilerinden biridir. Bir if niteleyicisi sadece ve sadece koşul sağlandığı zaman sol yandaki terimini çalıştırır.

chop! için (9. ve 14 satıra bakın) hakkında söylenecek çok şey var. Ruby'de geleneksel olarak yöntem isimlerinin sonuna '!' ya da '?' ekleriz. Ünlem işareti (! bazen "bang!" diye söylenir) potansiyel olarak yıkıcı bir görev görür, daha da açmak gerekirse; dokunduğu değeri değiştiren bir işleçtir. chop! bir dizgeye doğrudan etki eder ancak ünlem işareti olmayan bir chop bir kopya üzerinde çalışır. Aşağıda ikisi arasındaki fark görülüyor:

 ruby> s1 = "forth"
  "forth"
ruby> s1.chop!       # Bu s1'in değerini değiştirir.
  "fort"
ruby> s2 = s1.chop   # s2'ye değiştirilmiş bir kopyasını koyar.
  "for"
ruby> s1             # ... s1'e dokunmaz.
  "fort"

İlerde sonunda soru işareti olan yöntem isimleriyle karşılaşacaksınız (? genelde "huh?" şeklinde telaffuz edilir). Bu true ya da false döndüren bir 'doğrulama' yöntemidir.

15. satırda dikkat edilmesi gereken önemli bir uyarı yer almaktadır. Öncelikle gsub!'in başka bir sözde 'yıkıcı' yöntem olduğuna dikkat edelim. re'ye uyan her ne varsa str'nin yerine koyar (sub ikame etmekten (substitute), g ise globalden gelir); sadece ilk bulunanı değil, dizgedeki tüm eşleşen kısımları değiştirir. Çok iyi, çok güzel; fakat eşleştirilen kısımları neyle değiştireceğiz? 1. ve 2 satırda önalan ve artalan renklerini peşpeşe değiştiren st ve en adlı iki dizge tanımladık. 15. satırdaysa bunları, olduğu gibi yorumlandıklarından emin olmak için #{} arasına yazdık (değişken isimlerinin yazdırıldığını görmeyiz). Bunların arasında da "\\&" kodunu görüyoruz. Bu küçük bir hiledir. Yer değiştirilen dizge çift tırnak arasında olduğu için bir çift ters bölü işareti tek bir taneymiş gibi yorumlanır. Böylece gsub!'in göreceği şey "\&" olur ve bu da ilk konumda ne eşleştirildiyse onu gösteren özel bir koda dönüştürülür. Yani yeni dizge eşleşen parçaları farklı renkte gösterilen eski dizge olur.