2012-03-18 30 views
8

Hãy khai báo một def và một chức năng tương đương như một val:Phương pháp so Chức năng và implicits trong 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> 

Bây giờ tại sao không làm việc này?

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

Trong khi cả hai việc này đều có hiệu lực?

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

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

Từ Lựa chọn không phải là một subtype của GenTraversableOnce, tôi nghĩ rằng điều này phải có cái gì để làm với implicits, nhưng tôi không thể tìm ra chính xác những gì nó được. Tôi đang sử dụng Scala 2.9.1.

Trả lời

7

Chuyển đổi ẩn Option.option2Iterable là những gì làm cho công việc List(1).flatMap(optional)List(1).flatMap(optional2(_)) hoạt động.

vấn đề của bạn có thể được luộc xuống chuyển đổi ngầm không được nhặt:

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] 

Khi bạn sử dụng dấu gạch dưới, trình biên dịch cố gắng gõ chức năng và cung cấp chuyển đổi ngầm cần thiết. Khi bạn chỉ cung cấp tùy chọn2, không có chuyển đổi tiềm ẩn nào được áp dụng.

+0

vâng, nhưng tại sao nó không thể được áp dụng trong trường hợp đầu tiên? –

+0

@KimStebel, không có chuyển đổi ngầm cho 'optional2'. Trong trường hợp thứ hai 'optional2 (_)', trình biên dịch xây dựng một hàm cho bạn và cố gắng khớp với kiểu trả về và đó là khi nó chọn 'option2Iterable'. – huynhjl

+3

Nói cách khác, không có chuyển đổi ngầm từ 'Hàm [T, R1] => Hàm [T, R2]' tồn tại trong đó 'R1 => R2' tồn tại. Bạn cần xây dựng một đối tượng hàm mới với 'optional2 (_)' để chuyển đổi ngầm có thể xảy ra, trong trường hợp này 'i => optional2 (i: Iterable [String])'. 'optional2' là một đối tượng,' optional2 (_) 'là một đối tượng mới. –

Các vấn đề liên quan