我是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)
识别为新对象而不是导致值的按位运算?有没有办法用“_”表示法编写这个函数文字?
答案 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