如何简化scala的函数文字?

时间:2011-01-18 14:53:08

标签: scala function-literal

我是scala的新手,并尝试编写一个函数文字来检查给定的整数是否为奇数。 我的第一次尝试是:

val isOdd = (x:Int) => (x & 1) == 1

它工作得很好,而且,由于参数x只在这个函数文字中出现一次,我很想用“_”表示法进一步简化它,如下所示:

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

然而这次编译器抱怨:

warning: comparing a fresh object using `==' will always yield false
val isOdd = ((_:Int) & 1 ) == 1

这个警告意味着什么?为什么编译器将((_ :Int) & 1)识别为新对象而不是导致值的按位运算?有没有办法用“_”表示法编写这个函数文字?

5 个答案:

答案 0 :(得分:20)

问题基本上是Scala需要区分

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

你希望等号右边的所有内容都是lambda,并且

val result = collection.map( _ + 1 )

你只希望括号内的东西是lambda

Scala已经决定,当你使用下划线创建一个lambda时,它会选择最里面的一组括号作为lambda的边界。有一个例外:(_:Int)不算作最里面的括号,因为它的目的只是将它们的类型声明分组到_占位符。

因此:

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

最后一种情况可以让你做

之类的事情
_.map(_ + 1)

并将其翻译成

x => x.map( y=> y + 1 )

答案 1 :(得分:10)

只是轻微作弊:

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

: - )

答案 2 :(得分:7)

你去了:

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

答案 3 :(得分:2)

Scala正在做的是:

  • 它会看到((_:Int) & 1 )并创建一个(Int) => Int类型的对象,即一个函数。
  • 然后应用比较运算符==将此函数与值1
  • 进行比较

函数不等于值1.因此结果为false,因此您的代码等效于:

val isOdd = false

您可以做的是创建另一个执行计算== 1部分的匿名函数。这太丑了:

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

这相当于更详细(也许更容易理解):

val isOdd = (x: Int) => 1 == ((_: Int) & 1)(x)

答案 4 :(得分:1)

一种不同的方法

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