İçeriğe atla

Ruby/Söz Dizimi/Operatörler

Vikikitap, özgür kütüphane

←Değer İfadeleri | Kontrol Yapıları→


Operatörler

[düzenle]

Bütün Liste ve Öncelikler

[düzenle]
Operatör İsim/anlam Argümanlar Öncelik[1] İşlem yönü
! Boolean NOT Tek 1 Right
~ İkinin tümleyeni değeri Tek 1 Right
+ Unary artı değer(etkisi yok) Tek 1 Right
** Üst alma İki 1 Right
- Unary eksi değer (işareti ters çevirir) Tek 2 Right
* Çarpma İki 3 Left
/ Bölme İki 3 Left
% Modül (kalan değer) İki 3 Left
+ Toplama ya da birleştirme İki 4 Left
- Çıkarma İki 4 Left
<< İkili sistem sola kaydırma veya sona ekleme (<< ve <<- ayrıca "Here döküman" notasyonu'nda da kullanılır) İki 5 Left
>> İkili sistem sağa kaydırma İki 5 Left
& Bit seviyesi AND İki 6 Left
| Bit seviyesi OR İki 7 Left
^ Bit seviyesi XOR İki 7 Left
< Küçüktür İki 8 Left
<= Küçük veya eşittir İki 8 Left
> Büyüktür İki 8 Left
>= Büyük veya eşittir İki 8 Left
== Eşittir (aynı değerde olmalarını testeder) İki 9 N/A
=== "Case equality" veya "threequality" operatörü. A === B demek B A setinin içinde var mı demek. Veri tipine göre değişir. A ve B aynı veri tipiyse == ile farkı yoktur İki 9 N/A
!= Eşit değildir İki 9 N/A
=~ Eşleşme arama İki 9 N/A
!~ Eşleşmeme arama İki 9 N/A
<=> A <=> B sonucu -1, 0, veya 1 döner; sırasıyla A küçükse, eşitse ve büyükse (B'ye göre) İki 9 N/A
&& Boolean AND İki 10 Left
|| Boolean OR İki 11 Left
.. Range oluşturma, boolean flip-flop (flip-flop kaldırıldı) İki 12 N/A
... Açık sonlu range oluşturmak, ikinci değer range dışı İki 12 N/A
?: A?B:C yazınca eğer A true ise B işlemi, false ise C işlemi yapılır Üç 13 Right
rescue Sıradışı durumları yakalama belirleyicisi örn. array[3] rescue "yok" İki 14 Left
= Atama İki 15 Right
**= A **=B ve A = A ** B aynı İki 15 Right
*= A *=B ve A = A * B aynı İki 15 Right
/= A /=B ve A = A / B aynı İki 15 Right
%= A %=B ve A = A % B aynı İki 15 Right
+= A +=B ve A = A + B aynı İki 15 Right
-= A -=B ve A = A – B aynı İki 15 Right
<<= A <<=B ve A = A << B aynı İki 15 Right
>>= A >>=B ve A = A >> B aynı İki 15 Right
&&= A &&=B ile A değeri true veya nil olmayan bir değerse B değerini A'ya koyar İki 15 Right
&= A &=B ve A = A & B aynı İki 15 Right
||= A ||=B ile A değeri false veya nil değerse B değerini A'ya koyar İki 15 Right
|= A |= B ve A = A | B aynı İki 15 Right
^= A ^=B ve A = A ^ B aynı İki 15 Right
defined? Eğer ifsde çalıştırılamıyorsa nil değer olur(örn. değer verilmemiş değişken) Tek 16 N/A
not Boolean NOT Tek 17 Right
and Boolean AND İki 18 Left
or Boolean OR İki 18 Left
if Koşul, örn. print x if x İki 19 N/A
unless Ters koşul, örn. x = 0 unless x İki 19 N/A
while Koşullu döngü, örn. print x += 1 while (x < 10) İki 19 N/A
until Koşullu döngü, örn. print x += 1 until (x == 10) İki 19 N/A


Yüksek öncelikliler (yukarıdaki tabloda önceliği küçük olan operatörler) argümanlarının daha önce işlenmesi hakkına sahiptir. Öncelik sırası parantez blokları ile değiştirilebilir. Örneğin * operatörü +'ya göre önceliklidir :


1 + 2 * 3 == 7
(1 + 2) * 3 == 9

İşlem yönü , aynı önceliğe sahip bir'den fazla operatör kullanılınca hangisinin önce işleneceğini kontrol eder. Örneğin - sol yöne sahip olduğu için :

1 – 2 – 3 == (1 – 2) – 3 == -1 – 3 == -4

yani şöyle değil :

1 – 2 – 3 == 1 – (2 – 3) == 1 - -1 == 2


** operatörü sağ yön olduğu için :

2 ** 3 ** 2 == 2 ** (3 ** 2) == 2 ** 9 == 512

dir. Yani şöyle değil :

2 ** 3 ** 2 == (2 ** 3) ** 2 == 8 ** 2 == 64

{} blokları yukarıdaki listenin hepsinden düşük önceliklidir, arkasından do/end blokları gelir. [] kullanarak array elemanlarına erişimler ise yukarıdakilerden daha yüksek önceliğe sahiptir.

Operatör ** 'dan !~ 'ya kadar olanların işlevi değiştirilebilir (override) — yeni sınıflar için yeni tanımlama yapılabilir veya mevcut işlevleri değiştirilebilir.

rescue, if, unless, while, ve until tek satır kodlarda (one-liner) operatördürler (yukarıda örnekler gibi) , ama aynı zamnada deyim olarak da kullanılırlar.


Diğer operatörler

[düzenle]

Nokta operatörü . nesneler üzerinde metod çağırmak için kullanılır, buna nesneye mesaj göndermek de denir.

Ruby 2.3.0 ile &. operatörü kullanıma başladı , ayrıca "lonely operator".[2] olarak bilinir. Bu sayede

x = foo && foo.bar && foo.bar.baz

yerine

x = foo&.bar&.baz

yazılabilir.

.dig() metodu da hash ve array için getirildi :

hash_variable.dig(:foo, :bar, :baz)
array_variable.dig(1, 0, 2)

aşağıdakinden daha güvenlidir :

hash_variable[:foo][:bar][:baz]
array_variable[1][0][2]


Atama

[düzenle]

Ruby'de atama eşit işlemcisi "=" kullanılarak yapılır. Bu nesnelerde de değişkenlerde de böyledir, çünkü Ruby'de stringler, floatlar, integerlar hepsi nesnedir ve siz her zaman nesnelere atama yaparsınız.

Örnekler:

  myvar = 'myvar değişkeni şimdi bu string'
  var = 321
  dbconn = Mysql::new('localhost','root','password')


Kendine Atamalar

[düzenle]
  x = 1           #=>1
  x += x          #=>2
  x -= x          #=>0
  x += 4          #=>x 0 ise x= + 4 # x değeri 4 olur
  x *= x          #=>16
  x **= x         #=>18446744073709551616 # 16 üssü 16
  x /= x          #=>1

C ve C++ bilenlerden sık gelen bir soru "Bir değişkenin artırım ve azaltımı nasıl yapılacak? ++ ve -- işlemleri nasıl yapılır?" Ruby'de x+=1 artırma için x-=1 azaltım için kullanılır.

  x = 'a'
  x.succ!         #=>"b" : succ! metodu String için tanımlanmıştır ama sayılarda yoktur


Çoklu Atamalar

[düzenle]

Örnekler:

var1, var2, var3 = 10, 20, 30
puts var1           #=>var1 değeri 10
puts var2           #=>var2 değeri 20
  
myArray=%w(John Michel Fran Adolf) # %w() array tanımlamayı kolaylaştırmak için kullanılır
var1,var2,var3,var4=*myArray
puts var1           #=>John
puts var4           #=>Adolf

isimler,okul=myArray,'Sen Bernar'
isimler             #=>["John", "Michel", "Fran", "Adolf"]
okul                #=>"Sen Bernar"


Koşullu Atama

[düzenle]
x = nil           #=>nil
x ||= "default"   #=>"default" : x nil veya false değerdeyse "default" değerini alacaktır
x ||= "other"     #=>"default" : x değeri artık nil veya false olmadığı için değişmeyecektir

||= operatörü yaklaşık olarak aşağıdakinin kısaltılmışıdır:[3]

 x = x || "default"

||= operatörü şu kodun kısaltılmışı olarak kullanılabilir:

 x = "default" if x.nil?

Operator ||= şunun kısaltılmışı olabilir:

x = "(fallback değeri)" unless respond_to? :x or x


Aynı şekilde &&= operatörü çalışır:

x = get_node() #=>nil
x &&= x.next_node #=> nil : x değeri x.next_node değerini ancak nil veya false değilse alır
x = get_node() #=>Some Node
x &&= x.next_node #=>Next Node

Operator &&= şunun kısaltılmışı:

 x && x = x.get_node()

Kapsamlar (Scope)

[düzenle]

Ruby'de temel olarak yerel kapsam, genel kapsam, oluşum kapsamı ve sınıfsal kapsam olarak değişkenler işlenir.

Yerel Kapsam

[düzenle]

Örnek:

var=2
4.times do |x| puts x=x*var end  #=>0,2,4,6
puts x   #=>undefined local variable or method `x' for main:Object (NameError)

Bu hata oluşur çünkü üçüncü satırdaki x(üst seviye) do..end bloğu içindeki x(yerel) ile aynı değildir. Yerel x blok içinde tanımlanmış bir değişkendir bu yüzden biz blok dışında x değişkeni çağırdığımızda Ruby tanımadığını belirtecektir.


Global Kapsam

[düzenle]
$global = 0
4.times do |var|
   $global = $global + var
   puts "var #{var}  global #{$global}"
end
#=> var 0  global 0
#=> var 1  global 1
#=> var 2  global 3
#=> var 3  global 6
 
puts $global    #=> 6

Bu çalışır çünkü bir değişken adının önüne dolar işareti koymak onu global yapar.


Oluşum kapsamı

[düzenle]

Bir sınıfın metodları arasında değişkenleri paylaşmak için önüne @ karakteri koyarak oluşum değişkeni yaparsınız.

class A
   def setup
      @instvar = 1
   end
   def go
      @instvar = @instvar*2
      puts @instvar
   end
end
instance = A.new
instance.setup
instance.go       #=> 2
instance.go       #=> 4
instance2 = A.new
instance2.setup
instance2.go      #=> 2
instance.go       #=> 8

Gördüğünüz gibi iki nesnenin @instvar değişkeni farklı değerlerde olur.


Sınıf Kapsamı

[düzenle]

Bir sınıf değişkeni Java dilieki "static" değişken gibidir. O sınıfın tüm oluşum nesnelerinde aynı değişken paylaşılır.

class A
    @@classvar = 1
    def go
        @@classvar = @@classvar*2
        puts @@classvar
    end
end
instance = A.new
instance.go         #=> 2
instance2 = A.new
instance2.go        #=> 4 -- değişken devam ediyor


Şimdi de değişik tipleri gösteren bir demo :

$variable
class Test
    def initialize(arg1='kiwi')
        @instvar=arg1
        @@classvar=@instvar + ' dedim sana!!'
        localvar=@instvar
    end
    def print_instvar
        puts @instvar
    end
    def print_localvar
        puts @@classvar
        puts localvar
    end
end
var = Test.new
var.print_instvar       #=>"kiwi", çalışır çünkü @instvar'a sınıf içinde her yerden ulaşılabilir
var.print_localvar      #=>undefined local variable or method 'localvar' (NameError).

Bu kod önce "kiwi" ve "kiwi dedim sana!!" satırlarınıa yazar, sonra bir hata mesajı verir. var.print_instvar metodu @instvar oluşum değişkeni değerini yazar. Test.new komutu ile Test sınıfının initialize metodu otomatik olarak çalışır, ve new() metoduna argüman verilmediği için default değer olan "kiwi" değeri @instvar oluşum değişkenine atanır. Yine initialize metodu içinde @@classvar sınıf değişkenine de "kiwi dedim sana" değeri konur. var.print_localvar metodu çağrılınca metod tanımının ilk satırı @@classvar değerini yazar, ama ikinci satıra geçince localvar değerini yazamaz , çünkü localvar başka bir metod içinde tanımlandı ama bu metod onun içinde tanımlanan bu yerel değişkene erişemez. Diğer yandan sınıf değişkeni @@classvar ve oluşum değişkeni olan @instvar sınıfın tüm metodları tarafından erişilebilir, sınıf değişkeni aslında tüm oluşum nesneleri arasında paylaşılır.


class SubTest < Test
    def print_classvar
        puts @@classvar
    end
end
newvar=SubTest.new         # newvar nesnesi üretilince Test sınıfındaki @@classvar ile aynı değeri paylaşır!!
newvar.print_classvar      #=>kiwi dedim sana!!

Sınıf değişkenleri ebeveyn ve çocuk sınıfları kapsar, bu değişkenler sınıflar arası da paylaşılır, ve çocukları da etkileyebilir (soyuna çekmek gibi) ;-)

class SubSubTest < Test
    def print_classvar
        puts @@classvar
    end
    def modify_classvar
        @@classvar='kiwi kiwi heey!!'
    end
end
subtest=SubSubTest.new
subtest.modify_classvar     #lets add a method that modifies the contents of @@classvar in  SubSubTest
subtest.print_classvar      #=>kiwi kiwi heey!! 
newvar.print_classvar       #=>kiwi kiwi heey!! - @@classvar tüm sınıflarda paylaşılıyor


Bu çocukta da @@classvar sınıf değişkeni var ve üst sınıfla ve diğer çocuklarla aynı değeri gösteriyor (paylaşılıyor). newvar nesnesi ile oynamadığımız halde subtest nesnesinde @@classvar değerini değiştirince newvar nesnesinin print_classvar metodu da aynı değeri yazacaktır.


Default kapsam

[düzenle]

Eğer kodunuz herhangi bir kapsam sınırlayıcı içinde değilse mesela direk :

  @a = 33

Bu default kapsamda yani main adı verilen nesnede geçerlidir.

Örneğin betiğiniz şunu derse :

 @a = 33
 require 'diger_betik.rb'

ve "diğer_betik.rb" de şunu derse :

 puts @a     #=> 33

İki betik aynı oluşumdeğerini paylaşabilir.

Ancak iki betik aynı yerel değikenleri paylaşamaz.


Yerel kapsam ayrıntıları

[düzenle]

Bir sınıf tanımı içinde metodlar tanımlarken şöyle yapabilirsiniz.

class A
    a = 3
    if a == 3
        def go
            3
        end
    else
        def go
           4
        end
    end
end

Bu bir betik dil olduğu için koşullu olarak değişik metod tanımları yapılabilir, interpreter programı satır satır işlerken hangi tanıma gelirse o geçerli olur. Bu örnekte a değişkeni aynı seviyede bulunduğu if bloğunun koşulunda kullanılabilir. Mesela proc blokları da kendilerini çevreleyen kapsamdaki değişkenlere erişebilir.

a = 3
b = proc { puts a }
b.call # 3 -- a değerine ulaşabilir

Bununla beraber class ve def kelimeleri, tamamen yeni bir kapsama sahiptirler.

class A
    a = 3
    def go
        return a # bu çalışmaz!
    end
end

Bu kısıtlamanın dışına define_method kullanarak da kaçabilirsiniz (not edelim istediğiniz blok şekli kullanabilirsiniz buradaki sadece örnek verildi).

class A
   a = 3
   define_method(:go) { a }
end

Başka bir blok kullanma örneği

x = 3
PROC = proc { puts x } 

class A
    define_method(:go, &PROC)
end
a = A.new
a.go    #=> 3

veya bu :

class A
end
x = 3
A.class_eval do
    define_method(:go) do
        puts x
    end
end
a = A.new
a.go    #=> 3


Mantıksal Ve İşlemi

[düzenle]

"and" işlemi verilen iki operandın mantıksal ve işleminin sonucunu verir. "&&" işlemi ile aynı sonucu verir, ama önceliği daha düşüktür.

Örnek:

a = 1
b = 2
c = nil
puts "tüm argümanlarım true" if a and b    # bu yazılır
puts "olamaz argümanların biri false" if a and c    #bu yazılmaz


Mantıksal Veya İşlemi

[düzenle]

"or" işlemi verilen iki operandın mantıksal veya işleminin sonucunu verir. "||" işlemi ile aynı sonucu verir, ama önceliği daha düşüktür.

Örnek:

a = nil
b = "foo"
c = "boo"
puts (a and b or c) #=> boo - 'or' daga sonra çalışıyor 
puts (a and b || c) #=> nil - || işlemi 'and' işleminden öncelikli
Önceki: Söz Dizimi/Değer İfadeleri Index Sonraki: Söz Dizimi/Kontrol Yapıları


Referanslar

[düzenle]
  1. http://ruby-doc.org/core-2.4.0/doc/syntax/precedence_rdoc.html
  2. https://www.ruby-lang.org/en/news/2015/12/25/ruby-2-3-0-released/
  3. http://www.rubyinside.com/what-rubys-double-pipe-or-equals-really-does-5488.html