2010-01-14 17 views
12

Bir işlev olarak kullanmak için bir yöntem sonra _ gereken zaman kuralları hakkında biraz titrek. Örneğin, neden Foo ve Nil'un :: arasında bir fark var? Eğer kısmen uygulanan fonksiyon ifadede tüm parametreleri atlarsanızNeden ve ne zaman bir yöntem ismini takip etmem gerekiyor?

def square(n: Int) = n * n 
object Foo { def ::(f: Int => Int) = f(42) } 

// ... 

scala> Foo.::(square) 
res2: Int = 1764 

scala> Nil.::(square) 
<console>:6: error: missing arguments for method square in object $iw; 
follow this method with `_' if you want to treat it as a partially applied function 
    Nil.::(square) 
     ^
scala> Nil.::(square _) 
res3: List[(Int) => Int] = List(<function1>) 

cevap

15

, o zaman sürece derleyici Kullanmaya yerde bir işlev türü gerektirir _ ile takip etmek gerekir.

Foo üzerinde :: yöntemini çağırdığınızda, derleyici, parametre için Int => Int türünü bekler. Böylece, bu pozisyonda square'dan sonra alt çizgiyi güvenle atlayabilirsiniz.

Ancak Nil ile :: yöntem herhangi tipi bir parametre sunar. Bu nedenle, işlevi kısmen uygulamak istediğinizi varsaymak yerine, _ ekleyerek kesinlikle açık bir şekilde yapmadığınız sürece şikayetçi olur.

Kurallar bunlar ... neden bunlar hakkında aydınlatıcı olamam; belki de derleyiciyi, tip sistemini ve dil tasarımını daha iyi bilen biri size nedenini anlatabilir. Ancak, bu kurallar olmadan, pek çok yerde tesadüfi bir belirsizlik tehlikesi olacağını varsayıyorum.

+2

Teşekkürler. Scala 2.0 için "nota" ile ilgili bazı gerekçeler sunan Scala Language Spec'un bir parçasını bulduk: "Yöntemlerin işlevlerin örtük dönüştürülmesi kuralları (§6.25)). Daha önce kullanılan parametreli bir yöntem kullanıldı. bir değer olarak her zaman dolaylı olarak bir işleve dönüştürüldü. Bu, unutulduğu yöntem argümanları olduğunda beklenmedik sonuçlara yol açabilir. Örneğin aşağıdaki ifadeyi düşünün: (x.toString) ... " –