2016-02-26 20 views
0

這不起作用:flatmap(GenTraversableOnce)上的選項

val res = myOption flatMap (value => Seq(value, 「blo」)) 

但這是:

val res = myOption.toSeq flatMap (value => Seq(value, 「blo」)) 

你不覺得flatMapOption S的關係採取GenTraversableOnce就像Seq不?
或者此代碼對於可讀性不好,我應該使用matchmap/getOrElse

編輯:我們也在for/yield上得到同樣的問題。

乾杯

回答

3

Option.flatMap返回Option,這是「喜歡」的序列,但不能包含多於一個的元件。如果它被允許執行一個函數,返回一個Seq,並返回一個包含多個元素的Seq,那麼返回值flatMap(記住,它需要是Option)是什麼?

爲什麼flatMap需要首先返回一個選項?那麼,全部flatMap實現返回他們開始使用相同的類型。它是有道理的:如果我有一個Option的東西,並且想要以某種方式轉換內容,最常見的用例是我想結束另一個Option。如果flatMap給我回Seq,我會嗎? .headOption?這不是一個好主意,因爲它可能會默默丟棄數據。 if(seq.size < 2) seq.headOption else throw ....?那麼,這有點更好,但看起來很醜,並且在編譯時不可執行。

另一方面,將Option轉換爲Seq非常簡單且完全安全:只需要做.toSeq即可。

+0

」記住它需要一個選項「爲什麼?爲什麼我可以執行'Seq()。flatMap(Option())'而不是相反呢?如果它採用了GenTraversableOnce,它將處理所有收藏,包括選項 – Joan

+0

@Joan我將您的評論回覆給我的答案 – Dima

+0

非常好的答案感謝@迪瑪。我現在得到了問題的所有方面。 – Joan

3

總體語義的flatMap就像monadic bind方法,這意味着它往往有簽名像

[A]this:T[A].flatMap[B](f: A => T[B]): T[B] 

有時(SeqLike)這個簽名推廣到

[A]this:T[A].flatMap[B](f: A => F[B]): T[B] 

其中F[B]是什麼工作很容易兌換成T[B]

所以不僅Option,還有concurrent.Future,util.TryBindOps - scalaz monads的擴展語法有方法flatMap,它不接受任何可穿越的,但只有相同的包裝類型。

I.e. 「flatMap從monads世界更多的東西,而不是從集合