2012-03-18 46 views
8

讓我們聲明DEF和相同功能的一個VAL:方法對戰功能和implicits在斯卡拉

scala> def optional(x:Int):Option[String] = None 
optional: (x: Int)Option[String] 

scala> val optional2:(Int)=>Option[String] = (i:Int) => None 
optional2: Int => Option[String] = <function1> 

現在爲什麼不工作的呢?

scala> List(1).flatMap(optional2) 
<console>:9: error: type mismatch; 
found : Int => Option[String] 
required: Int => scala.collection.GenTraversableOnce[?] 
       List(1).flatMap(optional2) 
          ^

雖然這兩個呢?

scala> List(1).flatMap(optional) 
res4: List[String] = List() 

scala> List(1).flatMap(optional2(_)) 
res5: List[String] = List() 

由於選項不是GenTraversableOnce的一個亞型,我想這一定有事情做與implicits,但我想不出它到底是什麼。我正在使用Scala 2.9.1。

回答

7

隱式轉換Option.option2Iterable是什麼使List(1).flatMap(optional)List(1).flatMap(optional2(_))工作。

您的問題可以歸結爲沒有被拾起的隱式轉換:

scala> val optional2:(Int)=>Option[String] = (i:Int) => None 
optional2: Int => Option[String] = <function1> 

scala> (optional2(_)): Function[Int, Iterable[String]] 
res0: Int => Iterable[String] = <function1> 

scala> (optional2): Function[Int, Iterable[String]] 
<console>:9: error: type mismatch; 
found : Int => Option[String] 
required: Int => Iterable[String] 

當您使用下劃線,編譯器將嘗試輸入功能,並提供必要的隱式轉換。當您僅提供optional2時,不存在適用的隱式轉換。

+0

是的,但爲什麼它不能應用於第一種情況? – 2012-03-18 19:08:38

+0

@KimStebel,'optional2'沒有隱式轉換。在第二種情況'optional2(_)'中,編譯器爲你構建一個函數,並嘗試匹配返回類型,這是它選擇'option2Iterable'的時候。 – huynhjl 2012-03-18 19:27:52

+3

換句話說,在函數[T,R2] =>函數[T,R2]中沒有隱式轉換,其中隱含的R1 => R2存在。你需要用'optional2(_)'構建一個新的函數對象,這樣隱式轉換就可以發生,在這種情況下'i => optional2(i:Iterable [String])''。 'optional2'是一個對象,'optional2(_)'是一個新對象。 – 2012-03-18 19:42:56