Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala _ Placeholders (How does this code function?)

I am learning Scala (coming from a background of mostly Java). I am trying to wrap my head around the following code:

object Main {
  def main(args : Array[String]) {
    for (file <- filesEnding(".txt"))
      println(file.getName)
  }

  private val filesHere = (new java.io.File(".")).listFiles

  def filesMatching(matcher: String => Boolean) =
    for (file <- filesHere; if matcher(file.getName))
        yield file

  def filesEnding(query: String) = filesMatching(_.endsWith(query))
  /* Other matcher functions */
}

In particular I am confused where Scala gets the value for _ in each of the matcher functions. I can see that filesEnding is called with an argument of .txt. That argument is assigned to query. filesEnding then calls filesMatching with an argument consistent with a String => Boolean function. Finally I can see that file.getName is what eventually replaces the _ placeholder.

What I don't get is how Scala knows to put file.getName in place of _. I am having trouble tracing this code in my head and the eclipse debugger isn't much help in this situation. Can somebody walk me through what is happening in this code?

like image 907
knpwrs Avatar asked Jul 30 '11 01:07

knpwrs


2 Answers

The _ is just a shorthand for making an anonymous function:

_.endsWith(query)

is the same as the anonymous function

fileName => fileName.endsWith(query)

This function is then fed as the argument matcher to filesMatching. Inside that function you can see the call

matcher(file.getName)

This calls the anonymous function with file.getName as the _ argument (which I called fileName in the explicit example).

like image 187
hammar Avatar answered Oct 30 '22 10:10

hammar


If you write _.someMethod(someArguments), this desugars to x => x.someMethod(someArguments), so filesMatching(_.endsWith(query)) desugars to filesMatching(x => x.endsWith(query)).

So filesMatching is called with matcher being the function x => x.endsWith(query), i.e. a function which takes one argument x and calls x.endsWith(query) on that argument.

like image 39
sepp2k Avatar answered Oct 30 '22 10:10

sepp2k