Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to simplify scala's function literal like this?

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?

like image 364
hind_d Avatar asked Jan 18 '11 14:01

hind_d


1 Answers

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 )
like image 64
Ken Bloom Avatar answered Oct 01 '22 08:10

Ken Bloom