---
title: '`Enumerable` Modülü'
source: 'https://academia.sh/tr/kurslar/ruby-temelleri/enumerable-modulu'
course: 'Ruby Temelleri'
language: tr
updated: '2026-10-21T05:03:43+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Enumerable yöntemlerinin sahibini owner ile ölçer'
    - 'Kendi sınıfına include Enumerable ve tek bir each ile yineleme yöntemleri kazandırır'
    - 'sort_by, group_by, min_by ve tally yöntemlerinin sonuçlarını okur'
    - 'Aynı adlı bir yöntemin dizide, aralıkta ve modülde farklı sahipleri olabileceğini ölçer'
---

# `Enumerable` Modülü

Dizinin kendisinde olmayan yineleme yöntemlerinin Enumerable modülünden geldiği, kendi sınıfınıza tek bir each ile aynı yeteneğin verildiği ve modülün her işi üstlenmediği ölçülür.

Önceki derste `karma.map` yönteminin `Hash`'te değil `Enumerable` modülünde tanımlı olduğu görüldü. Bu ders o modüle bakar. **Modül (module)**, yöntemlerin bir sınıfa **karıştırıldığı (include)** bir yöntem topluluğudur; kendi başına nesne üretmez. M08'de nesne yönelimli temeller kuruldu; burada yalnız bu modülün hangi iletileri yanıtladığı ölçülür.

Bu dersin yanıtlayanı **modül**dür. Dizi, aralık ve karma yapı farklı sınıflardır, ama birçok yineleme iletisini ortak bir modül yanıtlar.

## Modülün Yanıtladığı İletiler

İlk ölçüm bir aralığa `each_slice` iletisini gönderir. Çekirdek sonucu, yöntemin sahibine bakarak sınıflandırır: sahip bir `Class` ise yanıtlayan sınıf, değilse modüldür.

```ruby
# yanit.rb — bir iletiyi kimin yanitladigini siniflandiran yardimcilar

# Siniflandirma sirayla sorar: once ifade bir ileti mi (defined?),
# sonra iki farkli blok iki farkli sonuc veriyor mu, sonra yontemin sahibi kim.
def yanitlayan(tanim, sahip: nil, sonuc: nil, bloklu: nil)
  return ["sozdizimi", "defined? #{tanim}"] unless tanim == "method"

  if bloklu
    birinci, ikinci = bloklu.call
    return ["blok", "#{birinci.inspect} / #{ikinci.inspect}"] unless birinci == ikinci
  end

  tur = sahip.instance_of?(Class) ? "sinif" : "modul"
  [tur, "#{sahip}, sonuc #{sonuc.inspect}"]
end
```

```ruby
# dilim.rb — each_slice iletisini kim yanitliyor
require_relative "yanit"

aralik = (1..5)
sahip = aralik.method(:each_slice).owner
sonuc = aralik.each_slice(2).to_a
tur, kanit = yanitlayan(defined?(aralik.each_slice(2)), sahip: sahip, sonuc: sonuc)
puts "#{tur}  #{kanit}"
```
```
modul  Enumerable, sonuc [[1, 2], [3, 4], [5]]
```

Bu, çekirdeğin `dilimleme` satırıdır: yanıtlayan **modül**, sahip `Enumerable`. `Range` sınıfı `each_slice` yöntemini kendisi tanımlamıyor; aralığa `each` ile elemanlarını vermeyi bilmesi yeterli. Aynı modülün diğer yöntemleri bu dersin ikinci ölçümündedir.

```ruby
# araclar.rb — Enumerable yontemleri
meyveler = %w[elma armut kiraz muz]
puts meyveler.sort_by { |m| m.size }.first
puts meyveler.group_by { |m| m.size }.inspect
puts meyveler.min_by { |m| m.size }
puts %w[a b a].tally.inspect
puts (1..6).select(&:even?).inspect
```
```
muz
{4 => ["elma"], 5 => ["armut", "kiraz"], 3 => ["muz"]}
muz
{"a" => 2, "b" => 1}
[2, 4, 6]
```

`sort_by` en kısa adı başa aldı, `group_by` adları uzunluğa göre gruplayan bir karma yapı kurdu, `min_by` en kısa adı verdi. `tally` her elemanın kaç kez geçtiğini saydı. `select(&:even?)` aralıktan çift sayıları seçti.

## Kendi Sınıfınıza Karıştırmak

Modülün yeteneği ancak bir sınıfa karıştırıldığında bir sınıfın olur. En küçük biçimi: sınıf yalnız `each` tanımlar ve `include Enumerable` der. Sınıf tasarımı M08'in konusudur; burada sınıf yalnız ölçüm için en küçük hâlinde kurulur.

```ruby
# sayilar.rb — kendi sinifimiza Enumerable karistirmak
class Sayilar
  include Enumerable

  def each
    yield 3
    yield 1
    yield 2
  end
end

sayilar = Sayilar.new
puts sayilar.map { |n| n * 2 }.inspect
puts sayilar.sort.inspect
puts sayilar.min_by { |n| -n }
puts "map=#{sayilar.method(:map).owner} each=#{sayilar.method(:each).owner}"
puts sayilar.to_a.inspect
puts sayilar.include?(2)
puts sayilar.first
puts sayilar.reduce(:+)
puts sayilar.each_with_index.to_a.inspect
puts sayilar.is_a?(Enumerable)
```
```
[6, 2, 4]
[1, 2, 3]
3
map=Enumerable each=Sayilar
[3, 1, 2]
true
3
6
[[3, 0], [1, 1], [2, 2]]
true
```

Sınıf yalnız `each` yazdı; `map`, `sort` ve `min_by` ek tanım yazmadan geldi. `min_by { -n }` en büyük sayıyı verdi, çünkü eksi değeri en küçük olan `3`'tür. Son satır paylaşımı gösterir: `map`'in sahibi `Enumerable`, `each`'in sahibi `Sayilar` sınıfı. `to_a` elemanları `each`'in verdiği sırayla topladı: `[3, 1, 2]`. `include?`, `first` ve `reduce` de aynı tek `each`'e dayandı; `reduce(:+)` elemanları toplayıp `6` verdi. `each_with_index` her elemana sıra numarasını ekledi. Son satır, sınıfın örneklerinin `Enumerable` olarak tanındığını doğrular. Sınıf `<=>` tanımlamadı, çünkü `sort` burada sayıları karşılaştırırken sayıların kendi karşılaştırmasını kullanır; sınıfın örneklerini kendi aralarında karşılaştırmak ayrı bir iştir. **KB8.** Bu sınıf `each` ile üç değer verir; `each` sonsuz bir dizi üretirse `sort` gibi tümünü okuyan yöntemler hiç bitmez, ama bu davranış burada ölçülmez.

## Modülün Döndürdüğü Türler

Modülün yöntemleri alıcının türünden bağımsız olarak belirli türler döndürür. Bu, modülün kullanıcıya verdiği bir sözleşmedir: aralığa, diziye ya da kendi sınıfınıza aynı iletiyi gönderdiğinizde sonuç türünü alıcıya bakmadan bilirsiniz.

```ruby
# turler.rb — Enumerable yontemlerinin dondurdugu turler
aralik = (1..3)
puts aralik.map { |n| n }.class
puts aralik.select { |n| n > 1 }.class
puts aralik.group_by { |n| n.odd? }.class
puts aralik.tally.class
puts aralik.each_slice(2).class
puts aralik.min_by { |n| -n }.class
```
```
Array
Array
Hash
Hash
Enumerator
Integer
```

`map` ve `select` dizi, `group_by` ve `tally` karma yapı döndürdü; bloksuz `each_slice` bir yineleyici verdi; `min_by` tek bir eleman verdi. Aralık burada alıcıydı, ama sonuç türleri aralığa değil modülün tanımına bağlı. Diziler ve Karma Yapılar dersinin `Hash#select` örneği bunun sınırını gösterir: orada sınıfın kendi tanımı karma yapı döndürmüştü. **KB9.** Bu tablo yalnız aralık alıcısıyla ölçüldü; aynı yöntemlerin kendi sınıfınızda aynı türleri döndürdüğü yukarıdaki `Sayilar` ölçümünden `map` için görülmüştür, diğerleri için varsayılmaz.

## Zincirleme Yöntemler

`Enumerable`'ın asıl gücü, küçük yöntemlerin birbirine bağlanmasıdır. Aşağıdaki ölçüm beş yöntemi bir aralık üzerinde koşturur ve her birinin sahibini yanına basar.

```ruby
# zincir.rb — her yontemin sonucu ve sahibi
s = (1..4)
puts "each_with_object=#{s.each_with_object([]) { |n, a| a << n * n }.inspect} sahip=#{s.method(:each_with_object).owner}"
puts "inject=#{s.inject(:+)} reduce=#{s.reduce(1) { |a, n| a * n }} sahip=#{s.method(:inject).owner}"
puts "zip=#{s.zip(%w[a b c d]).inspect} sahip=#{s.method(:zip).owner}"
puts "partition=#{s.partition(&:even?).inspect} sahip=#{s.method(:partition).owner}"
puts "each_cons=#{s.each_cons(2).to_a.inspect} sahip=#{s.method(:each_cons).owner}"
```
```
each_with_object=[1, 4, 9, 16] sahip=Enumerable
inject=10 reduce=24 sahip=Enumerable
zip=[[1, "a"], [2, "b"], [3, "c"], [4, "d"]] sahip=Enumerable
partition=[[2, 4], [1, 3]] sahip=Enumerable
each_cons=[[1, 2], [2, 3], [3, 4]] sahip=Enumerable
```

`each_with_object` boş bir diziyi taşıyarak kareleri topladı. `inject(:+)` toplamı, `reduce(1) { ... }` çarpımı verdi; `inject`'in sahibi `Enumerable` olarak basıldı. `zip` iki diziyi çiftledi, `partition` blok doğru olanları ve olmayanları iki ayrı diziye ayırdı, `each_cons(2)` ardışık ikilileri verdi. Beş yöntemin beşinde de basılan sahip `Enumerable` oldu: `Range` kendi `each`'ini tanımlasa da bu zincirin yanıtlayanı modüldür. **KB27.** Sahip ölçümü yalnız `Range` alıcısıyla yapıldı; `reduce`'un sahibi ayrıca basılmadı.

## Tembel Zincir

`lazy` zinciri hemen çalıştırmaz; sonucu istenen kadar elemanı üretir. Sonsuz bir aralık üzerinde `select` ve `first(3)` bu yüzden tamamlanabilir. `with_index` ise elemanlara sıra ekler ve ilk sıra numarası verilebilir.

```ruby
# tembel.rb — lazy zincir ve with_index
puts (1..Float::INFINITY).lazy.select(&:even?).first(3).inspect
puts (1..3).lazy.class
puts "lazy sahip=#{(1..3).method(:lazy).owner}"
puts %w[a b].each.with_index(1).to_a.inspect
puts %w[a b].map.with_index { |h, i| "#{i}#{h}" }.inspect
```
```
[2, 4, 6]
Enumerator::Lazy
lazy sahip=Enumerable
[["a", 1], ["b", 2]]
["0a", "1b"]
```

Sonsuz aralıkta `first(3)` ilk üç çift sayıyı bulunca durdu ve `[2, 4, 6]` verdi. `lazy` iletisini `Enumerable` yanıtladı ve dönen nesnenin sınıfı `Enumerator::Lazy` oldu. `each.with_index(1)` sırayı birden başlattı; `map.with_index` ise bloğa elemanla birlikte sırayı verdi ve dönüştürülmüş diziyi üretti. **KB28.** Yalnız bu üç zincir ölçüldü.

## Dışarıdan Yineleyici

Bloksuz çağrılan `each` bir yineleyici döndürür; `next` onu elle ilerletir. Elemanlar bittiğinde `StopIteration` fırlatılır.

```ruby
# dis_yineleyici.rb — next ile elle ilerletme
e = [1, 2, 3].each
puts e.next
puts e.next
puts e.next
sonuc = begin
  e.next
rescue StopIteration
  "bitti"
end
puts sonuc
puts e.size
```
```
1
2
3
bitti
3
```

Üç `next` çağrısı elemanları sırayla verdi. Dördüncü çağrı `StopIteration` fırlattı, `rescue` onu yakaladı ve `bitti` basıldı. `size` `3` döndürdü. **KB29.** `size` yalnız bu örnekte ölçüldü; boyutu önceden bilinmeyen yineleyiciler ölçülmedi.

## Karışımdan Gelen Yöntemler

Kendi sınıfınız yalnız `each` tanımlayıp `Enumerable`'ı karıştırınca onlarca yöntem kazanır. Aşağıdaki `Kutu` sınıfı elemanlarını bir dizide tutar ve `each` içinde dizinin `each` yöntemine devreder. Ardından dokuz farklı yöntem çağrılır.

```ruby
# kutu.rb — yalniz each tanimlayan sinif
class Kutu
  include Enumerable

  def initialize(*elemanlar)
    @elemanlar = elemanlar
  end

  def each(&blok)
    @elemanlar.each(&blok)
    self
  end
end

k = Kutu.new(3, 1, 2)
puts "sort=#{k.sort.inspect} sahip=#{k.method(:sort).owner}"
puts "min=#{k.min} max=#{k.max} sum=#{k.sum}"
puts "map=#{k.map { |n| n * 2 }.inspect}"
puts "each_slice=#{k.each_slice(2).to_a.inspect}"
puts "first=#{k.first} count=#{k.count} sort_by=#{k.sort_by { |n| -n }.inspect}"
puts "each sahip=#{k.method(:each).owner}"
```
```
sort=[1, 2, 3] sahip=Enumerable
min=1 max=3 sum=6
map=[6, 2, 4]
each_slice=[[3, 1], [2]]
first=3 count=3 sort_by=[3, 2, 1]
each sahip=Kutu
```

`Kutu` yalnız `each` tanımladı; `sort`'un sahibi `Enumerable` olarak basıldı. `min`, `max`, `sum`, `map`, `each_slice`, `first`, `count` ve `sort_by` hep `each` üzerinden çalıştı ve beklenen sonuçları verdi. Yanıtlayan modüldür; `each`'in sahibi ise `Kutu`'dur. Modül, elemanlara nasıl ulaşılacağını sınıftan öğrenir. **KB42.** Yalnız bu dokuz yöntem denendi; karışımın her yönteminin çalıştığı varsayılmaz.

## each Olmayınca

Modül `each`'i kendisi sağlamaz, sınıfın tanımlaması gerekir. `each` tanımlamayan bir sınıf karışımı alır ama yöntemler çalışmaz.

```ruby
# bos.rb — each tanimlamayan sinif
class Bos
  include Enumerable
end

sonuc = begin
  Bos.new.map { |x| x }
rescue NoMethodError => hata
  hata.class
end
puts sonuc
puts Bos.new.respond_to?(:each)
```
```
NoMethodError
false
```

`Bos` sınıfı `Enumerable`'ı karıştırdı ama `each` tanımlamadı. `map` çağrısı `NoMethodError` fırlattı ve `respond_to?(:each)` `false` verdi. Sözleşme tek yönlüdür: `Enumerable` yöntemleri, sınıfın `each` yöntemini çağırabileceğini varsayar. **KB43.** Hata iletisi basılmadı; yalnız sınıfı ölçüldü.

## Sorgu Yöntemleri ve Sahipleri

`any?`, `all?`, `none?`, `find` ve `take_while` koleksiyonu sorgular. Bir dizide bu yöntemlerin hepsi `Enumerable`'dan mı gelir? Sahip satırı bunu ölçer.

```ruby
# sorgular.rb — sorgu yontemleri ve sahipleri
s = [1, 2, 3, 4]
puts "any=#{s.any? { |n| n > 3 }} all=#{s.all?(Integer)} none=#{s.none?(&:zero?)}"
puts "find=#{s.find { |n| n > 2 }} take_while=#{s.take_while { |n| n < 3 }.inspect}"
puts "sahip=#{s.method(:take_while).owner} #{s.method(:find).owner} #{s.method(:any?).owner}"
```
```
any=true all=true none=true
find=3 take_while=[1, 2]
sahip=Array Array Array
```

Sorgu sonuçları beklenen çıktı: `any?`, `all?(Integer)` ve `none?(&:zero?)` doğru, `find` `3`, `take_while` `[1, 2]` verdi. Üç yöntemin sahibi de `Array` olarak basıldı: dizi bu yöntemleri `Enumerable`'a bırakmadan kendi tanımlıyor. Önceki bölümde `Kutu` için `sort`'un sahibi `Enumerable`'dı; yani yanıtlayan alıcının sınıfına bağlıdır. **KB44.** Ölçüm Ruby 4.0.7'de ve yalnız `Array` alıcısıyla yapıldı.

## Karışımın Başka Yöntemleri

Karışımla gelen yöntemler yalnız toplama ve sıralamayla sınırlı değildir. En küçük ve en büyüğü birlikte veren `minmax`, ilk `n` küçüğü veren `min(2)`, sırayı da ileten `each_with_index`, tembel zincir ve tersten gezme de `each`'e dayanır. Aşağıdaki `Raf` sınıfı yine yalnız `each` tanımlar.

```ruby
# raf.rb — each tanimlayan ikinci sinif ve ek yontemler
class Raf
  include Enumerable

  def initialize(*elemanlar)
    @elemanlar = elemanlar
  end

  def each(&blok) = @elemanlar.each(&blok)
end

r = Raf.new(4, 2, 9)
puts r.minmax.inspect
puts r.min(2).inspect
puts r.each_with_index.map { |n, i| n * i }.inspect
puts r.lazy.map { |n| n + 1 }.first(2).inspect
puts r.entries.inspect
puts r.reverse_each.to_a.inspect
```
```
[2, 9]
[2, 4]
[0, 2, 18]
[5, 3]
[4, 2, 9]
[9, 2, 4]
```

`minmax` `[2, 9]`, `min(2)` `[2, 4]` verdi. `each_with_index.map` her elemanı sırasıyla çarptı: `[0, 2, 18]`. `lazy.map { ... }.first(2)` yalnız ilk iki elemanı dönüştürdü: `[5, 3]`. `entries` elemanları ekleniş sırasıyla, `reverse_each` tersine verdi. Altı çağrının hiçbirinde `Raf` yeni bir yöntem tanımlamadı; hepsi `each`'ten türedi. **KB52.** Bu yöntemlerin sahibi basılmadı; yalnız sonuçları ölçüldü.

## Sıralama İçin Comparable

`sort` elemanları `<=>` ile karşılaştırır. Bu karşılaştırmayı bilmeyen nesneler sıralanamaz. `<=>` tanımlayıp `Comparable`'ı karıştıran bir sınıf ise hem `sort`'a hem `min`'e hem de `<` gibi işleçlere kavuşur.

```ruby
# karsilastir.rb — comparable ve sort
class Nesne; end
sonuc = begin
  [Nesne.new, Nesne.new].sort
rescue ArgumentError => hata
  hata.class
end
puts sonuc

class Etiket
  include Comparable
  attr_reader :boy

  def initialize(boy)
    @boy = boy
  end

  def <=>(diger) = boy <=> diger.boy
end

puts [Etiket.new(3), Etiket.new(1)].sort.map(&:boy).inspect
puts [Etiket.new(3), Etiket.new(1)].min.boy
puts Etiket.new(1) < Etiket.new(2)
puts "sahip=#{Etiket.new(1).method(:<).owner}"
```
```
ArgumentError
[1, 3]
1
true
sahip=Comparable
```

`<=>` tanımı olmayan iki `Nesne` sıralanamadı: `sort` `ArgumentError` fırlattı. `Etiket` yalnız `<=>` tanımladı ve `Comparable`'ı karıştırdı; `sort` `[1, 3]`, `min` `1` verdi. `<` işleci de çalıştı ve `<`'ün sahibi `Comparable` olarak basıldı. İşleci yanıtlayan modüldür; sınıf yalnız karşılaştırma kuralını verdi. **KB53.** Ölçüm tek bir alanla yapıldı.

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

Modül her işi üstlenmez. Aynı adlı yöntem farklı alıcılarda farklı sahipten gelebilir: sınıf kendi tanımını yazdıysa o yanıtlar.

```ruby
# sahipler.rb — ayni ad, farkli sahipler
puts "(1..3).sum   #{(1..3).method(:sum).owner}"
puts "[3, 1].sum   #{[3, 1].method(:sum).owner}"
puts "[1].sort_by  #{[1].method(:sort_by).owner}"
puts "[3, 1].sort  #{[3, 1].method(:sort).owner}"
puts "[3, 1].min   #{[3, 1].method(:min).owner}"
puts "(1..3).min   #{(1..3).method(:min).owner}"
```
```
(1..3).sum   Enumerable
[3, 1].sum   Array
[1].sort_by  Enumerable
[3, 1].sort  Array
[3, 1].min   Array
(1..3).min   Range
```

`sum` aralıkta `Enumerable`'dan, dizide `Array`'den geliyor. `sort_by` dizide de `Enumerable`'a ait; ama `sort` ve `min` dizide `Array`'in kendi yöntemleri. Aralık için `min` ise `Range`'in kendi yöntemi. Sonuçlar Ruby 4.0.7'ye aittir. Altı satır, üç ayrı sahip verdi: `Enumerable`, `Array` ve `Range`. `sum` ve `min` adları her iki alıcıda da çalışır, çağıran taraf farkı görmez; ama iletiyi alıcıya göre bir sınıf ya da modül yanıtlar. Bu yüzden `owner` sorusu, yöntemin adından değil alıcının türünden başlar. **KB10.** Altı satırın hiçbiri sonucun değerini karşılaştırmaz; yalnız sahip sorulur, yani bu ölçüm modülün ve sınıfın aynı sonucu verip vermediğini söylemez. Yani aynı ad, alıcıya göre modülün ya da sınıfın yanıtıdır; bunun nedeni sonraki kursun konusudur ve burada açıklanmaz.

## Özet

- `Enumerable`, `each` tanımlayan her sınıfa `map`, `sort`, `min_by`, `group_by` ve `tally` gibi yöntemler kazandıran bir modüldür.
- Bu dersin yanıtlayanı **modül**dür: `(1..5).each_slice(2)` iletisini `Range` değil `Enumerable` yanıtlar.
- Kendi sınıfına `include Enumerable` ve tek bir `each` eklemek yeterlidir; `map`'in sahibi modül, `each`'in sahibi sınıf çıkar.
- Sınırlayıcı ölçüm: aynı ad alıcıya göre farklı sahipten gelir; `sum` aralıkta modülden, dizide `Array`'den gelir.

## Sonraki Adım

Bu derste bir yöntemin gövdesi `yield` ile bloğu çağırdı. Sonraki ders bloğu bir nesneye dönüştürür: `Proc` ve lambda, aynı kodu bir değişkende tutmanın iki yoludur ve `call` iletisinin sahibi bu iki yol için aynıdır.
