Scala-可选谓词 [英] Scala - Optional Predicate

查看:107
本文介绍了Scala-可选谓词的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我被告知要使用这段有趣的代码,但是我的用例要求它做的工作比当前更多.

I was informed to use this interesting piece of code, but my use case requires it to do a bit more than is currently possible.

  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) (_) }

到目前为止,一切正常.但是说我想做这样的事情:

So far everything works ok. But say that I want to do something like this:

  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]如果Option为None,则只需忽略过滤器.

So now I need to && an Option[(A) => Boolean] If the Option is None then simply disregard the filter.

如果我使用类似的东西:

If I use something like:

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来解决此问题,但是&&存在相同的问题.

I have the problem of || with one filter set to true. I can solve this by changing true to false but then the same problem exists with &&.

我也可以采用这种方法:

I could also take this approach:

  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

但是当谓词不是Option的子类型时,必须将谓词转换为OptionalPredicate似乎是天生的错误:

But something seems inherently wrong with having to convert the Predicate into an OptionalPredicate when the predicate is not the child type of an Option:

  implicit def convertSimpleFilter[A](filter: A => Boolean) = Some(filter)

允许:

ifFruit && isShort

我觉得Optional在遵循DRY原则的同时应该与谓词无缝结合.

I have the feeling that the Optional should tie in seamlessly with Predicate while following DRY principles.

推荐答案

请参见下文(UPD)

能够将Option[Filter]转换为Filter会很好:

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]
}

然后,我们想使用可以转换为谓词的任何类型:

Then we would like to use any type that can be converted to a predicate:

implicit class Predicate[A, P <% A=>Boolean](val pred: P)

(并将pred的用法更改为(pred:A=>Boolean))

def &&[P2:A=>Boolean](that: P2) = new Predicate[A](x => (pred:A=>Boolean)(x) && (that:A=>Boolean)(x))

UPD

Option[A=>Boolean]是实际的过滤器类型.

Option[A=>Boolean] will be the real filter type.

implicit def convertSimpleFilter[A](filter:A=>Boolean)=Some(filter)

implicit class Predicate[A](val pred: Option[A=>Boolean]){
  def &&(that:Option[A=>Boolean]) = Some((x:A) => pred.getOrElse(const(true))(x) && that.getOrElse(const(true))(x) )
  def ||(that:Option[A=>Boolean]) = Some((x:A) => pred.getOrElse(const(false))(x) || that.getOrElse(const(false))(x) )
}

这篇关于Scala-可选谓词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆