29 Haziran 2014 Pazar

Ruby Programlama Dili Deyim ve İfade Kuralları

  1. Fonksiyon Yan Etkisi

Fonksiyon yan etkisi, bir fonksiyon kendisine iki yönlü parametre verilen değişkenin veya yerel olmayan bir değişkenin değerini değiştirdiğinde gerçekleşir [1].


Ruby'de fonksiyona verilen parametrenin değeri değişmez. Çünkü Ruby'de fonksiyona parametrenin sadece değeri geçirilir [2]. Aşağıdaki örnekte a değişkeninin değeri arttir fonksiyonu cagrildiktan sonra bile 1 olarak kalır.


def arttir(deger)
 deger += 1
end

a = 1;
arttir(a);
puts a;


Global bir değişkenin çağrımı durumunda ise Ruby'de operandların nasıl değerlendirileceği (associativity) önceden belirlenmiştir. Aritmetik işlemler için operandlar her zaman soldan sağa değerlendirilir [3]. Yani aşağıdaki örnekte b değişkeninin değeri hesaplanırken önce $a global değişkenin değeri olan 1 alınır. Daha sonra fun metodu cagrilir. fun metodu a'nın degerini 2 olarak değiştirir ve ve bunu döner. En sondaki $a değişkeninin değeri ise 2 olarak hesaplanır. Böylece b=1+2+2=5 olarak hesaplanır. Operandların aritmetik işlemlerde her zaman soldan sağa işleneceği garanti altına alındığı için fonksiyonel yan etki Ruby'de problem değildir.


$a = 1;

def fun
 $a += 1;
 return $a;
end

b = $a + fun + $a;
puts b;


  1. Kısa Devre İfadeleri

Ruby'de kısa devre ifadeleri desteklenmektedir [4,5] Aşağıdaki örnekte “hello” metninin ekrana basılması a && b=1 koşuluna bağlanmıştır. a değişkeni mantıksal (boolean) bir ifadeyken b ise sayı tutar ve ifade içinde b=1 ataması yapılmaktadır. Bu mantıksal ifadede a değişkeni false olduğunda ikinci kısmı yani atamayı işletmeye gerek yoktur. Bu durumda a değişkeni false olduğunda b'ye 1 ataması yapılmaz, true olduğunda ise 1 ataması yapılır.


a = false;
b = 0;

puts "hello" if a && b=1;  # assign b=1 if a is true
puts b; # b is 0

  1. Tip Dönüşümleri



Ruby'de tip dönüşümleri örtülü (implicit,coercion) veya açık (explicit) şekilde olabilir.


    • Örtülü (Implicit) Tip Dönüşümleri


Ruby'de iki farklı tipteki veri tipi üzerinde aritmetik işlem yapılmak istendiğinde otomatik olarak tip dönüşümünü sağlamak için tip üzerinde tanımlı coerce() metodu çağrılır. Tüm numerik tiplerde coerce() metodu dilde tanımlanmıştır. Programcının tanımladığı sınıflarda coerce() metodu tanımlanarak örtülü tip dönüşümleri sağlanabilir [6].


puts 1/2; # sonuc 0 int/int
puts 1/2.0 # sonuc 0.5 int/float. 1 --> 1.0'a donusturulur.


Örtülü tip dönüşümlerinde genlde büyük olan veri tipine doğru bir dönüşüm gerçekleşir.

    • Açık (Explicit) Tip Dönüşümleri


Ruby'de to_s(), to_f(), to_i() gibi metodlarla açık bir şekilde tip dönüşümü desteklenir [6].


puts 125.to_s
puts "12.111".to_i; #12
puts "13".to_f;
puts "12".to_r;
puts "13".to_c;
puts "Jane".to_sym;


Aşağıdaki örnekte ise bir String metni split metodu ile diziye çevrilmektedir.


v = "Ruby Python Tcl PHP Perl".split;
puts v.class;


  1. Operatörler

Operatör, bir ya da daha fazla operand üzerinde gerçekleşecek operasyonu (toplama, karşılaştırma vb.) gösteren bir tokendir [3]


Ruby'deki Operatörler öncelikleri yüksekten alçağa doğru sıralanmış şekilde Tablo-1'de gösterilmiştir. Tabloda N, operatörün kaç değişkenli olduğunu gösterir; A: aynı önceliğe sahip operatörler bulunduğunda değerlendirme (associativity) sırasını belirtir. L soldan sağa, R sağdan sola değerlendirmeyi ifade eder. M ise operatörün tekrar tanımlanıp tanımlanamayacağını (overload) belirtir [3]. Tabloda belirtilmese de parantezlerin önceliği en yüksektir.

Tablo 1: Ruby'de Operatörler [3]


Bu tablodaki öncelikleri dikkate alarak 1+2*3 ifadesini hesaplarsak, iki operand için * operatörünün önceliği +'ya göre daha yüksektir ve 2*3 işlemi toplamadan önce hesaplanır. Daha sonra toplama işlemi yapılır. Bu durumda işlemin sonucu 7 olacaktır. Aşağıda bazı aritmetik işlemler ve sonuçları örnek olarak verilmiştir:

puts 1 + 2*3;    # 7
puts 2**3;       # 8
puts 6%5;        # 1
puts 1==1.0;     # true


  1. Operatör Yeniden Tanımlama (Overloading)

Ruby'de hem standart tipler için hem de programcı tanımlı sınıflar için  operator overloading mümkündür [7,8].  Aşağıdaki örnekte String'lerdeki << operatörünün anlamı değiştirilmiştir.


class String
 def <<(value)
   self.replace(value + self)
 end
end

str = "Hello, ";
str << "World." # World.Hello,
puts str


Aşağıdaki örnekte de String için ** (kare alma) operatörünü tanımlanmıştır.


class String
 def **(value)
   square = self.length**value;
   self*(square/self.length);
 end
end
puts "aa"**3; #aaaaaaaa


[1] Sebesta, R.W., Concepts of Programming Languages, Pearson Education, 2012.


[2] “Ruby - Parameters by reference or by value”, 3 Nisan 2014,  http://stackoverflow.com/a/22827949/878710. [Erişim Tarihi: 27 Nisan 2014].


[3] Flanagan D., Matsumoto Y., The Ruby Programming Language, O'Reilly Media, 2008.


[4] "Short-circuit evaluation”, http://en.wikipedia.org/wiki/Short-circuit_evaluation . [Erişim Tarihi: 27 Nisan 2014].


[5] Kumar R. S., "Short circuit evaluation in ruby", 14 Mayıs 2013, http://blog.revathskumar.com/2013/05/short-circuit-evaluation-in-ruby.html. [Erişim Tarihi: 27 Nisan 2014].


[6] “Ruby Data Types”,  ZetCode, http://zetcode.com/lang/rubytutorial/datatypes/ . [Erişim Tarihi: 24 Nisan 2014].


[7] Robert Klemme, "The Complete Numeric Class", Ruby Best Practices, 20 Şubat 2010, http://blog.rubybestpractices.com/posts/rklemme/019-Complete_Numeric_Class.html. [Erişim Tarihi: 24 Nisan 2014].

[8] Philip De Smedt , "Operator Overloading in Ruby", Ruby Snippets, http://rubysnippets.com/2013/01/25/operator-overloading-in-ruby/. [Erişim Tarihi: 24 Nisan 2014].


NOT: YTÜ - İleri Programlama Dili Dersi 2014 1. Dönem Ödevi Çerçevesinde Hazırlanmıştır.

NOT 2: Ruby 1.9 baz alınmıştır.

Hiç yorum yok: