Programming Ruby

The Pragmatic Programmer's Guide

Previous < Contents ^
Next >

Ruby.new



Aslen bu kitabı yazmaya başladığımızda, büyük bir planımız vardı (daha gençtik). Dile, sınıflardan ve nesnelerden başlayıp, asıl konunun özü olan sözdizimi detaylarıyla bitirmeyi istiyorduk. O zaman iyi bir fikir gibi görünüyordu. Herşeyden sonra, Ruby'deki hemen herşey bir nesne olduğu için öncelikle nesneler hakkında konuşmak daha uygun olacaktı.

Ya da biz öyle düşünmüştük.

Ne yazık ki, bir dili bu yolla tanımlamak zor bir hale dönüştü. Eğer daha önce dizgilerle, if deyimleriyle, atamalarla ya da diğer detaylarla karşılaşmadıysanız, sınıf örnekleri yazmak zor olacaktı. Böylece örneklerimize anlam kazandıracak düşük- seviyeli detayları korumaya karar verdik.

Böylece, başka bir büyük planla geldik (bizi hiçbirşey için 'pratik' olarak adlandırmayın). Hala Ruby'yi en başta tanımlamayı düşünüyorduk. Ancak bundan önce, bir çeşit basit mini- kılavuz niteliğinde, örneklerde kullandığımız, Ruby'nin özel genel programlama özelliklerini açıkladığımız kısa bir bölüm eklemeyi uygun gördük.

Ruby Is an Object-Oriented Language

Tekrar söyleyelim. Ruby gerçek bir nesneye-yönelik dildir. Yönlendirdiğiniz herşey ve bunların döndürdüğü sonuçlar birer nesnedir. Nedense birçok dil aynı iddiada olmasına rağmen, her birisinin nesneye-yönelik kavramının ne olduğuna dair değişik yorumları vardır ve kullandıkları içerikler farklı terminolojiye sahiptirler.

Öyleyse, detaylara girmeden önce, ilk olarak kullanacağımız terimlere ve notasyona bakalım.

Nesneye-yönelik kod yazarken genelde gerçek hayattaki model kavramlarına bakarsınız. Tipik olarak, modelleme işlemi sırasında, kodda temsil etmeniz gereken değişik kategoride şeyler olduğunu farkedeceksiniz. Bir müzik kutusunda, bir ``şarkı'' kavramı bir kategori oluşturabilir. Ruby'de bu birimleri simgelemek için bir sınıf tanımlamaya ihtiyacınız olacak. Bir sınıf, durumun (örneğin, şarkı ismi) karışımıdır ve metotlar bu durumları kullanır (şarkıyı çalmak için bir metot olabilir).

Bir kez bu sınıflara sahip olduğunuz zaman, her biri için bir dizi örnek (instance) yaratmak isteyeceksiniz. Song adında bir sınıf içeren bir müzik kutusu sistemi için, ``Ruby Tuesday,'' ``Enveloped in Python,'' ``String of Pearls,'' ``Small talk,'' gibi birçok popüler hiti içeren örnekleriniz olacaktır. Nesne kelimesini sınıf örneği ile dönüşümlü olarak kullanacağız (ancak tembel daktilograflar olarak ``nesne'' kelimesini daha sık kullanacağız).

Ruby'de bu nesneler, sınıfla ilişkilendirilmiş özel bir metot olan constructor çağırılarak yaratılırlar. Standart constructor new'dir.

song1 = Song.new("Ruby Tuesday")
song2 = Song.new("Enveloped in Python")
# and so on

İki örnek de aynı sınıftan olmasına rağmen, her ikisi de kendine özgü nitekilklere sahiptir. İlk olarak, her nesne kendine özgü bir nesne tanımlayıcısına (nesne id'si olarak kısaltılmıştır) sahiptir. İkinci olarak, her örneğe özgü değerlere sahip olan örnek değişkenler tanımlayabilirsiniz. Bu örnek değişkenler nesnenin durumunu tutarlar. Mesela şarkılarımızdan her biri şarkı ismini tutan bir örnek değişkene sahip olabilir.

Her sınıfla birlikte, örnek metotlar tanımlayabilirsiniz. Her metot, sınıfın içinden ve (erişebilirlik kısıtlamalarına bağlı olarak) dışından çağırabilinen fonksiyonel bir parçaya tekabül eder. Bu metotlar sırayla nesnenin örnek değişkenlerine, dolayısıyla nesnenin durumuna erişebilirler.

Metotlar, nesneye bir mesaj yollayarak uyandırılırlar. Bu mesaj metodun ihtiyacı olabilecek parametrelerle birlikte metodun ismini içerir.[Metot çağrımlarını mesaj formunda ifade etme fikri Smalltalk'tan gelir.] Bir nesne bir mesaj aldığı anda, buna tekabül eden bir metot olup olmadığına bakar. Eğer bulunursa, metot çalıştırılır. Eğer bulunamazsa, ... bundan daha sonra bahsedeceğiz.

Metotların ve mesajların görevleri karmaşık görünebilir, ama pratikte oldukça doğaldır. Birkaç metot çağrımına bakalım. (Kod örneklerindeki okların, ifadelerin geri dönüş değerlerine tekabül eden değerleri gösterdiğini hatırlayın.)

"gin joint".length » 9
"Rick".index("c") » 2
-1942.abs » 1942
sam.play(aSong) » "duh dum, da dum de dum ..."

Burada, periyottan önceki şey receiver, periyottan sonraki şey ise uyandırılacak metot olarak isimlendirilir. İlk örnek, bir dizginin uzunluğunu sorguluyor, ikincisi ise başka bir dizgiye, ``c'' harfinin indexini bulmasını istiyor. Üçüncü satır, sayının mutlak değerini hesaplıyor. Ve en sonunda, Sam'den bizim için bir sarkı söylemesini istiyoruz.

Ruby ile bir çok dil arasındaki büyük bir farkı belirtmekte yarar var. Örneğin (diyelim ki) Java'da bir sayının mutlak değerini ayrı bir fonksiyon çağırıp sayıyı göndererek bulurdunuz. Muhtemelen aşağıdaki gibi birşey yazardınız:

number = Math.abs(number)     // Java code

Ruby'de bir sayının mutlak değerini, basitçe, bir sayı nesnesine abs mesajı geçerek bulabiliriz.

number = number.abs

Bu tüm Ruby nesneleri için geçerlidir: C'deki strlen(name) yerine, Ruby'de name.length yazabilirsiniz. Ruby'nin kusursuz bir nesneye- yönelik dil olduğunu söylerken kastettiğimiz nokta buydu.

Some Basic Ruby

Çoğu insan yeni bir dil öğrenirken bir yığın sıkıcı sözdizimi kurallarını okumak istemezler. O yüzden biraz aldatmacaya gideceğiz. Bu bölümde Ruby ile program yazarken ihtiyacınız olan bazı şeylerden bahsederek ışıkların bir kısmını yakma yoluna gideceğiz. Daha sonra, sayfa 199'da başlayan Bölüm 18'de detaylara ineceğiz.

Basit bir Ruby programıyla başlayalım. Bir dizgiyi bir kişinin ismine ekleyen ve bu dizgiyi döndüren bir metot yazalım. Daha sonra bu metodu iki kez çalıştıracağız.

def sayGoodnight(name)
  result = "Goodnight, " + name
  return result
end

# Time for bed... puts sayGoodnight("John-Boy") puts sayGoodnight("Mary-Ellen")

Önce genel bir inceleme yapalım. Ruby'nin sözdizimi basittir. Her satır sonunda noktalı virgül koymanız gerekmez. Ruby'de yorum satırları # karakteriyle başlar ve satır sonuna kadar devam eder.

Metotlar, metot ismini (bu bölümdeki ``sayGoodnight'') takiben, parantez içinde metodun parametreleri yazılmak suretiyle def anahtar kelimesiyle tanımlanır. Basitçe end anahtar kelimesiyle sonra erdirilirler. Metodumuzun gövdesi oldukça basittir. İlk satır ``Goodnight,[visible space]'' dizgisini name ile verilen parametreye yapıştırır ve sonucu yerel değişkene atar. Sonraki satır sonucu çağırana döndürür. result değişkennini tanımlamadığımıza dikkat edin; atama yaptığımız anda otomatik olarak olşuturuldu.

Metodu tanımladıktan sonra iki kere çağırdık. İki durumda da sonucu bir altsatır karakteriniyle birlikte çıktı olarak veren puts metoduna geçtik.

Goodnight, John-Boy
Goodnight, Mary-Ellen

``puts sayGoodnight("John-Boy")'' satırı, biri sayGoodnight birisi de puts olmak üzere iki metot çağrımı içerir. Bir çağrımın argümanları parantezler içindeyken diğeri neden değil? Bu sizin seçiminize kalmış. Aşağıdaki satırların hepsi eşittir.

puts sayGoodnight "John-Boy"
puts sayGoodnight("John-Boy")
puts(sayGoodnight "John-Boy")
puts(sayGoodnight("John-Boy"))

Ancak hayat her zaman bu kadar kolay değil; öncelik kuralları hangi argümanın hangi metot çağrımında kullanılacağını belirleme işini biraz zorlaştırabiliyor; bu yüzden her zaman parantez kullanmanızı öneriyoruz.

Bu örnek ayrıca Ruby'nin bazı dizgi nesnelerini de gösterir. Bir dizgi nesnesi yaratmak için bir sürü yol vardır; ama en çok kullanılanı dizgi literalleridir: tek ya da çift tırnak arasında bazı farklar bulunmaktadır. Tek tırnaklı durumda, Ruby daha az iş yapar. Çok az istisna dışında, literalin içine ne yazarsanız, dizginin değerie karşılık gelecektir.

Çift tırnaklı durumda, Ruby daha çok iş yapar. Öncelikle yer değiştirmek için---ters bölü karakteriyle başlayan dizilere---bakar ve bazı ikilik değerlerle yer değiştirir. Bu değerlerden en çok kullanılanı, yeni satır karakteriyle değiştirilen ``\n'''dir. Bir dizgi, çıktısında bir yeni satır karakteri içeriyorsa ``\n'' bir alt satıra geçilmesini sağlar.

puts "And Goodnight,\nGrandma"
produces:
And Goodnight,
Grandma

Ruby'nin çift tırnakla yaptığı ikinci şey, ifade enterpolasyonudur. Dizginin içindeki #{ ifade } ifadesi, ifade'nin değeriyle değiştirilir. Bunu önceki ifademizi yeniden yazmak için kullanabiliriz.

def sayGoodnight(name)
  result = "Goodnight, #{name}"
  return result
end

Ruby, bu dizgi nesnesini hazırlayacağı zaman, öncelikle name'in mevcut değerine bakar ve dizgidekiyle yer değiştirir. #{...} yapısının içinde, gelişigüzel karmaşık ifadeler kullanabilirsiniz. Bir kısayol olarak; eğer ifade global ya da örnek değişkense, ya da sınıf değişkeniyse, parantez koymanız gerekmez. Dizgiler hakkında daha fazla bilgi için, diğer Ruby standart tiplerinin de anlatıldığı, sayfa 47'den başlayan Bölüm 5'e bakabilirsiniz.

Son olarak, bu metodu biraz daha basitleştirebiliris. Bir Ruby metodunun döndürdüğü değer, değerlendirilen son ifadenin değeridir, böylece return ifadesinden kurtulmuş oluruz.

def sayGoodnight(name)
  "Goodnight, #{name}"
end

Bu bölümün genel bir bilgi verme amacı güttüğünden bahsettik. Bahsedeceğimiz bir konu daha var: Ruby isimleri. Bilgi vermek açısından, (sınıf değişkenleri gibi), burada açıklamayacağımız bazı terimler kullanacağız. Her ne kadar, kurallar hakkında şimdiden konuşmaya başlasak da, daha sonra örnek değişkenleri tartışacağımız zaman oyunda önde olacaksınız.

Ruby, isimlerin kullanışından ayırt edilebilen bir gelenek uygular: bir ismin ilk karakteri onun nasıl kullanılacağını belirler. Yerel değişkenler, metot parametreleri ve metot isimleri ya bir alt çizgiyle ya da küçük harfle başlamalıdırlar. Global değişkenler dolar işareti ($) ile ilişkilendirilirken, örnek değişkenler sayangoz (@) işaretiyle başlarlar. Sınıf değişkenleri iki salyangoz işareti (@@) ile başlar. Son olarak, sınıf isimleri, modül isimleri ve sabit isimleri büyük harfle başlamak zorundadırlar. Değişik isimlerin örnekleri sayfa 10'da Tablo 2.1'de gösterilmiştir.

İlk harfi takiben, bir isim harflerin, rakamların ve alt çizgilerin kombinasyonundan oluşmalıdır () Following this initial character, a name can be any combination of letters, digits, and underscores (bu şarta göre, @ karakterini takip eden karakterler rakam olmayabilir).

Değişken ve sınıf isimlerine örnekler
Değişkenler Sabitler ve
Yerel Global Örnek Sınıf Sınıf isimleri
name $debug @name @@total PI
fishAndChips $CUSTOMER @point_1 @@symtab FeetPerMile
x_axis $_ @X @@N String
thx1138 $plan9 @_ @@x_pos MyClass
_26 $Global @plan9 @@SINGLE Jazz_Song

Diziler ve Hash'ler

Ruby'nin dizileri ve hash'leri indekslenmiş öbeklerdir. Nesne öbeklerine, bir anahtar yardımıyla erişilebilir. Dizilerde, bu anahtar bir rakamken, hash'lerde herhangi bir nesne olabilir. Hem diziler hem de hash'ler yeni elemana ihtiyaç duyduklarında genişleyebilmektedir. Dizileri kullanmak daha verimliyken, hash'ler daha esnek bir yapı sağlar. Hem diziler hem de hash'ler değişik tipten nesneleri tutabilir; bir kaç dakika sonra göreceğimiz gibi hem sayı, hem dizgi hem de ondalık sayı tutan bir diziye sahip olabilirsiz.

Dizi literali sayesinde---köşeli parantezler arasında bir takım elemanlar--- yeni bir dizi yaratabilir ve hazırlayabilirsiniz. Bir dizi nesnesine, köşeli parantezler arasına, aşağıdaki örnekte görüldüğü gibi bir index değeri girerek ulaşabilirsiniz.

a = [ 1, 'cat', 3.14 ]   # array with three elements
# access the first element
a[0] » 1
# set the third element
a[2] = nil
# dump out the array
a » [1, "cat", nil]

Dizi literalini hiç eleman olmadan kullanarak ya da dizi nesnesinin hazırlayıcısını (constructor) Array.new kullanarak boş bir dizi yaratabilirsiniz. .

empty1 = []
empty2 = Array.new

Kelimelerin dizilerini yaratmak, tüm virgül ve kotalarla birlikte, bazen bir azaba dönüşebilmektedir. Neyse ki, bir kısayol var: %w tamı tamına istediğimizi yapar.

a = %w{ ant bee cat dog elk }
a[0] » "ant"
a[3] » "dog"

Ruby hash'leri dizilere benzer. Bir hash literali, köşeli parantezler yerine süslü parantezleri kullanır. Literal her giriş için iki nesne almalıdır: bir tanesi anahtar için, bir tanesi de değer için.

Örneğin, orkestra için müzikal aletleri haritalamak istiyorsunuz. Bunu bir hash kullanarak kolaylıkla yapabilirsiniz.

instSection = {
  'cello'     => 'string',
  'clarinet'  => 'woodwind',
  'drum'      => 'percussion',
  'oboe'      => 'woodwind',
  'trumpet'   => 'brass',
  'violin'    => 'string'
}

Hash'ler de tıpkı dizilerdeki gibi köşeli parantez notasyonuyla indekslenmiştir.

instSection['oboe'] » "woodwind"
instSection['cello'] » "string"
instSection['bassoon'] » nil

Son örnekte de görüldüğü gibi, bir hash içermediği bir anahtar indeksiyle karşılaşırsa nil değerini döndürür. Koşul ifadelerinde nil, false ile aynı anlama geldiği için, bu durum uygundur. Bazen varsayılan bu durumu değiştirmek isteyebilirsiniz. Örneğin, her anahtarın kaç kere olduğunu saymak için bir hash'e sahipseniz o zaman tüm varsayılan değerlerin sıfır olması daha uygun olacaktır. Bunu yeni, boş bir hash yarattığınızda varsayılan bir değer atayarak kolayca yapabilirsiniz.

histogram = Hash.new(0)
histogram['key1'] » 0
histogram['key1'] = histogram['key1'] + 1
histogram['key1'] » 1

Diziler ve hash'ler kullanışlı birçok metoda sahiptir: sayfa 33'de başlayan tartışmaya bakın ve detaylar için sayfa 278 ve 317'de başlayan başvuru kısımlarına göz atın.

Kontrol Yapıları

Ruby if deyimleri ve while döngüleri gibi kullanışlı tüm kontrol yapılarına sahiptir. Java, C ve Perl programcıları bu ifadelerdeki parantez eksikliğini yakalayacaklardır. Ruby, ifadelerin gövdesinin bittiğini belirtmek için end anahtar kelimesine sahiptir.

if count > 10
  puts "Try again"
elsif tries == 3
  puts "You lose"
else
  puts "Enter a number"
end

Benzer olarak, while ifadeleri de end ile sona ermektedir.

while weight < 100 and numPallets <= 30
  pallet = nextPallet()
  weight += pallet.weight
  numPallets += 1
end

Ruby'nin ifade değiştiricileri (statement modifiers), eğer if ya da while ifadelerinin gövdeleri tek bir ifadeden oluşuyorsa kullanışlı bir kısayol olacaktır. Basitçe, if ya da while'ı takiben ifadeyi, sonra da koşulu yazın. Örneğin, aşağıda basit bir if deyimi bulunuyor.

if radiation > 3000
  puts "Danger, Will Robinson"
end

Bu da yukarıdakinin aynısı, ancak ifade değiştiricisiyle yeniden yazıldı:

puts "Danger, Will Robinson" if radiation > 3000

Benzer olarak, bir while döngüsü

while square < 1000
   square = square*square
end

daha kısa hale geliyor:

square = square*square  while square < 1000

Bu ifade değiştiricileri Perl programcılarına tanıdık gelecektir.

Düzenli İfadeler

Ruby'nin birçok built-in tipleri, çoğu programcıya tanıdık gelecektir. Çoğu programlama dili, dizgiler, tamsayılar, ondalık sayılar, diziler ve benzeri birçok kavram içerir. Ancak Ruby ortaya çıkana kadar, düzenli ifade desteği sadece Perl, Python, awk gibi betik dillerinde bulunuyordu. Bu bir utançtı: çünkü düzenli ifadeler metinle çalışmak için çok kullanışlı ve güçlü bir araçtır.

Kitabın birçok kısmında düzenli ifadelerden (örneğin, Mastering Regular Expressions 'da) bahsedilmiştir, o yüzden düzenli ifadelerle ilgili herşeyi küçücük bir bölümde anlatmaya çalışmayacağız. Düzenli ifadelerle ilgili birkaç örneğe bakacağız; düzenli ifadelerle ilgili daha fazla bilgiyi sayfa 56'dan itibaren bulacaksınız.

Düzenli ifadeler, bir dizginin içinde belli bir şablona uyan karakterleri bulmanın basit bir yoludur. Ruby'de, basitçe, bölü işaretleri arasına bir şablon yazarak /şablon/ bir düzenli ifade yaratabilirsiniz. Ve, Ruby Ruby olalı, tabii ki düzenli ifadeler de birer nesnedir ve bu şekilde kullanılabilirler.

Örneğin bir dizgide ``Perl'' ya da ``Python'' kelimelerini bulan bir şablonu aşağıdaki düzenli ifadeyle bulabilirsiniz:

/Perl|Python/

Dıştaki bölü işaretleri şablonu sınırlar ve aranan iki şey olduğu için boru karakteri (``|'') bu ifadeleri ayırır. Şablonla birlikte, aritmetik ifadelerde olduğu gibi parantez de kullanabilirsiniz, örneğin yukarıdaki ifadeyi aşağıdaki gibi yazmak mümkündür:

/P(erl|ython)/

Ayrıca şablonlarla tekrarlama olayını da özelleştirebilisiniz. /ab+c/ ifadesi ``a'' ile başlayıp bir ya da daha fazla ``b''yi takiben ``c'' karakteri içeren dizgileri arar. Artı işaretini, yıldız işaretiyle değiştirmek bize ``a''yı takiben sıfır ya da daha fazla ``b'' ve bir ``c'' karakterini arayan bir düzenli ifade verir.

Ayrıca bir grup karakteri tek bir şablonda eşleştirebilirsiniz. Bazı genel örnekler, beyaz boşluk karakterlerini (boşluk, tab, yeni satır vb.) ifadeleri eşleştiren ``\s'' gibi ya da rakamları eşleştiren ``\d'' ya da tipik bir kelimedeki her karakteri eşleştiren ``\w'' gibi karakter sınıflarına sahiptir. ``.'' karakteri her karakter yerine geçmektedir.

Tüm bunları elverişli düzenli ifadeler hazırlamakta kullanabiliriz.

/\d\d:\d\d:\d\d/     # a time such as 12:34:56
/Perl.*Python/       # Perl, zero or more other chars, then Python
/Perl\s+Python/      # Perl, one or more spaces, then Python
/Ruby (Perl|Python)/ # Ruby, a space, and either Perl or Python

Bir kere bir şablon yarattınız mı, onu kullanmamak akılsızlık olur. ``=~'' operatörü bir dizgiyle bir düzenli ifadeyi eşleştirmek için kullanılabilir. Eğer bir şablon bulunursa, ``=~'', ifadenin başlangıç pozisyonunu, aksi halde nil değerini döndürür. Bu da düzenli ifadeleri if ve while ifadelerinde kullanabilceğiniz anlamına gelir. Örneğin aşağıdaki kod parçası bir metinin içinde 'Perl' ya da 'Python' geçtiğinde bir mesaj göstermektedir.

if line =~ /Perl|Python/
  puts "Scripting language mentioned: #{line}"
end

Düzenli ifadeler ile belli bir şablona uyan bir dizginin bir kısmını, Ruby'nin yer değiştirme metotlarıyla değiştirebilirsiniz.

line.sub(/Perl/, 'Ruby')    # replace first 'Perl' with 'Ruby'
line.gsub(/Python/, 'Ruby') # replace every 'Python' with 'Ruby'

Kitabın ilerleyen kısımlarında düzenli ifadelerden daha çok söz edeceğiz.

Blocks and Iterators

Bu kısımda, Ruby'nin belli başlı güçlerinden biri olan kod bloklarından bahsedeceğiz. Özellikle parametreyseler büyük kod bloklarını metot ??invocations??larıyla ilişkilendirebilirsiniz. Bu gerçekten çok güçlü bir özelliktir. Kod bloklarını geriçağrıları (callback) gerçekleştirmek için (ancak Java'nın anonim inner sınıflarından daha basit bir yapıya sahiptirler), iri kod parçalarını geçmek için (ancak C'nin fonksiyon göstericilerinden daha esnektir) ve tekrarlayıcıları (iterators) gerçekleştirmek için kullanılır.

Kod blokları parantezler ya da do...end arasındaki iri kod parçalarından başka birşey değildir.

{ puts "Hello" }       # this is a block

do                     #   club.enroll(person)  # and so is this   person.socialize     # end                    #

Bir kod bloğu yarattıktan sonra, bunu bir metot çağrısıyla ilişkilendirebilirsiniz. Böylece Ruby'nin yield deyimini kullanarak kod bloğunu bir ya da daha çok kez çalıştırabilirsiniz. Aşağıda bu durumu gösteren bir örnek bulunuyor. İki kere yield çağrısı yapan bir metot tanımlıyoruz. Çağrıdan sonra (ve metodun ihtiyacı olan tüm argümanlardan sonra), aynı satıra bir blok koyarak çağırıyoruz. [Bazı insanlar bir bloğun bir metotla olan ilişkisini parametre geçişi ile bağdaştırmayı seviyorlar. Bu bir derece doğrudur, ancak tüm hikaye bundan ibaret değildir. Blokları ve metotları, kontrolü birbirleri arasında değiş tokuş eden kavramlar olarak düşünebilirsiniz.]

def callBlock
  yield
  yield
end

callBlock { puts "In the block" }
produces:
In the block
In the block

Bloktaki kodun (puts "In the block"), her biri için bir yield olmak üzere nasıl iki kez çalıştırıldığına dikkat edin.

yield'i çağrırken parametreler ile bloğa geçilmesini sağlayabilirsiniz. Kod bloğunun içinde, boru işaretleri (``|'') arasına bu parametreleri alacak argümanların isimlerini listeleyerek bu işi kolaylıkla gerçekleştirebilirsiz.

  def callBlock
    yield , 
  end

callBlock { |, | ... }

Kod blokları, Ruby kütüphanesinde tekrarlayıcıları: dizi gibi herhangi bir veri topluluğundan üst üste eleman döndürme işini gerçekleştirmek için kullanılmıştır.

a = %w( ant bee cat dog elk )    # create an array
a.each { |animal| puts animal }  # iterate over the contents
produces:
ant
bee
cat
dog
elk

Önceki örneğimizde Array sınıfının each tekrarlayıcısını nasıl kullandığımıza dikkat edelim. each tekrarlayıcısı, bir döngü içerisinde dizinin her elemanı için bir yield kullanıyormuşuz gibi davranır. Sözde kodda bu durumu aşağıdaki gibi betimleyebiliriz:

# within class Array...
def each
  for each element
    yield(element)
  end
end

Böylece bir blok oluşturarak dizinin elemanlarını each metoduyla tekrarlayabilirsiniz. Bu blok, her dönüşte her bir elamanı çağırmak için kullanılabilir.

[ 'cat', 'dog', 'horse' ].each do |animal|
  print animal, " -- "
end
produces:
cat -- dog -- horse --

Basitçe, C ve Java gibi dillerde görülen döngü yapıcıları; Ruby'de, bir kod bloğunun sıfır ya da daha çok kez tekrarlanmasıyla gerçekleştirilen basit metot çağrılarına karşılık gelir.

5.times {  print "*" }
3.upto(6) {|i|  print i }
('a'..'e').each {|char| print char }
produces:
*****3456abcde

Yukarıda, 5 rakamına bir bloğu 5 kez çağırmasını istiyoruz ve 3 rakamına, 6'ya ulaşana kadar üst üste bir bloğu çağırmasını söylüyoruz. Son olarak ``a'' ile ``e'' arasındaki karakterlerden each metodunu kullanarak bir blok çağırmasını istiyoruz.

Reading and 'Riting

Ruby geniş bir Girdi/Çıktı kütüphanesiyle beraber gelir. Ancak bu kitaptaki çoğu örnekte, basit metotlara sadık kalacağız. Daha önce çıktı için kullanılan iki metotla karşılaşmıştık. puts argümanlarının her birini yeni bir satır koyarak yazarken, print metodu argümanları yeni satır olmadan yazar. İkisi de, herhangi bir G/Ç nesnesine yazabilir, ancak öntanımlı olarak konsola yazarlar.

Çok kullandığımız diğer çıktı metotlarından birisi de, dizgileri belirli bir biçime göre (C ya da Perl'deki printf metodu gibi) kontrol eden printf metodudur.

printf "Number: %5.2f, String: %s", 1.23, "hello"
produces:
Number:  1.23, String: hello

Bu örnekte, "Number: %5.2f, String: %s" dizgisi, printf'e bir kayan noktalı sayı (noktadan sonra iki, toplamda beş karakter olmak üzere) ve bir dizgi yazacağını belirtir.

Programınızdan girdi oluşturmak için birçok yol bulunur. Muhtemelen en çok kullanılan rutin, programın bir sonraki girdi akışını döndüren gets metodudur.

line = gets
print line

gets rutininin başka bir işlevi daha bulunur: aldığı satırı döndürdüğü gibi, aynı zamanda global bir değişken olan $_'un içine de yerleştirir. Bu, birçok durumda varsayılan argüman olarak da kullanılan özel bir değişkendir. Eğer print'i hiç argüman olmaksızın çağırırsanız, size $_ değişkenin içeriğini basacaktır. Eğer koşul olarak sadece bir düzenli ifade içeren bir if ya da write ifadesi yazarsanız bu ifade $_ ile eşleştirilir. Bazı puristler tarafından barbarizm olarak adlandırılsa da, bu kısaltmalar özlü programlar yazmanıza yardımcı olacaktır. Örneğin aşağıdaki program, girdi akışındaki tüm ``Ruby'' kelimesi içeren satırları ekrana yazar:

while gets           # assigns line to $_
  if /Ruby/          # matches against $_
    print            # prints $_
  end
end

Bunu yazmak için izleyeceğimiz ``Ruby yolu'', tekrarlayıcı kullanmak olmalıdır.

ARGF.each { |line|  print line  if line =~ /Ruby/ }

Yukarıda, bir program tarafından okunabilen bir girdi akışını simgeleyen, önceden tanımlı bir nesne olan ARGF'i kullandık.

Onward and Upward

İşte bu kadar. Ruby'nin bazı basit özelliklerinden bahsettiğimiz turumuzu ışık-hızıyla bitirdik. Bu kısa turda; nesnelere, metotlara, dizgilere, düzenli ifadelere, bazı kontrol yapılarına ve tekrarlayıcılara göz attık. Artık, kitabın geri kalan kısmına saldırmanız için elinizde yeterli koz bulunduna inanıyoruz.

Zaman ilerledi, ve bir üst kademeye geldik. İleriki bölümde Ruby'nin candamarı olan sınıflara ve nesnelere bakacağız.


Previous < Contents ^
Next >

Extracted from the book "Programming Ruby - The Pragmatic Programmer's Guide"
Copyright © 2001 by Addison Wesley Longman, Inc. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at http://www.opencontent.org/openpub/)).

Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder.

Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.