以下是正确的方法:
List(1,2,3,4).map("*" * _).foreach(println)
在Scala中,下划线有很多不同的用途。我在此列出了三个与本问题相关的用例。
用例1:在输入参数中使用下划线
当lambda表达式的输入参数在lambda表达式的主体中不会被使用时,您可以将下划线用作占位符,而不是声明lambda表达式的输入参数,如下所示。
List(1,2,3,4).foreach(_ => println("*" * 10)) // 这里显示10个星号字符,而不管输入值如何。
用例2:在lambda表达式的主体中使用下划线。
当在lambda表达式的主体中使用下划线时,它表示输入参数。如果输入仅被引用一次,则可以以这种方式使用下划线。
例如:List(1,2,3,4).foreach(println("*" * _)) // 下划线将被替换为输入参数。
用例3:引用未应用的方法。
假设我有一个方法foo(bar: Int)
。我可以通过表达式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))
"*".* _
,那就是第三种情况。但奇怪的是,这不会编译,而"*".+ _
可以... - Alexey Romanov"*".* _
是第三种情况,就像我在上一行中展示的那样,它被表示为"*"
* _
。 - rogue-one"*" * _
成为情况3,"*" *
必须是一个有效的SimpleExpr1
,但它本身不是(而"*".*
是)。请参见http://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#method-values。 - Alexey Romanov