Ruby'de +, -, *, ==, < gibi operatörlerin çoğu aslında metottur: 5 + 3 yazdığınızda 5 nesnesinin + metodu 3 argümanıyla çağrılır. Bu yüzden bir operatörün nasıl davranacağını sol taraftaki nesnenin sınıfı belirler ve kendi sınıflarınızda operatörleri tanımlayabilirsiniz. &&, ||, and, or ve not gibi mantıksal operatörler ise metot değildir ve yeniden tanımlanamaz.
Bu yazıda aritmetik, karşılaştırma, mantıksal ve diğer operatörleri; and ile && arasındaki öncelik farkını, &. güvenli gezinme operatörünü ve Ruby 4.0 ile satır başında yazılabilen mantıksal operatörleri resmî belgeler temelinde anlatıyoruz. Diğer temel konular için Ruby öğrenme rehberi sayfasına bakın.
Operatörler metottur

Operators belgesi, hangi operatörlerin kullanılabileceğinin onu uygulayan sınıfa bağlı olduğunu söyler. Aynı * işareti bir metinde tekrar, bir sayıda çarpma anlamına gelir; 3 * "ab" ise hata verir, çünkü Integer#* bir metni sayıya çeviremez:
p 5 + 3 # çıktı: 8
p 5.+(3) # çıktı: 8
p "ab" * 3 # çıktı: "ababab"
p [1, 2] + [3] # çıktı: [1, 2, 3]
begin
3 * "ab"
rescue TypeError => e
puts e.message # çıktı: String can't be coerced into Integer
endKendi sınıfınızda def +(diger) yazarak toplama operatörünü tanımlayabilirsiniz. Aşağıdaki örnek, kuruş cinsinden tutulan para değerlerini toplar:
class Para
attr_reader :kurus
def initialize(kurus)
@kurus = kurus
end
def +(diger)
Para.new(kurus + diger.kurus)
end
def to_s
format("%.2f TL", kurus / 100.0)
end
end
toplam = Para.new(1250) + Para.new(399)
puts toplam # çıktı: 16.49 TLKarşılaştırma operatörlerinin tamamını tek tek yazmak yerine yalnızca <=> tanımlayıp Comparable modülünü eklemek daha pratiktir; bu yöntem Comparable ve Enumerable yazısında anlatılıyor.
Aritmetik operatörler
Integer#/ iki tam sayıyı böldüğünde sonucu tam sayıya yuvarlar. Belgelerdeki örneklerde görüldüğü gibi yuvarlama negatif sonsuza doğrudur: -7 / 2 sonucu -3 değil -4 olur. Mod operatörü % de bu kurala uyar ve sonuç bölenin işaretini alır. Ondalıklı sonuç için fdiv kullanabilir veya işlenenlerden birini Float yapabilirsiniz. ** üs alır; negatif tam sayı üs Rational sonuç verir.
p 7 / 2 # çıktı: 3
p(-7 / 2) # çıktı: -4
p 7 % 3 # çıktı: 1
p(-7 % 3) # çıktı: 2
p 7.fdiv(2) # çıktı: 3.5
p 7.divmod(2) # çıktı: [3, 1]
p 2 ** 10 # çıktı: 1024
p 2 ** -1 # çıktı: (1/2)Karşılaştırma ve eşitlik
Ruby'de eşitlik için birden fazla metot vardır ve her birinin görevi farklıdır. == değer eşitliğini sınar ve sınıflar tarafından anlamlı biçimde yeniden tanımlanır. equal? iki ifadenin aynı nesne olup olmadığını sınar ve yeniden tanımlanmamalıdır. eql? hash anahtarlarının eşitliği için kullanılır; sayılarda tür dönüşümü yapmadığı için 1.eql?(1.0) yanlıştır. <=> (uzay gemisi operatörü) küçükse -1, eşitse 0, büyükse 1, karşılaştırılamıyorsa nil döndürür. === ise case ifadelerinde kullanılan eşleşme operatörüdür.
p 1 == 1.0 # çıktı: true
p 1.eql?(1.0) # çıktı: false
a = "ruby"
b = a.dup
p a == b # çıktı: true
p a.equal?(b) # çıktı: false
p 1 <=> 2 # çıktı: -1
p "b" <=> "a" # çıktı: 1
p 1 <=> "a" # çıktı: nil
p Integer === 5 # çıktı: true
p((1..10) === 7) # çıktı: true
p(/ab/ === "xaby") # çıktı: true=== sonuçlarının sol taraftaki nesneye göre değiştiğine dikkat edin: bir sınıf için "bu nesne benim örneğim mi", bir aralık için "bu değer aralıkta mı", bir düzenli ifade için "bu metin desene uyuyor mu" anlamına gelir. case ifadesinde nasıl kullanıldığını Ruby if, unless ve case yazısında görebilirsiniz.
Mantıksal operatörler ve kısa devre

&& ve and, ifadeleri soldan sağa değerlendirir ve ilk yanlış değerde durur; || ve or ise ilk doğru değerde durur. Belgelerin vurguladığı nokta şudur: sonuç her zaman true veya false değildir, son değerlendirilen ifadenin değeridir. Bu yüzden || varsayılan değer vermek için sık kullanılır. ! ise değerin tersini döndürür ve sonucu her zaman true veya false olur.
p(true && 9 && "metin") # çıktı: "metin"
p(1 && nil && "metin") # çıktı: nil
p(false || nil || "yedek") # çıktı: "yedek"
p(!nil) # çıktı: true
p(!!"dolu") # çıktı: trueand ile && arasındaki fark
and ve && aynı işi yapar, ama öncelikleri çok farklıdır. Precedence belgesindeki tabloda && atama operatörünün (=) üstünde, and ve or ise altındadır. Sonuç olarak x = true and false satırı önce x = true atamasını yapar, ardından sonucu false ile birleştirip atar. Aynı satır && ile yazıldığında önce mantıksal işlem yapılır:
x = true and false
p x # çıktı: true
y = true && false
p y # çıktı: false
def kaydet
puts "kaydedildi"
true
end
kaydet or puts "kaydedilemedi" # çıktı: kaydedildiBu yüzden değer hesaplayan ifadelerde && ve || kullanmak daha güvenlidir. and ve or düşük öncelikleri sayesinde son satırdaki gibi "bunu yap, olmazsa şunu yap" biçimindeki akış kontrolünde okunaklı durur.
Ruby 4.0: satır başında mantıksal operatör
Ruby 4.0 NEWS dosyasına göre ||, &&, and ve or artık bir satırın başında yazılabilir ve önceki satırın devamı sayılır; bu, satır başında nokta ile yazılan metot zincirlerine benzer. Uzun koşulları satırlara bölerken operatörü satır başına almak artık mümkün:
yas = 25
uye = true
if yas >= 18
&& uye
puts "giriş izni var" # çıktı: giriş izni var
endGüvenli gezinme operatörü: &.
Calling Methods belgesinde tanımlanan &. operatörü, alıcı nil ise metot çağrısını atlar ve nil döndürür; bu durumda metodun argümanları da değerlendirilmez. Normal nokta ile nil üzerinde metot çağırmak NoMethodError verir. &. yalnızca hemen sonraki çağrıyı atlar; uzun bir zincirde her adıma ayrıca yazılması gerekir.
kullanici = nil
p kullanici&.upcase # çıktı: nil
p "deniz"&.upcase # çıktı: "DENIZ"
begin
kullanici.upcase
rescue NoMethodError => e
puts e.message # çıktı: undefined method 'upcase' for nil
end
eslesme = "Python harika".match(/(ruby) (\w+)/i)
p eslesme&.captures&.join("-") # çıktı: nilBit, kaydırma ve diğer operatörler
Tam sayılarda &, |, ^ ve ~ bit düzeyinde işlem yapar, << ve >> bitleri kaydırır. Dizi ve metinlerde ise << sona ekleme anlamına gelir ve nesneyi döndürdüğü için zincirlenebilir. =~ bir metni düzenli ifadeyle eşleştirir ve eşleşme konumunu döndürür; !~ eşleşme yoksa true döndürür.
p 1 << 4 # çıktı: 16
p 0b1100 & 0b1010 # çıktı: 8
p 0b1100 | 0b1010 # çıktı: 14
p 6 ^ 3 # çıktı: 5
liste = [1]
liste << 2 << 3
p liste # çıktı: [1, 2, 3]
p "ruby" =~ /b/ # çıktı: 2
p "abc" !~ /z/ # çıktı: trueRuby 4.0'da dizi açma (splat) operatörüyle ilgili de küçük bir değişiklik var: NEWS dosyasına göre *nil artık nil.to_a metodunu çağırmıyor; bu, **nil ifadesinin nil.to_hash çağırmamasıyla tutarlı hale getirildi.
Öncelik tablosu

Bir ifadede birden fazla operatör varsa yüksek öncelikli olan önce çalışır. Aşağıdaki tablo Precedence belgesindeki sıranın özetidir; üstteki satırlar önce değerlendirilir. Emin olmadığınız her yerde parantez kullanmak, hem hatayı önler hem de kodu okuyanın işini kolaylaştırır.
| Öncelik (yüksekten düşüğe) | Operatörler |
|---|---|
| 1 | ! ~ tekli + |
| 2 | ** |
| 3 | tekli - |
| 4 | * / % |
| 5 | + - |
| 6 | << >> |
| 7 | & |
| 8 | | ^ |
| 9 | > >= < <= |
| 10 | <=> == === != =~ !~ |
| 11 | && |
| 12 | || |
| 13 | .. ... |
| 14 | ? : (üçlü operatör) |
| 15 | modifier rescue |
| 16 | = += -= ve diğer atamalar |
| 17 | defined? |
| 18 | not |
| 19 | or and |
| 20 | modifier if, unless, while, until |
Tablodaki ilginç bir ayrıntı: **, tekli eksiden daha yüksek önceliklidir. Bu yüzden -2 ** 2 ifadesi -(2 ** 2) olarak hesaplanır. defined? ise çok düşük öncelikli olduğu için parantezsiz kullanıldığında beklenmedik sonuç verebilir; Miscellaneous Syntax belgesi bu yüzden parantez kullanmayı önerir.
p(-2 ** 2) # çıktı: -4
p((-2) ** 2) # çıktı: 4
p(2 + 3 * 4) # çıktı: 14
p((2 + 3) * 4) # çıktı: 20
p(defined? @olmayan && @olmayan.zero?) # çıktı: "expression"
p(defined?(@olmayan) && @olmayan.zero?) # çıktı: nilSık yapılan hatalar
- Atamada
and/orkullanmak:x = a and byalnızcaadeğerini atar. Değer hesaplarken&&ve||kullanın. - Tam sayı bölmesinin yuvarlama yönünü bilmemek:
-7 / 2sonucu-4'tür. ==ileequal?metodunu karıştırmak: içerik eşitliği için==, aynı nesne olup olmadığı içinequal?kullanılır.&.operatörünü zincirin yalnızca başına yazmak: her adımnildönebiliyorsa her adımda&.gerekir.- Sırayı değiştirince sonucun aynı kalacağını sanmak:
"ab" * 3çalışır,3 * "ab"hata verir; davranışı sol taraf belirler.
Sık Sorulan Sorular
Ruby'de ++ operatörü var mı?
Hayır. Ruby'nin operatör ve öncelik belgelerinde ++ veya -- yer almaz. Bir değeri artırmak için kısaltılmış atama kullanılır: sayac += 1. Kısaltılmış atamaların listesi değişkenler yazısında.
Hangi operatörleri kendi sınıfımda tanımlayabilirim?
Metot olarak uygulanan operatörleri tanımlayabilirsiniz: aritmetik operatörler, karşılaştırmalar, ==, <=>, [], << ve ! gibi. Belgeler &&, ||, and ve or operatörlerinin metot olmadığını ve yeniden tanımlanamayacağını belirtir.
|| ile varsayılan değer vermek güvenli mi?
deger || "varsayılan" biçimi, deger yalnızca nil veya false olduğunda varsayılana geçer. 0 veya boş metin Ruby'de doğru sayıldığı için korunur. Ancak false değerinin geçerli bir değer olduğu durumlarda bu yöntem false değerini de ezer; o durumda açıkça nil? kontrolü yapın.
&. ile try arasında ne fark var?
&. dilin kendi operatörüdür ve Ruby'nin resmî belgelerinde tanımlanır. try ise Rails ile gelen bir eklentidir ve bu serinin kapsamı dışındadır; saf Ruby kodunda &. kullanılır.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: Ruby öğrenme rehberi · Ruby if, unless ve case · Ruby değişkenler ve sabitler · Ruby Integer, Float ve Rational · Comparable ve Enumerable