2012-03-18 13 views
8

Niech zadeklarować def i równoważną funkcję jako Val:Metody porównaniu Function and implicits w Scala

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> 

Teraz dlaczego nie to działa?

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

Podczas gdy oba te robią?

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

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

Ponieważ opcja nie jest podtypem GenTraversableOnce, myślę, że to może mieć coś wspólnego z implicits, ale nie mogę dowiedzieć się, co dokładnie jest. Używam Scala 2.9.1.

Odpowiedz

7

Niejawna konwersja powoduje, że działają List(1).flatMap(optional) i List(1).flatMap(optional2(_)).

Twój problem można sprowadzić do niejawna konwersja nie jest zabierana:

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] 

Podczas korzystania podkreślenia, kompilator próbuje wprowadzić funkcję i dostarcza niezbędnych niejawna konwersja. Gdy podasz opcjonalne2, nie ma żadnej niejawnej konwersji, która ma zastosowanie.

+0

tak, ale dlaczego nie można go zastosować w pierwszym przypadku? –

+0

@KimStebel, nie ma niejawnej konwersji dla 'optional2'. W drugim przypadku 'optional2 (_)', kompilator buduje dla ciebie funkcję i próbuje dopasować typ zwracany i wtedy wybiera opcję 'option2Iterable'. – huynhjl

+3

Innymi słowy, nie ma żadnej niejawnej konwersji z 'Funkcja [T, R1] => Funkcja [T, R2]', w której istnieje niejawny 'R1 => R2'. Musisz zbudować nowy obiekt funkcji za pomocą opcji "optional2 (_)", aby mogła wystąpić niejawna konwersja, w tym przypadku 'i => optional2 (i: Iterable [String])'. 'optional2' to jeden obiekt,' optional2 (_) 'jest nowym. –

Powiązane problemy