Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala-可选谓词_Scala_Implicit Conversion_Implicit - Fatal编程技术网

Scala-可选谓词

Scala-可选谓词,scala,implicit-conversion,implicit,Scala,Implicit Conversion,Implicit,我被告知要使用这段有趣的代码,但我的用例要求它做比目前可能做的更多的事情 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 => B

我被告知要使用这段有趣的代码,但我的用例要求它做比目前可能做的更多的事情

  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 (_) }
因此,现在我需要
&&
一个
选项[(A)=>布尔]
如果该选项为None,那么只需忽略过滤器即可

如果我使用类似于:

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
我觉得可选项应该与谓词无缝地结合,同时遵循干式原则。

请参见下文(UPD)

最好能够将
选项[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]
}
然后,我们希望使用任何可以转换为谓词的类型:

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

选项[A=>Boolean]
将是真正的过滤器类型

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

如果OP希望完全忽略空筛选器,则空筛选器的计算结果不应总是
true
。否则,当存在空筛选器时,
|
将始终为真。我不知道您可以执行
&&&[P2:A=>Boolean](即:P2)
谢谢!上面m-z所说的是正确的,同样适用于
false
&
。好吧,看来过滤器的基础应该是
选项[A=>Boolean]
。简单的过滤器应该可以转换为它,方法
&&
|
应该考虑过滤器可以省略。“
&&&
|
应该考虑过滤器可以省略。”没错。更新不错。我试图将
(A)=>Boolean
作为过滤器类型,并将
选项[(A)=>Boolean
]转换为它。有没有办法做到这一点?另外,我想要避免的是真实和错误,我更愿意删除过滤器和操作符。
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) )
}