I'm starting to learn Scala and I've come across a snippet from the Programming in Scala textbook which I don't quite understand. Was hoping some one could help me?
This is from Listing 9.1 from Programming in Scala, 2nd Edition.
object FileMatcher {
private def filesHere = (new java.io.File(".")).listFiles
}
private def filesMatching(matcher: String => Boolean) =
for (file <- filesHere; if matcher(file.getName)) yield file
def filesEnding(query: String) =
filesMatching(_.endsWith(query)) // ???
def filesContaining(query: String) =
filesMatching(_.contains(query)) // ???
def filesRegex(query: String) =
filesMatching(_.matches(query)) // ???
I'm a little confused with the lines that have // ???
. Does the use of the _
somehow create an anonymous function that is passed to filesMatching
? Or does the _
have nothing to do with this, and instead the compiler sees that filesMatching
requires a function and therefore doesn't execute _.endsWith(query)
as an expression but instead makes the expression a function?
Functions are data, and therefore can be passed around just like other values. This means a function can be passed to another function as an argument. This allows the function being called to use the function argument to carry out its action.
Because functions are objects we can pass them as arguments to other functions. Functions that can accept other functions as arguments are also called higher-order functions. In the example below, a function greet is created which takes a function as an argument.
=> is syntactic sugar for creating instances of functions. Recall that every function in scala is an instance of a class. For example, the type Int => String , is equivalent to the type Function1[Int,String] i.e. a function that takes an argument of type Int and returns a String .
extended definition
Anonymous function are defined, in their more verbose and complete form, as
(a: A, b: B, ...) => function body //using a, b, ...
E.g.
(a: String, b: String) => a ++ b // concatenates 2 Strings
inferred types
if the context provides the needed information (as when a higher order function expects a specific signature for its function arguments), you can omit the parameters' types, as
(a, b, ...) => function body //using a, b, ...
E.g.
val l = List(1, 2, 3)
//you can omit the type because filter on List[Int] expects a (Int => Boolean)
l.filter(i => i < 3)
placeholder syntax
Finally you can use a shorter form still, if your parameters are used once each and in the same order that you declare them, by the function body, as
_ ++ _ // which is equivalent to (a, b) => a ++ b
Each _
is a placeholder for the function's arguments
E.g.
filesMatching
's argument is a function of type String => Boolean
so you can use
_.endsWith(query) // equivalent to (s: String) => s.endsWith(query)
_.contains(query) // equivalent to (s: String) => s.contains(query)
_.matches(query) // equivalent to (s: String) => s.matches(query)
The _
as used here is shorthand for a function argument. Thus filesMatching(_.endsWith(query))
is equivalent to filesMatching(f => f.endsWith(query))
. As filesMatching
has as argument a function of String => Boolean
, the compiler can infer that f
is expected to be a String
here. So you are right that this expression is an anonymous function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With