---
title: 'Denetim Akışı'
source: 'https://academia.sh/tr/kurslar/ruby-temelleri/denetim-akisi'
course: 'Ruby Temelleri'
language: tr
updated: '2026-10-21T05:03:43+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - "case'in her when dalına === iletisi gönderdiğini sahip ölçümüyle gösterir"
    - "if ve while'ın ileti değil sözdizimi olduğunu defined? ile ayırır"
    - "case'in yanıtlayanını dalın nesnesinin sınıfı olarak bulur ve deyim değiştiricilerle if'in değer ürettiğini gösterir"
---

# Denetim Akışı

case'in her when dalına === iletisi göndermesi, if ve while'ın ise ileti göndermeyen sözdizimi olması; deyim değiştiriciler ve if'in değer üretmesi; case'in yanıtlayanının dalın nesnesinin sınıfı olması.

Önceki ders atamanın bir ileti değil, dilin kendi yazımı olduğunu ölçtü ve bir soru bıraktı: dilin kendi yazımıyla çalışan `if`, `while` ve `case`'ten hangisi gerçekten ileti gönderiyor? Koşul ve döngü kavramları Programlama Temelleri kursunda (M01/K02) tanıtılmıştı; burada o kavramlar tekrarlanmaz. Bu ders yalnız bir soruyu ölçer: bir `case` dalının seçilmesi sırasında hangi nesneye hangi ileti gidiyor?

Rust kursunda (M10/K01) "bu yapı değer mi üretiyor" sorusu ölçülmüştü. Ruby'de de neredeyse her denetim yapısı değer üretir, ve o soru bu derste yalnız bir yan gözlem olarak geri gelir. Asıl ölçü, dallanmanın arkasındaki iletidir.

## case Her Dala === Gönderir

Aşağıdaki dosya bir aralık nesnesine `===` iletisi gönderir ve bu iletiyi kimin yanıtladığına bakar. Sonra aynı aralığı bir `case` içinde `when` dalına koyar.

```ruby
# aralik_eslesmesi.rb — case her when dalina === iletisi gonderir
aralik = 1..10

puts aralik.class
puts aralik.method(:===).owner
puts aralik === 7

sonuc = case 7
        when 1..10 then "aralikta"
        else "disinda"
        end
puts sonuc
```

```
Range
Range
true
aralikta
```

`1..10` bir `Range` nesnesidir ve `===` iletisini `Range` yanıtlar. Aralığa `7` sorulduğunda cevap `true` döner. `case 7 when 1..10` yazıldığında dal da eşleşir: çünkü `case` değerini `when` dalının nesnesine `===` iletisinin argümanı yapar. Yani `when 1..10`, perde arkasında `(1..10) === 7` sorusudur.

**DT10.** Bu derste "dal nesnesi", `when` satırında yazılan nesnedir; `case` değeri ise `case` anahtar sözcüğünden sonra gelen nesnedir. `===` iletisinin alıcısı dal nesnesi, argümanı `case` değeridir. Sıra önemlidir: `7 === (1..10)` yazılsaydı alıcı `7` olurdu ve yanıtlayan değişirdi.

## if ve while İleti Göndermez

`case` dallarında `===` iletisi gittiğini gördük. `if` ve `while` için aynı soru sorulabilir: bir koşul bir iletiyle mi seçiliyor? `defined?` buna doğrudan yanıt verir.

```ruby
# kosul_ifadeleri.rb — if ve while sozdizimidir
puts defined?(if true then 1 end)
puts defined?(while false do end)
puts defined?(1 + 2)
puts defined?(case 1 when 1 then 2 end)
```

```
expression
expression
method
expression
```

`if` ve `while` `"expression"` olarak bildirildi; yani bir yöntem çağrısı değil, dilin yapısıdır. `1 + 2` ise `"method"`. `case` de `"expression"` çıktı: dalın kendisi sözdizimidir, ama içindeki her `when` karşılaştırması bir iletiyi gönderir. Aynı yapıda iki katman var: `case` iskeleti sözdizimidir, dal seçimi ise nesnenin sınıfının yanıtladığı bir iletidir.

## Deyim Değiştiriciler ve Değer Üreten if

Ruby'de bir koşulu ya da döngüyü cümlenin sonuna koymak mümkündür. Bunlara deyim değiştirici denir: `puts x if y`, `x += 1 until z`. Ayrıca `if` bir değer üretir; hiçbir dal çalışmazsa bu değer `nil` olur.

```ruby
# deyim_degistirici.rb — deyim degistiriciler ve if'in degeri
x = 3
puts "buyuk" if x > 2
x += 1 until x >= 6
puts x

y = if false then 1 end
p y
z = if true then 1 end
p z
```

```
buyuk
6
nil
1
```

İlk satır `x > 2` doğru olduğu için çalıştı. `until` değiştiricisi `x` altıya ulaşana kadar toplamayı tekrarladı. `if false then 1 end` hiçbir dalı çalıştırmadığı için `nil` döndü, `if true then 1 end` ise `1` döndü. Sonuç: `if` bir deyim değil, değer üreten bir ifadedir. Bu, atamanın da `7` değerini taşımasıyla aynı özelliktir.

## Doğruluk ve Döngünün Değeri

Koşulun doğru ya da yanlış sayılması da dilin kendi kuralıdır. Ruby'de yalnız iki değer yanlış sayılır: `nil` ve `false`. Geri kalan her şey, `0` ve boş dizgi dahil, doğru sayılır. Aşağıdaki dosya beş değeri aynı koşulda dener.

```ruby
# dogruluk.rb — yalniz nil ve false yanlis sayilir
[nil, false, 0, "", []].each do |deger|
  durum = if deger then "dogru" else "yanlis" end
  printf("%-5s %s\n", deger.inspect, durum)
end
```

```
nil   yanlis
false yanlis
0     dogru
""    dogru
[]    dogru
```

`nil` ve `false` yanlış, `0`, `""` ve `[]` doğru çıktı. Bu kural dilin kendi kuralıdır: yalnız `nil` ve `false` yanlış sayılır, geri kalan her değer doğrudur. Döngüler de değer üretir. `while` döngüsü `break` ile bir değerle çıkarsa o değer döngünün sonucu olur; `break` olmadan biterse sonuç `nil`'dir.

```ruby
# dongu_degeri.rb — while da deger uretir
n = 0
sonuc = while true
  n += 1
  break n * 10 if n == 3
end
p sonuc

bos = while false do end
p bos
```

```
30
nil
```

Döngü üçüncü turda `30` ile çıktı ve `sonuc` bu değeri taşıdı. Hiç çalışmayan döngü ise `nil` verdi. Bu, `if`'in hiçbir dal çalışmadığında `nil` üretmesiyle aynı davranıştır: Ruby'de denetim yapıları ifadedir ve değeri vardır.

## Döngüler ve Değer Üretmeleri

Önceki bölümler dalları ölçtü; bu bölüm döngüleri ölçer. Soru yine değerle ilgilidir: bir döngü ifadesi bir değer üretir mi, ve `break` o değeri belirleyebilir mi? Yanıtlayan ekseni bu bölümde iki yerde görünür: `while` ve `until` anahtar sözcüktür ve sözdizimidir, `loop` ise bir yöntemdir ve sahibi çıktıda okunur. İkinci blok ise bir kapsam farkına bakar: `for` ile blok değişkeni dışarıya aynı biçimde mi davranır?

```ruby
# donguler.rb — dongulerin degeri ve next
sonuc = loop { break 5 }
puts sonuc
i = 0
i += 1 while i < 3
puts i
j = 10
j -= 1 until j < 8
puts j
bos = while false do end
puts bos.inspect
toplam = 0
(1..5).each do |n|
  next if n.even?
  toplam += n
end
puts toplam
puts method(:loop).owner
```

```
5
3
7
nil
9
Kernel
```

`loop { break 5 }` döngünün değeri olarak `5` verdi: `break` argümanı döngü ifadesinin sonucu olur. `i += 1 while i < 3` değiştiricisi `i`'yi `3`'e çıkardı, `j -= 1 until j < 8` ise `j`'yi `7`'de durdurdu; `while` koşul doğru kaldıkça, `until` koşul yanlış kaldıkça sürer. `while false do end` ifadesi hiç çalışmadığı hâlde bir değer üretti ve bu değer `nil`'dir. Yani döngü de, `if` gibi, bir ifadedir ve değer taşır. `(1..5).each` içinde `next if n.even?` çift sayıları atladı; kalan `1`, `3`, `5` toplandı ve `9` çıktı. `next` yinelemeyi atlar, `break` döngüyü bitirir; ikisi de blok içinde yazılır ve ikisi de dilin anahtar sözcüğüdür; bu dosya onlar için bir sahip basmadı. Son satır `loop`'un sahibinin `Kernel` olduğunu gösterdi: `loop` bir anahtar sözcük değil, `puts` gibi bir yöntemdir.

```ruby
# for_sizintisi.rb — for degiskeni disari sizar, blok degiskeni sizmaz
[1, 2].each { |k| k }
d = defined?(k)
puts d.inspect
for m in [1, 2] do end
puts defined?(m)
puts m
puts [1, 2].method(:each).owner
puts 1.upto(3).to_a.inspect
puts 3.times.class
```

```
nil
local-variable
2
Array
[1, 2, 3]
Enumerator
```

`each` bloğunun değişkeni `k` dışarıdan sorulduğunda `nil` döndü: blok değişkeni bloğun içinde kalır. `for m in [1, 2] do end` ise `m`'yi dışarıya sızdırdı: `defined?(m)` `"local-variable"` bildirdi ve `m` sonunda `2` oldu. Yani `for` döngüsü yeni bir kapsam açmaz. Aynı işi gören iki yazımın kapsam davranışı farklıdır; bu fark, hangisinin seçildiğini bir tercih olmaktan çıkarıp bir sonuca bağlar. `[1, 2].method(:each).owner` `Array` verdi; yani `each`'i dizinin sınıfı karşılar. `1.upto(3).to_a` `[1, 2, 3]` verdi ve bloksuz çağrılan `3.times` bir `Enumerator` döndürdü: bloksuz çağrılan `times` değer üretmek yerine bir yineleyici verir.

**DT11.** `for`'un arka planda dizinin `each` iletisini çağırdığı ölçülmedi. Ölçülen yalnızca kapsam farkı ve `each`'in sahibinin `Array` olduğudur.

## Kısa Devre ve Karşılaştırma

Koşullar yalnız `if` ve `case` ile kurulmaz: `||` ve `&&` işleçleri de sağ tarafı çalıştırıp çalıştırmamaya karar verir. Bu bölüm iki soruyu ölçer: bir işleç sağ tarafı değerlendirmeyi atladığında ne gözlenir, ve karşılaştırma yapan yöntemlerin sahibi kim? Eksen yine yanıtlayandır; `||` ve `&&` dilin sözdizimidir, `<=>` ve `between?` ise iletidir.

```ruby
# kisa_devre.rb — sag taraf calisir mi, kim karsilar
def iz(ad)
  puts ad
  true
end
iz("a") || iz("b")
iz("c") && iz("d")
v = nil || "varsayilan"
puts v
w = false && 1
puts w.inspect
puts 1 <=> 2
puts 5.between?(1, 10)
n = 5
durum = n > 3 ? "buyuk" : "kucuk"
puts durum
puts 5.method(:<=>).owner
puts 5.method(:between?).owner
```

```
a
c
d
varsayilan
false
-1
true
buyuk
Integer
Comparable
```

`iz("a") || iz("b")` satırında yalnız `a` basıldı: sol taraf doğru olduğu için sağ taraf hiç çalışmadı. `iz("c") && iz("d")` satırında ise `c` ve `d` ikisi de basıldı, çünkü `&&` sol taraf doğru olunca sağ tarafa da bakar. Kısa devre budur: sonuç sol tarafla belirlenmişse sağ taraf değerlendirilmez. `nil || "varsayilan"` ifadesi `varsayilan` verdi; `||` yalnız doğruluk değeri üretmez, işleneninin kendisini döndürür. `false && 1` ise `false` döndürdü. `||` ile varsayılan değer vermek bu davranışa dayanır: sol taraf `nil` ya da `false` ise sağ taraftaki değer döner.

`1 <=> 2` `-1` verdi: karşılaştırma iletisi sıralamayı bir tam sayı olarak bildirir. `5.between?(1, 10)` `true` oldu. Üçlü işleç `n > 3 ? "buyuk" : "kucuk"` `buyuk` verdi. Sahip satırları iki ayrı yanıtlayanı ortaya çıkardı: `<=>` iletisini `Integer` karşılar, `between?` iletisini ise `Comparable` modülü karşılar. İkisi de bir sayıya gönderilir ve sonucu verir, ama tanımlandıkları yer farklıdır. Yani koşul yazarken kullanılan karşılaştırma iletileri, sınıfın kendi yöntemleri ile ortak bir modülün yöntemleri arasında bölünmüştür.

## Hata Akışı: rescue, else ve ensure

Denetim akışı yalnız koşul ve döngüden ibaret değildir; hata da akışı değiştirir. Bu bölüm `rescue`, `else` ve `ensure` dallarının hangi sırayla çalıştığını ve yöntemin değerini hangisinin belirlediğini ölçer. Hata sınıfı basılır, iletisi basılmaz. Eksen sözdizimidir: `rescue` ve `ensure` anahtar sözcüktür, `raise` ise bir yöntemdir.

```ruby
# istisna_akisi.rb — rescue, else ve ensure sirasi
def dene
  yield
rescue ZeroDivisionError => e
  puts e.class
  :kurtarildi
else
  :sorunsuz
ensure
  puts "temizlik"
end
a = dene { 1 / 0 }
puts a.inspect
b = dene { 1 / 1 }
puts b.inspect
c = begin
  Integer("x")
rescue ArgumentError
  -1
end
puts c
puts method(:raise).owner
puts method(:dene).owner
```

```
ZeroDivisionError
temizlik
:kurtarildi
temizlik
:sorunsuz
-1
Kernel
Object
```

İlk çağrıda blok `1 / 0` hesapladı ve `ZeroDivisionError` fırlattı. `rescue` dalı çalıştı, sınıfı bastı ve `:kurtarildi` döndürdü; ardından `ensure` dalı `temizlik` yazdı. Dönüş değeri `:kurtarildi` olarak kaldı: `ensure` yöntemin değerini belirlemez. İkinci çağrıda hata çıkmadı, bu yüzden `else` dalı çalıştı ve yöntemin değeri `:sorunsuz` oldu; `ensure` yine `temizlik` yazdı. Yani `ensure` her iki yolda da çalışır, `rescue` yalnız hata olduğunda, `else` yalnız hata olmadığında çalışır.

`begin` bloğu da bir ifadedir ve değer taşır. `Integer("x")` `ArgumentError` fırlattı, `rescue` dalı `-1` döndürdü ve `c` bu değeri aldı. Bu, `if`'in değer üretmesinin hata akışındaki karşılığıdır: dallardan biri çalışır ve çalışan dalın son ifadesi bütünün değeri olur. Sahip satırları `raise` için `Kernel`, `dene` için `Object` gösterdi: hata fırlatmak bir yöntem çağrısıdır, ama `rescue` ile `ensure` dilin kendi yazımıdır. Hata iletisinin metni bu bölümde basılmadı; çünkü iletinin metni sürüme göre değişebilir, sınıfı ise değişmez.

## Sınırlayıcı Ölçüm

Bu dersin yanıtlayanı sınıftır. Burada kayma, `case`'in yanıtlayanını `case`'e verilen değerin sınıfı sanmaktır. Oysa `case 7` ifadesinde `7`'nin sınıfı `Integer`'dır, ama `===` iletisinin alıcısı dal nesnesidir. Bu yüzden aynı `7` için `when Integer` satırında `Module`, `when /a/` satırında `Regexp`, `when 1..10` satırında `Range` yanıtlar.

```ruby
# dal_nesnesi.rb — case'in yanitlayani dalin nesnesinin sinifidir
dallar = [Integer, /a/, 1..10]

dallar.each do |dal|
  printf("%-8s sinifi %-8s ileti sahibi %s\n", dal.inspect, dal.class, dal.method(:===).owner)
end

puts Integer === 7
puts(/a/ === "kalem")
puts dallar[2] === 7
```

```
Integer  sinifi Class    ileti sahibi Module
/a/      sinifi Regexp   ileti sahibi Regexp
1..10    sinifi Range    ileti sahibi Range
true
true
true
```

Üç dal nesnesi, üç ayrı sahip: `Integer` için `===` iletisini `Module` yanıtlar (önceki dersteki `Integer.===` gözlemi), düzenli ifade için `Regexp`, aralık için `Range`. `case`'in değeri hep `7` ya da aynı `"kalem"` olsa bile değişen yalnız alıcıdır. Sınıf yanıtlayanı olarak okunacak olan, `case` değerinin değil, dal nesnesinin sınıfıdır.

Bu derste ölçülen iki katmanı birlikte okumak gerekir. Denetim yapısının iskeleti, yani `if`, `while` ve `case` sözcükleri, dilin kendi yazımıdır ve `defined?` onları `"expression"` olarak bildirir. Dalın içindeki karşılaştırma ise bir iletidir ve nesnenin sınıfı onu yanıtlar. İkisini ayırmak, bir `case` ifadesini okurken "bu dal neden eşleşti" sorusunu "dal nesnesinin `===` yöntemi ne yapıyor" sorusuna çevirir.

## Özet

- `case` her `when` dalında dal nesnesine `===` iletisi gönderir; `when 1..10` perde arkasında `(1..10) === 7` sorusudur.
- `===` iletisinin alıcısı dal nesnesi, argümanı `case` değeridir; sıra tersine çevrilirse yanıtlayan değişir.
- `if` ve `while` `defined?` ile `"expression"` bildirilir; dilin kendi yapısıdır ve ileti göndermez.
- Deyim değiştiriciler (`if`, `unless`, `while`, `until`) bir cümleyi koşullu ya da döngülü yapar; `if` bir değer üretir ve hiçbir dal çalışmazsa `nil` döner.
- Bu dersin yanıtlayanı sınıftır: `case`'in yanıtlayanı, `case` değerinin değil dal nesnesinin sınıfıdır.
- `loop { break 5 }` `5` döndürür, `while false do end` `nil` verir; `for` değişkeni dışarı sızar, blok değişkeni sızmaz; `||` ve `&&` sağ tarafı gerekmedikçe çalıştırmaz, `ensure` her yolda çalışır.

## Sonraki Adım

Koşul ve dal seçimini kimin yanıtladığını ölçtük. Peki bir yöntem çağrısında alıcı hiç yazılmadığında, örneğin `puts` ya da `format` yazıldığında, iletiyi kim karşılıyor? Sonraki ders, Yöntemler, alıcısız çağrının yanıtlayanını ölçer.
