45

我正在尝试在 Scala 中使用布尔函数的否定,例如:

def someFunction(x: Set, p: Int => Boolean): Boolean = 
    someOtherFunction(x, !p)

但我得到了错误:

 value unary_! is not a member of Int => Boolean

如何引用p的否定?

4

4 回答 4

57

的否定p是一个应用于p其参数并否定结果的函数。

x => !p(x)

如果您希望能够编写!p,或者p && q您可以使用这个库,它会使用各种逻辑运算符返回布尔值的函数。

于 2012-10-01T21:50:31.607 回答
21

p 的最短否定:!p(_)

当您将谓词p作为参数应用到另一个函数时:

  • p 或 p(_) 是 lambda 表达式的缩写:(x) => p(x)
  • !p(_) 是 lambda 表达式的缩写: (x) => !p(x) 并且只有 !p 编译器会丢失。

例如,使用一组整数(在 Scala 工作表上尝试):

  def someOtherFunction (x: Set[Int], p: Int => Boolean):Boolean = x.forall(p)
  def someFunction(x: Set[Int], p: Int => Boolean): Boolean =
    someOtherFunction(x, !p(_))

  val x = Set(1,2,3)
  var p: Int => Boolean = (_ > 0)
  //_ > 0 is an abbreviaton of (x) => x > 0

  someFunction(x, p)        //false
  someOtherFunction(x, p)   //true

  p = _ > 1
  someFunction(x, p)        //false
  someOtherFunction(x, p)   //false

  p = _ > 3
  someFunction(x, p)        //true
  someOtherFunction(x, p)   //false
  println
于 2014-09-23T16:47:05.797 回答
5

另一种不使用匿名函数来解决它的方法是为此任务定义一个具体函数。

def even(x:Int):Boolean = x%2==0
def not(f: Int => Boolean): Int => Boolean = !f(_)
def odd = not(even)
odd(1) // true
odd(2) // false

你也可以定义!你自己

def even: Int => Boolean = _%2==0
implicit def bangy(f: Int => Boolean) = new { def unary_! : Int => Boolean = !f(_) }
def odd = !even
odd(1) // true
odd(2) // false

但这似乎只适用于 Int=>Boolean 类型的函数,而不适用于 (Int)=>Boolean。not(even) 解决方案适用于两者。

于 2012-10-06T06:24:10.267 回答
2

Istador 提出的not函数运行良好,但我认为我们可以通过泛型实现的多态性做得更好!

def not[T](f: T => Boolean): T => Boolean = x => !f(x)

然后我们可以将它用于Int => Boolean类似的功能isEven

def isEven(x: Int): Boolean = x % 2 == 0

val numbers = List(1,2,3,4,5,6,7,8,9,10)

val evens = numbers filter isEven
val odds = numbers filter not(isEven _)

// if you actually wanted both, use partition instead
// val (evens2, odds2) = numbers partition isEven

并将用于这样的String => Boolean功能:

def startsWith(prefix: String)(text: String) = text.startsWith(prefix)

val fruits = List("apple", "banana", "cranberry")

val bFruits = fruits filter startsWith("b")
val notBFruits = fruits filter not(startsWith("b"))

有点做作,但老实说,我不确定为什么not标准库中没有内置多态函数?

顺便说一句,我也在 Coursera 上 Odersky 教授的 Scala 课程!

于 2020-06-11T04:05:44.697 回答