npi*_*piv 3 scala type-inference filter scala-collections
以下内容无法编译.我需要先安排这个人吗?
object People {
def all = List(
new Person("Jack", 33),
new Person("John", 31) with Authority,
new Person("Jill", 21),
new Person("Mark", 43)
)
}
class Person(val name: String, val age: Int)
trait Authority {
def giveOrder {
println("do your work!")
}
}
object Runner {
def main(args:List[String]) {
val boss = People.all.find { _.isInstanceOf [Authority] }.get
boss.giveOrder // This line doesnt compile
}
}
Run Code Online (Sandbox Code Playgroud)
你是在思考,不管怎么说,应该有一种让你避免施法的机制.这样的演员阵容将是丑陋和多余的,因为它无论如何已经出现在过滤器中.find然而,它根本不关心它得到的谓词的形状; 它只是应用它并返回一个Option[A]if A是集合元素的静态类型.
你需要的是collect功能:
val boss = People.all.collect { case boss: Authority => boss }.head
Run Code Online (Sandbox Code Playgroud)
collect创建一个新的集合.如果你想避免这种情况(如果你真的只对第一个那种元素感兴趣的话Authority),如果有可能很长的潜在老板列表,你可能想要切换到一个view懒惰的评估:
val boss = People.all.view.collect { case boss: Authority => boss }.head
Run Code Online (Sandbox Code Playgroud)
最后,除非你绝对确定列表中总是至少有一个boss,否则你应该真的测试搜索是否成功,例如:
val bossOpt = People.all.view.collect { case boss: Authority => boss }.headOption
bossOpt.foreach(_.giveOrder) // happens only if a boss was found
Run Code Online (Sandbox Code Playgroud)
编辑:最后,如果你正在使用Scala 2.9,你肯定应该collectFirst按照Kevin Wright的回答中的说明使用.
让 - 菲利普的回答很好,但有可能更进一步......
如果使用Scala的2.9,你也有一个collectFirst可行的方法,可以让你避免那些繁琐view的,head年代和headOption的
val boss = People.all.collectFirst { case x: Authority => x }
boss.foreach(_.giveOrder) // happens only if a boss was found
Run Code Online (Sandbox Code Playgroud)
boss仍然是一个Option[Person],我建议你为了更安全的代码保持这种方式.如果你愿意,你也可以使用for-comprehension,有些人仍然更清洁:
for(boss <- People.all.collectFirst { case x: Authority => x }) {
boss.giveOrder // happens only if a boss was found
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
322 次 |
| 最近记录: |