开发者

how to simplify scala's function literal like this?

开发者 https://www.devze.com 2023-02-05 02:43 出处:网络
I\'m new to scala and trying to write a function literal that check whether a given integer is odd or not.

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?


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 )


Only slightly cheating:

val isOdd = (_: Int) % 2 == 1

:-)


There you go:

val isOdd = ((_: Int) & 1) andThen (1 ==)


What Scala is doing is this:

  • it sees ((_:Int) & 1 ) and creates an object of type (Int) => Int, that is, a function.
  • it then applies the comparison operator == to compare this function to the value 1

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


A different approach

val isOdd = (_:Int).&(1) == 1
0

精彩评论

暂无评论...
验证码 换一张
取 消