Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Scala: passing functions as arguments

Tags:

scala

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?

like image 215
C0deAttack Avatar asked Jan 24 '13 15:01

C0deAttack


People also ask

Can you pass a function as an argument?

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.

Why would you pass a function as an argument?

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.

What is the meaning of => in Scala?

=> 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 .


2 Answers

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)
like image 90
pagoda_5b Avatar answered Nov 15 '22 08:11

pagoda_5b


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.

like image 23
Péter Török Avatar answered Nov 15 '22 08:11

Péter Török