Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
699 views
in Technique[技术] by (71.8m points)

functional programming - Underscores in a Scala map/foreach

Can you please help me understand what the underscore is doing in the second case below? I guess it's defining an anonymous function for each element of the list, but why is that function not being called like it is in the first case?

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
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...