Scala地图/ foreach中的下划线

时间:2017-10-30 01:03:38

标签: scala functional-programming

您可以帮我理解下面第二种情况下下划线的作用吗?我猜它是为列表中的每个元素定义一个匿名函数,但是为什么在第一种情况下不会调用该函数?

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

1 个答案:

答案 0 :(得分:8)

正确的方法如下

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))