提取器可以是减少模式匹配代码重复的一种非常有用的方法,但是,它们中包含的逻辑通常只是一个简单的单行模式,需要从代码中删除,例如,我有一个Person(_, _, Some(Position(_, Some(company))))
的重复模式,所以我提出了这个提取器:
object EmployedAt {
def unapply(x: Person): Option[Company] = x match {
case Person(_, _, Some(Position(_, company))) => company
case _ => None
}
}
我可以这样使用:
val companies = people.collect { case EmployedAt(c) => c }.distinct
def numEmployees(company: Company) =
people.collect { case EmployedAt(`company`) => }.size
people.collect { case p @ EmployedAt(c) if numEmployees(c) >= 2 => (p, c) }
等 - 所有非常好,简洁和可读......除了提取器实现本身。我看到的问题是,最终,提取器只归结为第一个case
语句,其余的只是样板。相反,我认为以下更适合定义简单(可能是一次性或两次性)提取器:
def EmployedAt(x: Person): Company = {
case Person(_, _, Some(Position(_, Some(company)))) => company
}
...这是2条实线而不是4条。
- 我如何继续阅读样板来达到上述简洁的目的?
答案 0 :(得分:4)
我立即开始使用潜在的解决方案,我认为我已经找到了一个非常好的解决方案,除了允许在没有object
+ unapply
+的情况下定义提取器Option[T]
+ case _ => None
样板,也让读者立即明白给定函数是一个提取器,并将其静态标记为Extractor
:
trait Extractor[T, U] { def unapply(x: T): Option[U] }
object Extractor {
def apply[T, U](f: PartialFunction[T, U]) = new Extractor[T, U] {
def unapply(x: T) = f.lift(x)
}
}
val EmployedAt = Extractor[Person, Company] {
case Person(_, _, Some(Position(_, Some(company)))) => company
}
我没有打算立即回答我自己的问题,但结果却是如此。我仍然对可能更有能力的Scala社区成员的批评和其他建议持开放态度! :)