Reputation: 355
I'm new to scala and trying to write a function literal that check whether a given integer is odd or not. my first attempt is:
val isOdd = (x:Int) => (x & 1) == 1
it works great, and, since the parameter x only appears once within this function literal, I'm tempted to use the "_" notation to simplify it further, like this:
val isOdd = ((_:Int) & 1 ) == 1
however this time the compiler complains :
warning: comparing a fresh object using `==' will always yield false val isOdd = ((_:Int) & 1 ) == 1
what does this warning mean? why does the compiler recognize ((_ :Int) & 1)
as fresh object rather than a bitwise operation that results in a value? is there any way to write this function literal using the "_" notation?
Upvotes: 5
Views: 1514
Reputation: 58770
The problem is basically that Scala needs to tell the difference between
val isOdd = ((_:Int) & 1 ) == 1
where you want everything to the right of the equals sign to be a lambda, and
val result = collection.map( _ + 1 )
where you want only the stuff inside the parentheses to be a lambda
Scala has decided that when you use the underscore to create a lambda, that it's going to pick the innermost set of parentheses as the boundaries of that lambda. There's one exception: (_:Int)
doesn't count as the innermost parentheses because its purpose is only to group they type declaration with the _
placeholder.
Hence:
val isOdd = ((_:Int) & 1 ) == 1
^^^^^^^^^^^^^^
this is the lambda
val result = collection.map( _ + 1 )
^^^^^^^
this is the lambda
val result = collection.map(( _ + 1) / 2)
^^^^^^^^
this is the lambda
and the compiler can't infer the type of the _
val result = somemap.map(( _ + 1) / 2 * _)
^^^^^^^^
this is an inner lambda with one parameter
and the compiler can't infer the type of the _
^^^^^^^^^^^^^^^^^
this is an outer lambda with one parameter
This last case lets you do things like
_.map(_ + 1)
and have that get translated into
x => x.map( y=> y + 1 )
Upvotes: 20
Reputation: 20538
Only slightly cheating:
val isOdd = (_: Int) % 2 == 1
:-)
Upvotes: 10
Reputation: 37822
What Scala is doing is this:
((_:Int) & 1 )
and creates an object of type (Int) => Int
, that is, a function.==
to compare this function to the value 1A function is not equal to the value 1. Therefore the result is false
, so your code is equivalent to:
val isOdd = false
What you could do is create another anonymous function that does the == 1
part of your computation. This is ugly:
val isOdd = ((_: Int) & 1)(_: Int) == 1
This is equivalent to the more verbose (and perhaps easier to understand):
val isOdd = (x: Int) => 1 == ((_: Int) & 1)(x)
Upvotes: 2