2012-07-11 22 views
15

我很困惑。在TraversableLike,有一個功能flatMap與簽名是選項GenTraversableOnce?

flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): Iterable[B]

不過,我可以使用這種方式

scala> Iterable(1,2,3,4,5).flatMap{i=>if (i%2==0) {None} else {Some(i)}} 
res1: Iterable[Int] = List(1, 3, 5) 

爲什麼這可能嗎? Option如何轉換爲GenTraversableOnce?它似乎不是一個子類...

回答

15

事實上,默認情況下存在從Some [X]到GenTraversableOnce [X]的隱式轉換。這在REPL中測試非常簡單

scala> implicitly[Function[Some[Int],GenTraversableOnce[Int]]] 
res1: Some[Int] => scala.collection.GenTraversableOnce[Int] = <function1> 

scala> implicitly[Some[Int] => GenTraversableOnce[Int]] // alternative syntax 
res2: Some[Int] => scala.collection.GenTraversableOnce[Int] = <function1> 

實際上這是在對象Option中定義的。內部scala包:

object Option { 
    /** An implicit conversion that converts an option to an iterable value 
    */ 
    implicit def option2Iterable[A](xo: Option[A]): Iterable[A] = xo.toList 

    /** An Option factory which creates Some(x) if the argument is not null, 
    * and None if it is null. 
    * 
    * @param x the value 
    * @return Some(value) if value != null, None if value == null 
    */ 
    def apply[A](x: A): Option[A] = if (x == null) None else Some(x) 

    /** An Option factory which returns `None` in a manner consistent with 
    * the collections hierarchy. 
    */ 
    def empty[A] : Option[A] = None 
} 

option2Iterable正是你在找的東西。你也可以看到爲什麼在你的REPL測試中你可以看到GenTraversableOnce的實現是一個列表。

如果你正在尋找這是沒有你做任何事情(如一個你可以使用隱式的REPL見),你必須看看自動導入的隱式轉換:

  • Predef.scala
+1

「這很容易在REPL中測試」[Function [Some [Int],GenTraversableOnce [Int]]] -__-簡單,是的,但是這是一個非常多的方括號被稱爲「簡單」imho。 – 2012-07-11 10:34:04

+2

大答案,由於 – 2012-07-11 10:34:43

+0

丹:階>進口scala.collection.GenTraversableOnce 進口scala.collection.GenTraversableOnce 階>型OptionToTraversableConversion [X] =函數[選項[X],GenTraversableOnce [X]] 定義類型別名OptionToTraversableConversion scala>隱式[OptionToTraversableConversion [Int]] res3:Option [Int] => scala.collection.GenTraversableOnce [Int] = Edmondo1984 2012-07-11 15:15:35

3

它似乎確實隱含轉換爲List

scala> val l:scala.collection.GenTraversableOnce[Int] = Some(3) 
l: scala.collection.GenTraversableOnce[Int] = List(3) 

scala> val l:scala.collection.GenTraversableOnce[Int] = None 
l: scala.collection.GenTraversableOnce[Int] = List() 

個人記錄:scala魔術隱式轉換有時真的讓人困惑。

18

正如你可以在類圖(*)見同伴對象,Option不是GenTraversableOnce一個子類,但有可供Iterable一個隱式轉換,這是一個GenTraversableOnce

enter image description here

(*)是啊,好吧,我被騙了。類圖不可用於Scaladoc,但它們應該是明天! :-)

+0

視覺上很好地說明了發生了什麼!這與埃德蒙多的答案相結合應該被接受(和卡雷爾的更簡單,但也提供了更多的證據) – Aktau 2012-07-12 08:26:30

+0

只在2.10的權利? – Edmondo1984 2012-07-31 09:09:28

+0

@ Edmondo1984當然,但是沒有什麼能夠阻止你爲2.9.2的需求查看2.10的scaladoc。大部分時間都是一樣的。 – 2012-07-31 13:03:10

相關問題