2011-09-07 18 views
5

Bir i fonksiyonu uygulayan bir kredi kalıbı var, burada 'i' artan değişken. "Bazen", "i" ye erişebilmek için işlevin geçmesini istiyorum .... ama 'i' kabul etmek için bir parametrenin tanımlanmasını gerektiren tüm işlevlerin aktarılmasını istemiyorum. Aşağıdaki Örnek ...scala kredi kalıbı, isteğe bağlı fonksiyon param

def withLoaner = (n:Int) => (op:(Int) => String) => { 
    val result = for(i <- 1 to n) yield op(i) 
    result.mkString("\n") 
} 

def bob = (x:Int) => "bob" // don't need access to i. is there a way use() => "bob" instead? 
def nums = (x:Int) => x.toString // needs access to i, define i as an input param 

println(withLoaner(3)(bob)) 

println(withLoaner(3)(nums)) 
+0

soruya ilişkin, ancak def f yazarsanız değil: expr => (args) yerine (Ben genel olarak bunu yapmaz emin) def f (args) = expre yerine, hem oldukça fa val yapabilir bir def. –

cevap

11
def withLoaner(n: Int) = new { 
    def apply(op: Int => String) : String = (1 to n).map(op).mkString("\n") 
    def apply(op:() => String) : String = apply{i: Int => op()} 
} 

(o kredi modeli ile ilgili nasıl emin değilim) yorumunda istendiği gibi

Düzenleme Küçük açıklama.

Scala hakkında ne bildiğinizden ve bilmediğinizden ve bu kodda neleri kestiğinizden emin olmadığınızdan emin olun. Çok üzgünüm, sadece açık olanı yaparsam. İlk olarak, bir scala programı, özellikler/sınıflar (ayrıca tekil nesne) ve yöntemlerden oluşur. Yapılan her şey metotlarla yapılır (kurucu ayrılır). Fonksiyonlar (metotların tersine), çeşitli FunctionN özelliklerinin (altta yatan argüman sayısı) (alt tipleri) örnekleridir. Her biri, gerçek uygulama olan uygulama yöntemi olarak sahiptir.

val inc = {i: Int => i + 1} 

o (verilen ile Function1 uzanan anonim sınıf, yöntem ve bir örneğini oluşturarak uygulamak tanımlar)

val inc = new Function1[Int, Int] {def apply(i: Int) = i + 1} 

için şekeri alınmış olup

Yani bir işlev yazma yerine daha vardır sen yazma varsa basit bir yöntemden daha ağır. Ayrıca aşırı yükleme yapamazsınız (aynı adda, imzayla farklılık gösteren, yukarıda yaptığım gibi farklı yöntemler), argümanlar için varsayılan argüman veya varsayılan argüman kullanamazsınız.

Diğer taraftan, işlevler yöntemler değilken, işlevler birinci sınıf değerleridir (bunlar argüman olarak iletilebilir, sonuç olarak döndürülebilir). Gerektiğinde otomatik olarak işlevlere dönüştürülürler, ancak bunu yaparken bazı kenarlar olabilir. Bir yöntem yalnızca bir yöntem olarak adlandırılmak yerine bir işlev değeri olarak kullanılacaksa, bir işlev yazmak daha iyi olabilir.

onun apply yöntemi ile bir işlev f, (çok çalışır) f(x) yerine f.apply(x) ile adlandırılır, çünkü bir çağrı için bir değer (parantez ve 0 ya da daha fazla args ardından değeri) ile skala desugars işlev çağrısı notasyonu yöntem apply. f(x), f.apply(x) için sözdizimsel şekerdir. Bu, f türü ne olursa olsun çalışır, FunctionN'dan biri olması gerekmez.

Loaner ile yapılan, bir nesneyi (anonim bir türden döndürüyor, ancak biri bir sınıfı ayrı olarak tanımlamış ve bir örneğini döndürmüş olabilir) döndürüyor. Nesne, biri Int => String, diğeri () => String kabul eden iki apply yöntemine sahiptir. withLoaner(n)(f)'u yaptığınızda, withLoaner(n).apply(f) anlamına gelir. Uygun uygulama yöntemi, f, bunlardan biri için uygun türde ise, aksi halde, derleme hatası seçilirse seçilir.

(veya durdurmak asla, tıpkı iyi withLoaner.apply.apply(n) anlamına gelebilir o) withLoaner.apply(n) anlamına gelmez withLoaner(n) merak Hemen durumda, withLoaner bir yöntem değil, bir değerdir olarak.

+0

Bu harika görünüyor. Çok hoş. Bu yaptığı işlemle biraz açıklanması ekleyerek sakınca var mı? Ayrıca, bu def f (args) diyorsun = ifade daha yaygın/iyi uygulamadır? emin niçin ... – eptx

+0

Mükemmel didierd. Teşekkür ederim! – eptx