---
title: 'Proc ve Lambda'
source: 'https://academia.sh/tr/kurslar/ruby-temelleri/proc-ve-lambda'
course: 'Ruby Temelleri'
language: tr
updated: '2026-10-21T05:03:43+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Bir bloğu proc ya da lambda olarak bir değişkene atar ve call ile çağırır'
    - 'Proc ve lambda arasındaki argüman denetimi farkını ölçer'
    - 'lambda? ile bir nesnenin hangi türde olduğunu sorar'
    - 'call yönteminin sahibinin iki tür için de aynı olduğunu ölçer'
---

# Proc ve Lambda

Bir bloğun nesneye dönüştürülmesinin iki yolu olan proc ve lambda için call iletisini bir sınıfın yanıtladığı, farkın argüman denetiminde ve lambda? durumunda yattığı ölçülür.

Önceki iki derste blok yalnız bir yöntemin çağrısına eşlik eden kod parçasıydı: yazıldığı yerde kaldı, bir değişkende doğrudan saklanamadı. **Proc**, bloğu bir nesneye dönüştürür; **lambda** ise aynı nesnenin daha kati davranan biçimidir. İkisinin de sınıfı `Proc`'tur. Bir proc, tanımlandığı kapsamdaki değişkenleri taşır; bu özelliğe M01/K02'de **kapanış (closure)** denmişti ve burada yeniden tanımlanmaz.

Bu dersin yanıtlayanı **sınıf**tır: `call` iletisini `Proc` sınıfı yanıtlar. Fark ise sınıfta değil, nesnenin **lambda? durumu**ndadır.

## Çağırmanın Üç Yolu

Lambda `->` ile yazılır. Çağırmak için `call`, nokta-parantez kısayolu `.()` ya da köşeli parantez kullanılır; üçü aynı iletidir. Çekirdek bu çağrıyı sınıflandırır: `call`'ın sahibi bir `Class` ise yanıtlayan **sınıf**tı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
# lambda.rb — lambda cagrisini kim yanitliyor
require_relative "yanit"

iki_kat = ->(n) { n * 2 }
sahip = iki_kat.method(:call).owner
tur, kanit = yanitlayan(defined?(iki_kat.call(3)), sahip: sahip, sonuc: iki_kat.call(3))
puts "#{tur}  #{kanit}"
puts iki_kat.class
puts iki_kat.call(3)
puts iki_kat.(3)
puts iki_kat[3]
```
```
sinif  Proc, sonuc 6
Proc
6
6
6
```

İlk satır çekirdeğin `lambda cagrisi` gözlemidir: yanıtlayan **sınıf**, sahip `Proc`. Üç çağrı biçimi de `6` verdi. **KB11.** Üç biçim bu derste aynı sonuçla ölçüldü; hangisinin tercih edildiği bir yazım tercihidir ve ölçülmez.

## Proc ile Lambda Arasındaki Fark

Fark ilk bakışta görünmez: ikisi de çağrılır, ikisi de değer döndürür. Ayrım argüman denetiminde ortaya çıkar. Lambda tam sayıda argüman bekler; proc ise fazlayı yok sayar, eksiği `nil` ile doldurur. Hata durumunda lambda'nın fırlattığı istisnanın sınıfı basılır, iletisi değil.

```ruby
# fark.rb — proc ve lambda arasindaki arguman farki
gevsek = proc { |x| x }
kati = lambda { |x| x }
puts gevsek.call(1, 2)

sonuc = begin
  kati.call(1, 2)
rescue ArgumentError => hata
  hata.class
end
puts sonuc

cift = proc { |x, y| [x, y] }
puts cift.call(1).inspect
puts "gevsek=#{gevsek.lambda?} kati=#{kati.lambda?}"
```
```
1
ArgumentError
[1, nil]
gevsek=false kati=true
```

Proc iki argümanı birden verildiğinde fazlayı bıraktı ve `1` döndürdü; lambda aynı çağrıda `ArgumentError` fırlattı. İki parametreli proc'a tek argüman verilince eksik parametre `nil` oldu. `lambda?` ikisini ayırır: proc için `false`, lambda için `true`.

## Başka Nesnelerden Proc

Ruby'de başka kaynaklardan da proc elde edilir: bir yöntem nesnesinden `to_proc`, bir sembolden `to_proc`. İkisi de lambda gibi davranır.

```ruby
# donusum.rb — yontem ve sembol proc'a donusur
def kare(n)
  n * n
end

puts method(:kare).to_proc.lambda?
puts :upcase.to_proc.lambda?
puts :upcase.to_proc.call("a")
```
```
true
true
A
```

Yöntemden ve sembolden elde edilen proc'ların `lambda?` değeri `true`. `:upcase.to_proc.call("a")` büyük harfli dizgiyi verdi. Bu, önceki derste görülen `select(&:even?)` biçiminin arkasındaki düzenektir: `&` sembolü bir proc'a çevirir ve bloğun yerine verir.

## Değişkeni Taşımak

Bir proc, tanımlandığı kapsamdaki değişkenlere bağlı kalır. Bunu görmek için bir yöntem bir lambda döndürür ve lambda, yöntem bittikten sonra bile değişkeni artırmaya devam eder.

```ruby
# sayac.rb — lambda tanimlandigi yerdeki degiskeni tasir
def sayac_uret
  adet = 0
  -> { adet += 1 }
end

birinci = sayac_uret
ikinci = sayac_uret
puts birinci.call
puts birinci.call
puts ikinci.call
puts birinci.call
```
```
1
2
1
3
```

Her `sayac_uret` çağrısı kendi `adet` değişkenini kurdu. `birinci` sırayla `1`, `2` ve `3` verdi; `ikinci` kendi sayacından `1` verdi. Yöntem bitmişti, ama lambda değişkeni taşımaya devam etti. **KB13.** Bu ölçüm iki bağımsız sayacı gösterir; aynı değişkeni paylaşan iki lambda bu derste ölçülmez.

## Nesneyi Blok Yerine Vermek

Bir proc ya da lambda, başına `&` konarak bir yönteme blok olarak verilebilir. Bu, Bloklar dersindeki `map` ile bu dersin nesnelerini birleştirir. `arity` ise nesnenin kaç parametre beklediğini sayı olarak verir.

```ruby
# blok_yerine.rb — nesneyi blok olarak vermek ve arity
iki_kat = ->(n) { n * 2 }
gevsek = proc { |x, y| [x, y] }
puts [1, 2, 3].map(&iki_kat).inspect
puts "arity lambda=#{iki_kat.arity} proc=#{gevsek.arity}"
puts [[1, 2], [3, 4]].map(&gevsek).inspect
```
```
[2, 4, 6]
arity lambda=1 proc=2
[[1, 2], [3, 4]]
```

`map(&iki_kat)` her elemanı lambda'ya verip `[2, 4, 6]` topladı: ayrı bir blok yazmak gerekmedi. `arity` lambda için `1`, iki parametreli proc için `2` döndü. İç içe dizilerde proc her alt diziyi iki parametreye bölüp `[x, y]` dizisini yeniden kurdu, bu yüzden sonuç girdiyle aynı göründü. **KB14.** Bu ölçümde lambda her zaman tek elemanlı çağrıldı; lambda'ya `&` ile iç içe dizi verildiğinde ne olduğu ölçülmedi.

## return Nerede Döner

Proc ile lambda arasındaki bir fark da `return`'ün nereye döndüğüdür. Aşağıdaki iki yöntem aynı işi yapar: içeride bir nesne kurar, çağırır ve ardından `2` döndürmeye çalışır.

```ruby
# donus_farki.rb — proc ve lambda icinde return
def proc_ile
  p = proc { return 1 }
  p.call
  2
end

def lambda_ile
  l = lambda { return 1 }
  l.call
  2
end

puts proc_ile
puts lambda_ile
```
```
1
2
```

`proc_ile` `1` döndürdü: proc içindeki `return`, proc'u değil onu çevreleyen yöntemi bitirdi ve `2` satırına hiç ulaşılmadı. `lambda_ile` ise `2` döndürdü: lambda içindeki `return` yalnız lambda'yı bitirdi, yöntem kaldığı yerden sürdü. **KB30.** Ölçüm yalnız yöntem içinde yapıldı; üst düzeyde bir proc içindeki `return` bu derste denenmedi.

## Kısmi Uygulama

`curry`, çok parametreli bir lambda'yı her çağrıda bir parametre alan bir zincire çevirir. Parametrelerin bir kısmı verilince geriye kalanı bekleyen yeni bir nesne döner.

```ruby
# curry.rb — curry ile parametre parametre cagirma
topla = ->(a, b, c) { a + b + c }
puts topla.curry[1][2][3]
puts topla.curry.(1, 2).(3)
kismi = topla.curry[1]
puts kismi.class
puts kismi.lambda?
```
```
6
6
Proc
true
```

Üç köşeli parantezle ve `(1, 2).(3)` biçimiyle `curry` aynı sonucu, `6`'yı verdi. `topla.curry[1]` bir `Proc` döndürdü ve bu nesne hâlâ bir lambda'ydı. **KB31.** `curry` yalnız sabit parametreli bir lambda ile ölçüldü.

## Yöntem Nesnesi

`method(:ad)` bir yöntemi nesneye çevirir. Bu nesne çağrılabilir, sahibi sorulabilir ve `&` ile bloğa dönüştürülebilir.

```ruby
# yontem_nesnesi.rb — method ile Method nesnesi ve to_proc
def kare(n) = n * n
m = method(:kare)
puts m.class
puts m.call(4)
puts "sahip=#{m.owner} arity=#{m.arity}"
puts [1, 2, 3].map(&m).inspect
puts m.to_proc.class
```
```
Method
16
sahip=Object arity=1
[1, 4, 9]
Proc
```

`method(:kare)` bir `Method` nesnesi verdi ve `call(4)` `16` döndürdü. Üst düzeyde tanımlanan `kare`'nin sahibi `Object` olarak basıldı. `map(&m)` yöntemi blok yerine verdi ve `[1, 4, 9]` üretti; `to_proc` ise bir `Proc` döndürdü. **KB32.** Ölçüm yalnız üst düzeyde tanımlı bir yöntemle yapıldı.

## Blok ile Proc Arasındaki Dönüşüm

Bir yöntemin son parametresi `&blok` ise, kendisine verilen blok bir `Proc` nesnesine çevrilir. Tersine, bir lambda `&` ile bloğun yerine verilebilir. Aşağıdaki ölçüm, bu iki yönde nesnenin kimliğinin korunup korunmadığına bakar.

```ruby
# blok_proc.rb — blok ve lambda arasindaki donusum
def al(&blok) = blok
b = al { |x| x + 1 }
puts b.class
puts b.lambda?
puts b.call(1)
l = ->(x) { x + 1 }
puts al(&l).equal?(l)
puts al(&l).lambda?
```
```
Proc
false
2
true
true
```

Bloktan dönen nesne bir `Proc` oldu ve `lambda?` `false` verdi. Bir lambda `&l` ile verilince ise `al` aynı nesneyi geri döndürdü: `equal?` `true` ve `lambda?` hâlâ `true`. Yani `&` bir lambda'yı proc'a dönüştürmedi. **KB33.** Ölçüm yalnız tek parametreli bir blok ve bir lambda ile yapıldı.

## Çağrılabilir Nesneleri Birleştirmek

`>>` ve `<<` iki çağrılabilir nesneyi tek bir `Proc` içinde birleştirir. `f >> g` önce `f`'yi sonra `g`'yi uygular; `f << g` ise tersini yapar. `Method` nesnesi de aynı birleştirmeye katılabilir.

```ruby
# birlestir.rb — proc birlestirme
art = ->(x) { x + 1 }
iki = ->(x) { x * 2 }
puts (art >> iki).call(3)
puts (art << iki).call(3)
puts (art >> iki).class
puts (method(:Integer) >> art).call("4")
```
```
8
7
Proc
5
```

`(art >> iki).call(3)` önce `art`'ı sonra `iki`'yi uyguladı: `(3 + 1) * 2 = 8`. `(art << iki).call(3)` sırayı ters çevirdi: `art(iki(3)) = 7`. Birleştirme sonucu bir `Proc` oldu. `method(:Integer) >> art` bir `Method` nesnesini lambda ile birleştirdi: `"4"` önce `4` oldu, sonra `5` verdi. **KB45.** Ölçüm tek parametreli lambda'larla yapıldı.

## arity ve parameters

`arity` bir çağrılabilir nesnenin kaç parametre beklediğini, `parameters` ise her birinin türünü bildirir. Proc ile lambda aynı parametre listesini farklı bildirebilir.

```ruby
# arity.rb — arity ve parameters
puts proc { |a, b| }.arity
puts lambda { |a, b| }.arity
puts proc { |*a| }.arity
puts lambda { |a, b = 1| }.arity
puts lambda { |a, b = 1| }.parameters.inspect
puts proc { |a, b| }.parameters.inspect
```
```
2
2
-1
-2
[[:req, :a], [:opt, :b]]
[[:opt, :a], [:opt, :b]]
```

`proc { |a, b| }` ve `lambda { |a, b| }` ikisi de `2` bildirdi. `*a` ile `-1`, bir zorunlu ve bir isteğe bağlı parametreyle `-2` basıldı: iki ölçümde de negatif değer, zorunlu parametre sayısının bir fazlasının eksilisiydi. `parameters` farkı gösterir: lambda'da `a` zorunlu (`:req`), proc'ta aynı parametre isteğe bağlı (`:opt`). Proc ile Lambda Arasındaki Fark bölümündeki gevşeklik böylece nesnenin kendi tanımında okunur. **KB46.**

## Kapanış Değişkeni Paylaşır

Lambda, dıştaki yerel değişkenin değerini değil değişkenin kendisini taşır. Değişken sonradan değişirse lambda yeni değeri görür; lambda değişkene yazarsa dıştaki değişken de değişir.

```ruby
# paylasim.rb — kapanis ve dis degisken
x = 1
oku = -> { x }
x = 5
puts oku.call
yaz = -> { x = 9 }
yaz.call
puts x
```
```
5
9
```

`oku` tanımlandığında `x` `1`'di; `x` sonradan `5` yapıldı ve `oku.call` `5` verdi. `yaz` içindeki `x = 9` dıştaki `x`'e yazdı ve `puts x` `9` bastı. Lambda bir kopya değil, tanımlandığı yerdeki değişkeni kullanır. **KB47.** Ölçüm üst düzeydeki yereller içindir; yöntem sınırını geçen durum Değişkeni Taşımak bölümünde ölçüldü.

## case ile Lambda

`case` ifadesi `when` koşulunu `===` ile sınar. Bir lambda, `Proc#===` sayesinde bu sınamaya doğrudan katılabilir: `===` lambda'yı verilen değerle çağırır.

```ruby
# case_lambda.rb — when kolunda lambda
cift = ->(n) { n.even? }
[1, 2].each do |n|
  case n
  when cift then puts "#{n} cift"
  else puts "#{n} tek"
  end
end
puts cift === 2
puts "sahip=#{cift.method(:===).owner}"
```
```
1 tek
2 cift
true
sahip=Proc
```

`when cift` lambda'yı her `n` için çağırdı: `1` için `false` döndüğünden `else` koştu, `2` için `true` döndüğünden `when` kolu koştu. `cift === 2` doğrudan `true` verdi ve `===`'ün sahibi `Proc` olarak basıldı. Böylece `case`, koşulu sınarken lambda'ya `===` iletisini gönderir ve yanıtlayan bir sınıftır. Bu, Proc ve Lambda dersinin ortak sorusuna bağlanır: aynı çağrılabilir nesne `call` ile, `.()` ile, `&` ile blok yerine ve burada `===` ile kullanılabilir; her birinde nesnenin kendisi aynıdır, yalnız ileti değişir. **KB54.** Ölçüm tek parametreli bir lambda ile yapıldı; çok parametreli lambda'nın `when` kolunda davranışı denenmedi. `===` kolunun değeri `case`'in kendi sınamasında kullanıldığı için bu ölçümde ayrıca bir sonuç değişkenine atanmadı.

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

Proc ile lambda arasındaki farkı `call`'ın sahibine bakarak görebilir miyiz? Hayır: iki tür için de sahip aynıdır, çünkü ikisi de `Proc` sınıfının örneğidir. Fark sahipte değil, nesnenin durumundadır.

```ruby
# sahip.rb — call iletisinin sahibi iki turde de ayni
gevsek = proc { |x| x }
kati = lambda { |x| x }
puts "proc    #{gevsek.method(:call).owner} lambda?=#{gevsek.lambda?}"
puts "lambda  #{kati.method(:call).owner} lambda?=#{kati.lambda?}"
```
```
proc    Proc lambda?=false
lambda  Proc lambda?=true
```

Sahip iki satırda da `Proc`; yalnız `lambda?` farklı. Önceki derslerde `owner` sorusu bir yöntemin hangi sınıfta ya da modülde tanımlı olduğunu ayırıyordu; burada iki nesne aynı sınıftan olduğu için aynı soru bir farkı ortaya çıkarmıyor. Aynı iletiyi iki nesneye göndermek iki ayrı yanıtlayanı değil, tek yanıtlayanın iki durumunu veriyor. Yani `owner` sorusu, `proc` ile lambda arasındaki farkı göstermez: sınıf aynıdır, farkı nesnenin kendi durumu taşır. **KB12.** Bu ölçüm yalnız `call` iletisini sorar; başka iletilerde sahip farkı olup olmadığı bu derste ölçülmez.

## Özet

- Proc ve lambda, bir bloğu nesneye çeviren iki yoldur; ikisinin de sınıfı `Proc`'tur.
- Bu dersin yanıtlayanı **sınıf**tır: `call` iletisini `Proc` yanıtlar ve `call`, `.()` ve köşeli parantez aynı sonucu verir.
- Lambda argüman sayısını denetler ve fazlalıkta `ArgumentError` fırlatır; proc fazlayı bırakır, eksiği `nil` yapar.
- Yöntem nesnesinden ve sembolden elde edilen proc'lar `lambda?` bakımından `true` döner.
- Sınırlayıcı ölçüm: `call` sahibi iki tür için de `Proc`'tur; fark `lambda?` durumundadır.

## Sonraki Adım

Bir lambda'nın hatası argüman sayısıydı. Sonraki ders hata kavramının kendisine geçer: `rescue` bir yöntem değil, dilin kendi yapısıdır ve bu yapının hangi ifadelerde ne döndürdüğü ölçülecektir.
