How to use / refer to the negation of a boolean function in Scala?

前端 未结 4 1355
梦如初夏
梦如初夏 2020-12-23 21:51

I\'m trying to use the negation of a boolean function in Scala, such as:

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


        
相关标签:
4条回答
  • 2020-12-23 22:02

    Istador's proposed not function works well, but I think we can do even better with polymorphism accomplished through generics!

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

    Then we can use it for Int => Boolean functions like 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
    

    And also use it for a String => Boolean function like this:

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

    A bit contrived, but honestly I'm not sure why that polymorphic not function isn't built into the standard library?

    0 讨论(0)
  • 2020-12-23 22:05

    The negation of p is a function that applies p to its argument and negates the result.

    x => !p(x)
    

    If you want to be able to write !p or p && q you can use this library, which pimps functions that return a bool with various logical operators.

    0 讨论(0)
  • 2020-12-23 22:09

    Shortest negation of p: !p(_)

    When you apply the predicate p as an argument to another function:

    • p or p(_) are abbreviations of the lambda expresion: (x) => p(x)
    • !p(_) is an abbreviation of the lambda expresion: (x) => !p(x) and with only !p the compiler gets lost.

    For example, using a Set of integers (try it on a Scala worksheet):

      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
    
    0 讨论(0)
  • 2020-12-23 22:09

    Another way to solve it without the use of an anonym function is to define a concrete function for this task.

    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
    

    You can also define ! yourself

    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
    

    but this only seems to works for functions of type Int=>Boolean, and not (Int)=>Boolean. The not(even) solution works with both.

    0 讨论(0)
提交回复
热议问题