我熟悉的概念,即Scala的for內涵是對一元的操作只是語法糖(map,withFilter,foreach和flatMap)和脫糖中描述這個流行的答案。
通過這種邏輯,我驚訝地發現,當使用模式匹配作為推導式的賦值部分的一部分時for,MatchError當模式與元素不匹配時會拋出no 。相反,不匹配的元素被過濾掉:
case class Account(id: String, role: String)
val accounts = Set(Account("a", "ADMIN"), Account("b", "USER"), Account("c", "ADMIN"), Account("d", "USER"), Account("e", "USER"))
val adminIds = for (Account(id, "ADMIN") <- accounts) yield id
// Set("a", "c") (no MatchError on Account("b", "USER")!
我原以為這種理解會轉化為這樣的東西:
val adminIds = accounts.map { case Account(id, "ADMIN") => id }
// or maybe
val adminIds = accounts.map { account =>
val Account(id, "ADMIN") = account
id
}
但當然那些會拋出一個MatchError. 相反,它似乎與此更相似:
val adminIds = accounts.collect { case Account(id, "ADMIN") => id }
但是,我從未見過任何提及將for理解脫糖到collect電話中的情況。
那么這是如何在引擎蓋下完成的呢?
uj5u.com熱心網友回復:
添加我的答案,最初是作為評論發布的。
在幕后,你的理解被翻譯成:
val adminIds = accounts.withFilter {
case Account(id: String, "ADMIN") => true;
case _ => false
}.map({
case Account(id: String, "ADMIN") => id
})
換句話說,它使用withFilter.
從鏈接的答案中總結,withFilter在 scala 2.8 中引入并適用于嚴格集合(如List,而不是像那樣的非嚴格集合Stream。)它不是回傳一個新的、過濾的集合,而是按需過濾。
這就是為什么您MatchError在運行代碼時沒有注意到 a 的原因。
uj5u.com熱心網友回復:
如果你把代碼放在像 Intellij 和 desugar 這樣的 IDE 中,你會得到這樣的東西
val adminIds: Set[String] = accounts.withFilter { case Account(id: String, "ADMIN") => true; case _ => false }.map({ case Account(id: String, "ADMIN") => id })
這不是一個電話收集
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/318735.html
