【发布时间】:2015-02-22 15:19:19
【问题描述】:
我被告知要使用这段有趣的代码,但我的用例要求它做的比目前可能的要多。
implicit class Predicate[A](val pred: A => Boolean) {
def apply(x: A) = pred(x)
def &&(that: A => Boolean) = new Predicate[A](x => pred(x) && that(x))
def ||(that: A => Boolean) = new Predicate[A](x => pred(x) || that(x))
def unary_! = new Predicate[A](x => !pred(x))
}
一些用例样板:
type StringFilter = (String) => Boolean
def nameFilter(value: String): StringFilter =
(s: String) => s == value
def lengthFilter(length: Int): StringFilter =
(s: String) => s.length == length
val list = List("Apple", "Orange", "Meat")
val isFruit = nameFilter("Apple") || nameFilter("Orange")
val isShort = lengthFilter(5)
list.filter { (isFruit && isShort) (_) }
到目前为止一切正常。但是说我想做这样的事情:
val nameOption: Option[String]
val lengthOption: Option[Int]
val filters = {
nameOption.map((name) =>
nameFilter(name)
) &&
lengthOption.map((length) =>
lengthFilter(length)
)
}
list.filter { filters (_) }
所以现在我需要&& 和Option[(A) => Boolean] 如果选项为无,那么只需忽略过滤器。
如果我使用类似的东西:
def const(res:Boolean)[A]:A=>Boolean = a => res
implicit def optToFilter[A](optFilter:Option[A => Boolean]):A => Boolean = optFilter match {
case Some(filter) => filter
case None => const(true)[A]
}
我遇到|| 的问题,其中一个过滤器设置为 true。我可以通过将 true 更改为 false 来解决这个问题,但是 && 也存在同样的问题。
我也可以采用这种方法:
implicit def optionalPredicate[A](pred: Option[A => Boolean]): OptionalPredicate[A] = new OptionalPredicate(pred)
class OptionalPredicate[A](val pred: Option[A => Boolean]) {
def apply(x: A) = pred match {
case Some(filter) => filter(x)
case None => trueFilter(x)
}
def &&(that: Option[A => Boolean]) = Some((x: A) =>
pred.getOrElse(trueFilter)(x) && that.getOrElse(trueFilter)(x))
def ||(that: Option[A => Boolean]) = Some((x: A) =>
pred.getOrElse(falseFilter)(x) || that.getOrElse(falseFilter)(x))
}
def trueFilter[A]: A => Boolean = const(res = true)
def falseFilter[A]: A => Boolean = const(res = false)
def const[A](res: Boolean): A => Boolean = a => res
但是当谓词不是选项的子类型时,必须将谓词转换为 OptionalPredicate 似乎本质上是错误的:
implicit def convertSimpleFilter[A](filter: A => Boolean) = Some(filter)
允许:
ifFruit && isShort
我觉得 Optional 应该与 Predicate 无缝结合,同时遵循 DRY 原则。
【问题讨论】:
标签: scala implicit-conversion implicit