2012-03-08 60 views
2

當我看着Scala庫時,我看到了這樣的代碼。爲什麼把測試[A]爲什麼在函數旁邊放置一個泛型?

def test[A](block : Int => Unit) : Unit = { 
     block(10) 
    }  

    test { u => 

     println(u)   
    } 

這和我想的一樣有效。它以同樣的方式運行。

def test(block : Int => Unit) : Unit = { 
      block(10) 
     } 

我剛剛好奇它背後的推理(或設計模式)是什麼。謝謝。

+1

你能否提供一個來自Scala庫的特定示例?這不是我通常看到的。 (我想不出一個例子。) – 2012-03-08 15:03:02

+2

這可能是相關的:http://stackoverflow.com/questions/7933786 – 2012-03-08 15:04:55

+0

謝謝!這似乎解釋了它。 這裏是我看到它的代碼。 https://github.com/playframework/Play20/blob/master/framework/src/play/src/main/scala/play/api/db/DB.scala 具體是withConnection函數。雖然我的例子在這種情況下沒有意義,因爲我提供了Unit類型作爲塊的返回碼。 – 2012-03-08 15:18:26

回答

7

類型參數A在這裏沒有意義,因爲它沒有被使用。

def test[A](block: Int => A): A = block(10) 

這裏A指定返回類型。

+0

但是函數名稱旁邊的A如何使用?我看到它是如何用作返回塊簽名的。 – 2012-03-09 13:19:07

+0

@DrewH:你的意思是「如何使用函數名稱旁邊的A」? A由編譯器在您調用它時推斷出來。 'test {i => new Test(i)}'將用給定的i創建一個Test實例。編譯器推斷測試爲A的類型。 – sschaef 2012-03-09 15:51:38

1

當函數旁邊有泛型類型時,表示該函數是泛型函數。

下面是一個很簡單的例子:

// generic functions which returns type of `A` 
def test1[A](x: A) = x 
def test2[A](x: => A) = { println("Hello"); x } 

val x1 = test1(1) 
// x1: Int = 1 

val x2 = test1("Hello World") 
// x2: java.lang.String = Hello World 

val x3 = test2(123.4) 
// Hello 
// x3: Double = 123.4 

val x4 = test2("Test2") 
// Hello 
// x4: java.lang.String = Test2 

正如你所看到的,test1test2返回類型是通過它們的參數的類型決定。

以下是另一個用例。

// We could implement `map` function ourself. 
// We don't care about what type of List contains, 
// so we make it a generic function. 
def map[A, B](xs: List[A], f: A => B): List[B] = { 
    var result: List[B] = Nil 
    for (i <- xs) { 
     result ++= List(f(i)) 
    } 
    result 
} 

// Now use can map any type of List to another List. 
map(List("1", "2", "3"), (x: String) => x.toInt) 
//res1: List[Int] = List(1, 2, 3)