5

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

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

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

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

但是这次编译器抱怨:

警告:使用 `==' 比较新对象将始终产生错误
val isOdd = ((_:Int) & 1 ) == 1

这个警告是什么意思?为什么编译器将其识别((_ :Int) & 1)为新对象而不是产生值的按位运算?有没有办法使用“_”符号来编写这个函数文字?

4

5 回答 5

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 )
于 2011-01-18T15:14:34.247 回答
10

只是轻微作弊:

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

:-)

于 2011-01-18T20:30:07.860 回答
7

你去:

val isOdd = ((_: Int) & 1) andThen (1 ==)
于 2011-01-18T16:36:01.220 回答
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)
于 2011-01-18T15:02:30.070 回答
1

不同的方法

val isOdd = (_:Int).&(1) == 1
于 2012-01-06T18:47:23.370 回答