Reputation: 8521
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, !p)
But I get the error:
value unary_! is not a member of Int => Boolean
How can I refer to the negation of p?
Upvotes: 46
Views: 24976
Reputation: 91
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? 🤔
BTW, I'm taking Professor Odersky's Scala class on Coursera, too!
Upvotes: 2
Reputation: 533
Shortest negation of p: !p(_)
When you apply the predicate p as an argument to another function:
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
Upvotes: 23
Reputation: 173
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.
Upvotes: 5
Reputation: 42047
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.
Upvotes: 58