mame tarafından 12.12.2019 tarihinde gönderildi
Çeviri: İsmail Arılık
Bu makale Ruby 3.0’daki planlanan anahtar kelime argümanlarının uyumsuzluklarını açıklamaktadır.
tl;dr
Ruby 3.0’da konumsal ve anahtar kelime argümanları ayrılacaktır. Ruby 2.7, Ruby 3.0’da değişecek davranışlar konusunda uyarı gösterecektir. Eğer aşağıdaki uyarıları görüyorsanız, kodunuzu güncellemelisiniz:
Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
, ya daPassing the keyword argument as the last hash parameter is deprecated
, ya daSplitting the last argument into positional and keyword parameters is deprecated
Çoğu durumda çift splat operatörü ekleyerek uyumsuzluktan kaçınılabilir.
Bu operatör harici olarak, bir Hash
nesnesi yerine anahtar kelime argümanları geçirildiğini ifade eder.
Harici olarak, anahtar kelime argümanları yerine bir Hash
nesnesi geçirmek içinse süslü parantezler ({}
) ekleyebilirsiniz.
Daha fazla ayrıntı için aşağıdaki “Tipik durumlar” bölümünü okuyun.
Ruby 3’te, tüm argümanları yetkilendiren bir metod, konumsal argümanlara ilaveten harici olarak anahtar kelime argümanlarını da yetkilendirmelidir.
Ruby 2.7 ve öncesinde bulunan yetkilendirme davranışını korumak istiyorsanız, ruby2_keywords
‘ü kullanın.
Daha fazla ayrıntı için aşağıdaki “Argüman yetkilendirmeyi ele alma” bölümüne bakın.
Tipik durumlar
İşte en tipik durumlar.
Hash yerine anahtar kelimeleri geçmek için çift splat operatörünü (**
) kullanabilirsiniz.
Bir diğer durum. Anahtar kelimeler yerine Hash geçirmek için harici olarak süslü parantezleri kullanabilirsiniz.
Sonu gelen hangisi?
Ruby 2’de anahtar kelime argümanları son konumsal Hash argümanı olarak düşünülebilir ve son konumsal Hash argümanı anahtar kelime argümanları olarak düşünülebilir.
Otomatik çevrim son bölümde açıklandığı gibi bazen çok karmaşık ve sıkıntılı olduğu için, Ruby 2.7 ile birlikte sonunun geldiği belirtilecek ve Ruby 3’te kaldırılacaktır.
Diğer bir deyişle, Ruby 3’te anahtar kelime argümanları, konumsal olanlardan tamamen ayrılacaktır.
Yani anahtar kelime argümanları geçirmek istediğinizde her zaman foo(k: expr)
ya da foo(**expr)
kullanmalısınız.
Eğer anahtar kelime argümanları kabul etmek istiyorsanız, prensipte her zaman def foo(k: default)
ya da def foo(k:)
ya da def foo(**kwargs)
kullanmalısınız.
Anahtar kelime argümanları ile anahtar kelime argümanları kabul etmeyen bir metod çağrıldığında, Ruby 3.0’ın farklı davranmayacağına dikkat edin. Örneğin, aşağıdaki durumun desteği sonlanmayacaktır ve bu durum Ruby 3.0’da çalışmaya devam edecektir. Anahtar kelime argümanları hala konumsal bir Hash argümanı olarak değerlendirilir.
Çünkü bu tarz çok sık kullanılmaktadır ve argümanın nasıl değerlendirileceği konusunda bir kafa karışıklığı ihtimali yoktur. Bu çevrimi yasaklamak, küçük bir fayda için ek uyumsuzluklara neden olacaktır.
Fakat bu tarz, yeni kodlarda tavsiye edilmez, tabii sık sık bir Hash’i konumsal bir argüman olarak geçirip ayrıca anahtar kelime argümanlarını kullanmıyorsanız. Diğer türlü çift splat kullanın:
Kodum Ruby 2.7’de patlayacak mı?
Kısa cevap: “Patlamayabilir.”
Ruby 2.7’deki değişiklikler, 3.0’a doğru bir göç etme yolu olarak tasarlanmaktadır. Prensipte Ruby 2.7, Ruby 3’te değişecek özelliklere karşı sadece uyarsa da, küçük olduğunu düşündüğümüz bazı uyumsuz değişiklikler içermektedir. Ayrıntılar için “Diğer küçük değişiklikler” bölümüne bakınız.
Uyarılar ve küçük değişiklikler dışında Ruby 2.7, Ruby 2.6 ile uyumlu olmaya çalışmaktadır. Yani kodunuz muhtemelen Ruby 2.7’de çalışacaktır, tabii uyarılar verebilir. Ayrıca kodunuzu Ruby 2.7’de çalıştırarak, onun Ruby 3.0 için hazır olup olmadığını kontrol edebilirsiniz.
Tüm uyarıları kapatmak istiyorsanız, lütfen $VERBOSE = nil
‘i ayarlayın (genel olarak bu, tavsiye edilmez).
Ruby 2.7, uyarı görünürlüğünü daha iyi kontrol etmek için yeni bir mekanizma ekleyebilir (Özellik #16345).
Fakat bu özelliğin son sürümde olup olmayacağına henüz karar vermedik.
Eğer ileride kaldırılma uyarılarını kapatmak istiyorsanız, lütfen -W:no-deprecated
komut satırı argümanını kullanın ya da Warning[:deprecated] = false
ifadesini kodunuza ekleyin.
Argüman yetkilendirmeyi ele alma
Ruby 2.6 ya da öncesi
Ruby 2’de, bir *rest
ve &block
argümanı kabul ederek ve bu ikisini hedef metoda geçirerek bir yetkilendirme metodu yazabilirsiniz.
Bu davranışta anahtar kelime argümanları da konumsal argümanlar ve anahtar kelime argümanları arasındaki çevrim ile dahili olarak ele alınırlar.
Ruby 3
Anahtar kelime argümanlarını harici olarak yetkilendirmeniz gerekir.
Alternatif olarak, eğer Ruby 2.6 ya da öncesi ile uyumluluğa ihtiyacınız yoksa ve herhangi bir argümanı değiştirmiyorsanız, Ruby 2.7’de tanıtılan yeni yetkilendirme sözdizimini (...
) kullanabilirsiniz.
Ruby 2.7
Kısaca: Module#ruby2_keywords
‘ü kullanın ve *args, &block
‘u yetkilendirin.
ruby2_keywords
, son Hash argümanı olarak anahtar kelime argümanlarını kabul eder, ve diğer metodu çağırırken bunu anahtar kelime argümanları olarak geçirir.
Aslında Ruby 2.7 birçok durumda yeni tarz yetkilendirmeyi destekler. Fakat bilinen bir çıkmaz var. Bir sonraki bölüme bakın.
Ruby 2.6, 2.7 ve Ruby 3’te çalışan uyumlu bir yetkilendirme
Kısaca: Yine, Module#ruby2_keywords
‘ü kullanın.
Maalesef eski tarz yetkilendirmeyi (yani **kwargs
olmadan) kullanmalıyız çünkü Ruby 2.6 ya da öncesi yeni yetkilendirme tarzını doğru şekilde ele almaz.
Bu, anahtar kelime ayrımının nedenlerinden biridir; ayrıntılar son bölümde açıklanmaktadır.
ruby2_keywords
, eski tarzı Ruby 2.7 ve 3.0’da bile çalıştırmanızı sağlar.
2.6 ya da öncesinde tanımlı bir ruby2_keywords
olmadığı için, lütfen ruby2_keywords gem‘ini kullanın ya da bunu kendiniz tanımlayın:
Eğer kodunuzun Ruby 2.6 ya da öncesinde çalışması gerekmiyorsa, Ruby 2.7’deki yeni tarzı deneyebilirsiniz. Bu neredeyse her durumda çalışır. Fakat maalesef aşağıdaki gibi çıkmazlar vardır:
Boş bir Hash argümanı otomatik olarak çevrilir ve **kwargs
‘a çekilir, ve yetkilendirme çağrısı boş anahtar kelime hash’ini kaldırır, yani target
‘a hiçbir argüman geçirilmez.
Bildiğimiz kadarıyla bu, tek çıkmaz durum.
Son satırda belirtildiği üzere, bu çıkmazın çevresinden **{}
argümanını kullanarak dolaşabilirsiniz.
Eğer gerçekten taşınabilirlik konusunda endişeleniyorsanız, ruby2_keywords
‘ü kullanın.
(Ruby 2.6 ya da öncesinin de anahtar kelime argümanları konusunda bir sürü çıkmaza sahip olduğunu kabul edin. :-)
İleride, Ruby 2.6’nın hayatının sonuna gelmesiyle birlikte ruby2_keywords
silinebilir.
Bu noktada, anahtar kelime argümanlarını harici olarak yetkilendirmenizi tavsiye ederiz (yukarıdaki Ruby 3 koduna bakın).
Diğer küçük değişiklikler
Anahtar kelime argümanları konusunda Ruby 2.7’de üç küçük değişiklik var.
1. Sembol olmayan anahtarlar anahtar kelime argümanlarında kullanılabilir
Ruby 2.6 ve öncesinde anahtar kelime argümanlarında sadece Sembol anahtarlara izin veriliyordu. Ruby 2.7’de anahtar kelime argümanları Sembol olmayan anahtarlar kullanabilir.
Eğer bir metod hem isteğe bağlı argümanları hem de anahtar kelime argümanlarını kabul ediyorsa, hem Sembol anahtarlara hem de Sembol olmayan anahtarlara sahip bir Hash nesnesi Ruby 2.6’da ikiye ayrılır. Ruby 2.7’de ikisi de anahtar kelime olarak kabul edilir çünkü Sembol olmayan anahtarlara izin verilir.
Ruby 2.7 eğer harici anahtar kelimeler kabul eden fakat anahtar kelime gerisi argümanı (**kwargs
) kabul etmeyen bir metoda hem Sembol hem de Sembol olmayan anahtarlar ile bir Hash ya da anahtar kelime argümanları geçirilirse, yine de hash’leri ayırır.
Bu davranış Ruby 3’te kaldırılacaktır, ve bir ArgumentError
yükseltilecektir.
2. Boş bir hash (**{}
) ile çift splat hiçbir argüman geçirmez
Ruby 2.6 ve öncesinde, **empty_hash
geçirmek konumsal bir boş Hash argümanı geçirir.
Ruby 2.7 ve sonrasında ise hiçbir argüman geçirmez.
foo(**{})
‘nun Ruby 2.6’da da 2.7’de de hiçbir şey geçirmediğine dikkat edin.
Ruby 2.6 ve öncesinde **{}
, ayrıştırıcı tarafından kaldırılır, ve Ruby 2.7’de ve sonrasında bu, **empty_hash
olarak düşünülür, ki bu da bir metoda hiçbir anahtar kelime argümanı geçirmemek için kolay bir yol sunar.
Ruby 2.7’de, bir metod yetersiz konumsal argüman ile çağrıldığında, Ruby 2.6 ile uyumlu olabilmek için foo(**empty_hash)
bir uyarı yayınlayarak boş bir hash geçirir.
Bu davranış 3.0’da kaldırılacaktır.
3. Anahtar-kelime-argümanı-yok sözdizimi (**nil
) tanıtıldı
Bir metodun hiçbir anahtar kelime argümanı kabul etmediğini harici olarak belirtmek için bu metodun tanımında **nil
kullanabilirsiniz.
Bu gibi metodları anahtar kelime argümanları ile çağırmak ArgumentError
‘a neden olacaktır.
(Aslında bu yeni bir özelliktir, bir uyumsuzluk değildir.)
Bir metodun anahtar kelime argümanlarını kabul etmediğini harici olarak belirtmek kullanışlıdır. Diğer türlü, anahtar kelimeler yukarıdaki örnekteki gibi gerisi argümanına çekilir. Eğer bir metodu, anahtar kelime argümanları kabul etmek için genişletiyorsanız, bu metod aşağıdaki gibi bir uyumsuzluğa sahip olabilir:
Neden otomatik çevrimin sonunu getiriyoruz
Otomatik çevrim başta iyi bir fikir gibiydi, ve çoğu durumda iyi çalıştı. Fakat çok fazla sivrilikler vardı ve davranış hakkında birçok hata raporu aldık.
Otomatik çevrim, bir metod isteğe bağlı argümanlar ve anahtar kelime argümanları kabul ettiğinde, iyi çalışmamaktadır. Bazı kişiler son Hash nesnesinin konumsal bir argüman olarak değerlendirilmesini, diğerleri ise anahtar kelime argümanlarına çevrilmesini beklemektedir.
İşte en çok kafa karıştıran durumlardan birisi:
Ruby 2’de foo({})
, boş bir Hash’i normal bir argüman olarak geçirir (yani {}
, x
‘e geçirilir), fakat bar({})
bir anahtar kelime argümanı geçirir (yani {}
, kwargs
‘a atanır).
Yani any_method({})
oldukça kafa karıştırıcıdır.
bar({}, **{})
‘ı, x
‘e harici olarak boş bir hash geçiriyormuşuz gibi düşünebilirsiniz.
Şaşırtıcı biçimde bu, beklediğiniz şekilde çalışmaz; Ruby 2.6’da hala [1, {}]
yazdırır.
Bunun nedeni Ruby 2.6’da ayrıştırıcının **{}
argümanını boşvermesi ve ilk sıradaki {}
argümanının otomatik olarak anahtar kelimelere (**kwargs
) çevrilmesidir.
Bu durumda bar({}, {})
‘ı çağırmalısınız, fakat bu fazla garip durmaktadır.
Aynı durumlar gerisi ve anahtar kelime argümanları kabul eden metodlarda da vardır. Bu, anahtar kelime argümanlarının harici yetkilendirmesini çalışmaz hale getirir.
foo()
hiçbir argüman geçirmez, fakat target
Ruby 2.6’da boş bir hash argümanı alır.
Bunun nedeni foo
metodunun anahtar kelimeleri (**kwargs
) harici olarak yetkilendirmesidir.
foo()
çağrıldığında args
boş bir Array, kwargs
boş bir Hash, block
ise nil
‘dir.
Sonrasında target(*args, **kwargs, &block)
argüman olarak boş bir Hash geçirir çünkü **kwargs
otomatik olarak konumsal bir Hash argümanına çevrilir.
Otomatik çevrim sadece insanların kafasını karıştırmakla kalmaz ayrıca metodu daha az genişletilebilir yapar. Davranıştaki değişikliğin nedenleri ve belirli gerçeklemelerin neden seçildiği ile ilgili daha fazla ayrıntı için [Özellik #14183]‘e bakın.
Teşekkür
Bu makale Jeremy Evans and Benoit Daloze tarafından nazikçe gözden geçirilmiştir (hatta onlarla birlikte yazılmıştır).
Değişiklik Günlüğü
- 23 Aralık 2019: 2.7.0-rc2’de uyarı mesajları biraz değişti, ve uyarıları bastırmak için bir API eklendi.