Reputation: 13
I'm trying to learn programming with Scala, and I met some problem about the underscore.Here is the code:
FileMatcher.filesContaining("hello").foreach(println(_))
FileMatcher.filesContaining("hello").foreach(println((_:java.io.File).getName))
My question is, if underscore represent the formal parameter of a function(right?, i have seen some answer about underscore), why the first code runs well, but the second crashed?
=====================================================================
the whole code(sorry for my poor english. "crashed" means compile failed)
object FileMatcher{
private def filesHere = (new java.io.File(".")).listFiles
def filesMatching(query: String, matcher: (String, String) => Boolean) =
for (file <- filesHere if matcher(file.getName, query))
yield file
def filesEnding(query: String) =
filesMatching(query, _.endsWith(_))
def filesContaining(query: String) =
filesMatching(query, _.contains(_))
}
FileMatcher.filesContaining("hello").foreach(println(_))
FileMatcher.filesContaining("hello").foreach(println((_:java.io.File).getName))
Upvotes: 0
Views: 121
Reputation: 67280
val seq: Seq[java.io.File] = Seq(new java.io.File("hello"))
In here:
seq.foreach(println(_))
...the underscore replaces the argument of println
with the argument of an anonymous function (the function that is passed to foreach
). This is equal to
seq.foreach(f => println(f))
In fact you could even shorten this to:
seq.foreach(println)
Whereas in:
seq.foreach(println(_.getName))
...you would pass a function x => x.getName
to println
. This doesn't compile because now you are ignoring that foreach
takes a function of arity 1. You could for example attempt to write:
seq.foreach(f => println(_.getName))
Then still Scala has no idea what the argument type of x => x.getName
is (because there is no context from which it could infer that). So:
seq.foreach(f => println((x: java.io.File) => x.getName))
The output:
<function1>
Ooops. That's not what you wanted. You are printing the string representation of a function (without applying the function). Obviously, you are also not doing anything with f
. So you see, the inner function is one bubble too much.
Correct is:
seq.foreach(f => println(f.getName))
Scala doesn't allow you to shorten this to seq.foreach(println(_.getName))
because there is something in the middle between foreach
and getName
and that is the println
method.
Upvotes: 5