Merhaba Arkadaşlar,
Ruby' nin güçlü olmasını sağlayan pek çok özellik vardır. block' lar bu güçlü özelliklerden birisidir. (Block' lar dışında Proc ve Lambda kavramları da mevcuttur ki bu konuları ve aralarındaki temel farklılıkları sonraki kod parçacıklarında ele alacağız)
Bir Block ile değişkene veya nesneye atayamadığımız kod parçalarını işaret edebilir ve bu isimsiz kod parçalarını metodlara parametre olarak taşıyabiliriz. Tabi burada yield anahtar kelimesinin önemli bir yeri vardır. Gelin konuyu aşağıdaki kod parçacığı ile anlamaya çalışalım.
Block' lar Ruby dilinde pek çok yerde kullanılmaktadır. each,select,detect gibi metodlar dahili olarak bu yapıyı kullanırlar. Block' ların lambda kullanımına göre olumlu yönde performans farkı olduğu ifade edilmektedir (Henüz ispat edecek kod parçacığı mertebesine ulaşamadım)
class Utility
def justDoIt
if !block_given? then #0 yield yerine bir block gelmediyse
puts "Block yok"
else
yield #1
yield
yield
end
end
def repeat(count) #2
raise 'Empty Block Error' if !block_given? #3 Exception firlatimi
count.times { yield } #4
end
def calculate (min,max) #5
for i in min..max do
yield i
end
end
end
if __FILE__==$0
puts "What is your motto?"
motto=gets
cevatKelle=Utility.new
cevatKelle.justDoIt{ puts motto }
cevatKelle.repeat(2) { puts "I love ruby" }
cevatKelle.repeat(2) #4 deki exception' in firlamasina neden olacak #7
total=0
cevatKelle.calculate(10,20) {|x,y| total+=x}
puts total
min,max,e=10,20,2
total=0
cevatKelle.calculate(min,max) {|x,y| total+=(x*e)} #e local degiskeni kullanilmistir
puts total
total=0
[1,3,5,7,9].each{ |i| total+=(i*2) } #8 each metodunda built-in block kullanimi
puts total
cevatKelle.justDoIt #6
end
Uygulamanın iki çalışma zamanı çıktısı söz konusudur. #7 deki satır kapalı iken denediğimizde aşağıdaki çıktıyı elde ederiz.
Ancak #7 deki satırı açtığımızda çalışma zamanına hata fırlatılmasından dolayı(bunun sebebi boş blok gönderilmesi ve #3 deki raise çağırımıdır) aşağıdaki çıktıyı elde ederiz.
Şimdi kod parçacığında neler olduğuna maddeler halinde kısaca bakalım.
- Utility sınıfı içerisinde justDoIt, repeat ve calculate isimli üç farklı fonksiyon yer almaktadır. Bu fonksiyonların ortak özelliği, gövdelerinde yield anahtar kelimesinin kullanılmış olmasıdır. Bu sayede metodların çağırıldığı yerlerde, süslü parantezler içerisine yazılan kod bloklarının yield olan yerlere gönderilmesi mümkün hale gelmektedir.
- #0 numaralı satırda block_given? çağrısı ile metoda bir bloğun gönderilip gönderilmediğine bakılır. Eğer gönderilen bir block varsa arka arkaya üç kez icra edilir. #1 ile başlayan yield anahtar kelimeleri sebebiyle gelen kod bloğunun arka arkaya üç kez çalıştırıması söz konusudur.
- #2 nuımaralı ve #5 numaralı satırlardaki metodlar block gönderilen fonskiyonların parametreler de alabileceğini göstermektedir.
- #3 numaralı satırda şu ana kadar ilk kez karşılaştığımız bir kod parçası söz konusudur. Aslında çalışma zamanına bir istisna(exception) fırlatılmaktadır(.Netçiler throw new Exception(""); olarak düşünebilirler) raise' den sonra gelen ifade istisna mesajı olarak düşünülebilir. Kod satırının sonunda Statement Modifier kullanıldığına dikkat edelim.
- Eğer yield kullanılan bir metoda kod bloğu gönderilmezse bu durumda herhangi bir işlem yapılmaz. Bu vaka repeat ve justDoIt metodlarında ele alınmıştır. #7 deki kod satırı açıldığında bir Exception fırlatıldığı görülür. #6 daki kod satırında ise istisna yerine ekrana "block yok" mesajı basılılır. Nitekim justDoIt metodu içerisindeki if...else...end ifadesi ile boş blok gönderilme vakası kontrollü bir şekilde ele alınmıştır.
- #8 Numaralı kod satırında built-in block kullanımına ait bir örnek verilmektedir. Daha önceden de bahsettiğimiz gibi each ve select benzeri fonksiyonlar içerisinde yield kullanımları dilin doğal yapısı gereği mevcuttur. Bu nedenle bir dizinin arkasından çağırılan each metodu için block gönderimi/kullanımı mümkün hale gelmiştir.
Konuyu biraz daha iyi anlamak adına aşağıdaki grafiğin de işe yarayacağını düşünüyorum. Görüldüğü üzere kod blokları ilgili metodlarda yield kullanılan yerlere taşınmaktadır.
Böylece geldik bir kod parçacığının daha sonuna. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.