Scala中的"Hello" foreach (x = x * _.toLong)
和"Hello" foreach (x *= _.toLong)
有什么区别?
不起作用:
scala> var x : Long = 1
x: Long = 1
scala> "Hello" foreach (x = x * _.toLong )
<console>:13: error: missing parameter type for expanded function ((x$1) => x.$times(x$1.toLong))
"Hello" foreach (x = x * _.toLong )
作品:
scala> "Hello" foreach (x *= _.toLong )
scala> xbtebh
res89: Long = 9415087488
最佳答案
这个:
"Hello" foreach (x = x * _.toLong)
实际上由编译器扩展为:
"Hello" foreach (x = x * (x$1 => x$1.toLong))
显然,将
Long
与匿名函数相乘并在其参数上调用toLong()
并没有多大意义。当然,自己编写扩展版本也可以,例如"Hello" foreach (y => x = x * y.toLong)
。在您的第二个表达式
"Hello" foreach (x *= _.toLong )
中,编译器需要完成两个扩展:一个像上一个示例一样扩展下划线,另一个将x *= y
扩展为x = x * y
。显然,第一个发生在第二个之前,因此编译器将(x *= _.toLong)
视为单个表达式,因此它不会扩展为(x *= (x$1 => x$1.toLong))
,而是扩展为x$1 => (x *= x$1.toLong)
。由于需要深入研究Scala规范和编译器内部,因此我无法真正指出这一点,但是现在您已经了解了导致这种行为的原因。我的个人建议是仅在琐碎的情况下使用下划线,例如
List(1, 2, 3).map(_.toLong)
,并在诸如您的情况下始终编写完整功能,例如"Hello" foreach (arg => x = x * arg.toLong)
。另请注意,在Scala中,使用副作用和可变值是一个很大的禁忌。这是代码的改进版本:
val result = "Hello".foldLeft(1: Long)((x, c) => x * c.toLong)