The right way to do this is as below
List(1,2,3,4).map("*" * _).foreach(println)
There are many different use cases for underscore in scala. I am listing three of those use cases that are relevant to this question here.
case 1: using underscore in input argument
You can use underscore for the argument of a lambda expression when the input argument is not going to used in the body of the lambda expression and thus you use the underscore as a placeholder instead of declaring a input argument for the lambda expression as shown below.
List(1,2,3,4).foreach(_ => println("*" * 10)) // here 10 '*' characters are displayed irrespective of the input value.
case 2: using underscore in body of lambda expression.
when underscore is used in body of lambda expression it refers to the input argument. You can use the underscore in this fashion if the input is going to be referred only once.
for eg: List(1,2,3,4).foreach(println("*" * _)) // the underscore will be subsituted with the input argument.
case 3: to refer to unapplied methods.
lets say I have a method foo(bar: Int)
. I can refer to the unapplied method method by expression foo _
(ie foo immediately followed by an underscore).
unapplied function here means getting a reference to a function object which can be executed later on demand.
@ 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
you cannot mix case 1 and case 2. ie you can use the underscore either in input argument or in the body of the lambda function but not in both. since you are mixing both the cases you are unexpectedly using case 3 of underscore usage as shown below. ie you are referring to the unapplied method *
defined via implicits on java.lang.String
.
@ "*" * _
res20: Int => String = $sess.cmd20$$$Lambda$2581/1546372166@20967474
so effectively what you are doing is something like the below.
List(1,2,3,4).foreach(x => println(("*" * _).toString))