Groovy'nin uygulaması curry
aslında hiçbir noktada, perde arkasında bile köri yapmaz. Kısmi uygulama ile özdeştir.
curry
, rcurry
Ve ncurry
yöntem , bir geri CurriedClosure
nesne bağlı argümanlar tutar. Ayrıca getUncurriedArguments
, bağlı bağımsız değişkenlerle kendisine iletilen bağımsız değişkenlerin kompozisyonunu döndüren bir yöntem (yanlış adlandırılmış - işlevleri bozarsınız, bağımsız değişkenleri değil).
Bir kapatma çağrıldığında, sonuçta çağıran nesnenin bir örneği olup olmadığını açıkça kontrol eden invokeMethod
yönteminiMetaClassImpl
çağırır CurriedClosure
. Öyleyse, yukarıda belirtilenleri getUncurriedArguments
uygulamak için tüm argüman dizisini oluşturmak için kullanır :
if (objectClass == CurriedClosure.class) {
// ...
final Object[] curriedArguments = cc.getUncurriedArguments(arguments);
// [Ed: Yes, you read that right, curried = uncurried. :) ]
// ...
return ownerMetaClass.invokeMethod(owner, methodName, curriedArguments);
}
Yukarıdaki kafa karıştırıcı ve biraz tutarsız bir isimlendirmeye dayanarak, bunu yazan her kimsenin iyi bir kavramsal anlayışa sahip olduğundan şüpheleniyorum, ama belki biraz aceleci ve - birçok akıllı insan gibi - kısmi uygulama ile körelemeyi sınırladı. Biraz talihsiz ise bu anlaşılabilir (Paul King'in cevabına bakınız); geriye dönük uyumluluğu bozmadan bunu düzeltmek zor olacaktır.
Önerdiğim bir çözümcurry
, herhangi bir argüman iletilmediğinde, gerçek körelme yapacak şekilde yöntemin aşırı yüklenmesi ve yöntemin yeni bir partial
işlev lehine argümanlarla çağrılmasının kaldırılmasıdır . Bu biraz garip gelebilir , ancak sıfır argümanla kısmi uygulama kullanmak için bir sebep olmadığından geriye dönük uyumluluğu en üst düzeye çıkarırken, işlev aslında gerçek körelme için yeni, farklı adlandırılmış bir işleve sahip olmanın (IMHO) çirkin durumundan kaçınırken adlı curry
farklı ve kafa karıştırıcı bir şey yapar.
Arama sonucunun curry
gerçek körelemeden tamamen farklı olduğunu söylemeye gerek yok . İşlevi gerçekten köreltiyorsa, şunları yazabilirsiniz:
def add = { x, y -> x + y }
def addCurried = add.curry() // should work like { x -> { y -> x + y } }
def add1 = addCurried(1) // should work like { y -> 1 + y }
assert add1(1) == 2
Çünkü ... ve o çalışacak addCurried
gibi çalışması gerekir{ x -> { y -> x + y } }
. Bunun yerine bir çalışma zamanı istisnası atar ve içinde biraz ölürsün.