假设l = List(1, 2, 3):
scala> l foreach { println _ }
1
2
3
scala> l foreach { println }
1
2
3
l foreach { println _ } <=> l foreach { println }
因为_
可以省略。但为什么以下也会产生相同的结果呢?
scala> l foreach { println(_) }
1
2
3
不应该将_
限制为println而不是foreach吗?
换句话说:
l foreach { println(_) } <=> l foreach { println(x => x) }
并因此在缺少参数类型时抛出错误?
l foreach { println(_.toString) }
生成预期的缺失参数类型错误
答案 0 :(得分:1)
foreach
采用函数A => Unit
,在本例中为Int => Unit
println
满足这个条件,但它是一个方法,而不是一个函数。 Scala可以通过一种称为eta扩展的技术解决这个问题。它创建了一个函数,该函数接受方法的输入并使用这些输入调用方法。在您的情况下,它看起来类似于(x: Int) => println(x)
。
你写的每一种方式都可以实现这一点。
l foreach { println }
Scala能够推断您希望将println
视为一个函数并将其传递给foreach
l foreach { println _ }
通过添加下划线,您明确表示要将方法转换为函数
l foreach {println(_)}
这与上一个类似,对于您调用的任何方法,您可以使用下划线而不是传递参数。通过执行此操作,您可以创建部分应用的函数,而不是调用该方法。然后,您将此功能传递给foreach
l foreach {println(_。toString)}
这有点不同。 _.toString
创建了一个函数A => String
,但Scala无法确定A的正确类型。另一个问题不是您将值传递给println
,因此您调用println
并且将结果传递给foreach
而不是将其转换为函数。 println
会返回Unit
,这是传递给foreach
答案 1 :(得分:0)
您忘记了println(x)
也可以在Scala中写为println x
。如果只有一个参数,则括号是可选的。
答案 2 :(得分:0)
_不应该将_绑定到println而不是foreach?换句话说:
l foreach { println(_) } <=> l foreach { println(x => x) }
不,匿名函数中的占位符规则明确排除了这一点:
“正确包含”表示_
从不绑定自身,因此它永远不会扩展为x => x
。在上一个示例中,_.toString
正确包含_
,因此满足上述两个条件。