Scala映射/foreach中的下划线



你能帮我理解下面第二种情况下下划线的作用吗?我猜它为列表中的每个元素定义了一个匿名函数,但为什么没有像第一种情况那样调用该函数呢?

scala> List(1,2,3,4).foreach(x => println("*" * x))
*
**
***
****
scala> List(1,2,3,4).foreach(_ => println("*" * _))
$line25.$read$$iw$$iw$$iw$$iw$$$Lambda$1197/562203102@a632ae0
$line25.$read$$iw$$iw$$iw$$iw$$$Lambda$1197/562203102@a632ae0
$line25.$read$$iw$$iw$$iw$$iw$$$Lambda$1197/562203102@a632ae0
$line25.$read$$iw$$iw$$iw$$iw$$$Lambda$1197/562203102@a632ae0

正确的方法如下

List(1,2,3,4).map("*" * _).foreach(println)

scala中有许多不同的下划线用例。我在这里列出了其中三个与这个问题相关的用例。

情况1:在输入参数中使用下划线

当lambda表达式的主体中不使用输入参数时,可以对lambda表达式中的参数使用下划线,因此可以将下划线用作占位符,而不是为lambda表达式声明输入参数,如下所示。List(1,2,3,4).foreach(_ => println("*" * 10)) // here 10 '*' characters are displayed irrespective of the input value.

情况2:在lambda表达式的正文中使用下划线

当在lambda表达式的正文中使用下划线时,它指的是输入参数。如果输入只被引用一次,则可以用这种方式使用下划线。

例如:List(1,2,3,4).foreach(println("*" * _)) // the underscore will be subsituted with the input argument.

案例3:引用未应用的方法

假设我有一个方法foo(bar: Int)。我可以通过表达式foo _(即foo后面紧跟一个下划线)引用未应用的方法。这里的未应用函数意味着获得对函数对象的引用,该引用可以在以后根据需要执行。

@ def foo(bar: Int) = bar
defined function foo
@ val baz = foo _
baz: Int => Int = $sess.cmd24$$$Lambda$2592/612249759@73fbe2ce
@ baz.apply(10)
res25: Int = 10

不能混合使用情况1和情况2。即您可以在输入参数或lambda函数的主体中使用下划线,但不能同时在两者中使用。由于您混合了这两种情况,您意外地使用了下划线用法的情况3,如下所示。即您指的是通过java.lang.String上的隐式定义的未应用的方法*

@ "*" * _
res20: Int => String = $sess.cmd20$$$Lambda$2581/1546372166@20967474

因此,有效地说,你正在做的事情如下。

List(1,2,3,4).foreach(x => println(("*" * _).toString))

最新更新