I was just reminded that functions are values just like Int
, String
, etc. Beyond the “typical” use cases, this is also true when it comes to supplying a default value for a function parameter that you’re passing into a method.
As some quick background, as I show in the 1st Edition of the Scala Cookbook, you can define a method that provides default values for one or more of its parameters like this:
def makeConnection(timeout: Int = 5000, protocol: String = "http") { // method body here ...
In that example, timeout
is an Int
with a default value of 5000, and protocol
is a String
with a default value of “http”. Both timeout
and protocol
are method parameters.
Supplying a default function for a function parameter
While that’s cool, what’s even cooler is that (a) you can pass a function into a method as a parameter, and (b) you can also supply a default function for the function that’s being passed in. To demonstrate both of these points I’ll share some code I wrote recently.
Source code example
Here’s the source code, but as a quick “heads up”, notice that the defaultFilter
function that I define first is later used as the default value for the method parameter named filterFunction
:
// default function private def defaultFilter(song: Song) = true // a method that takes a Seq and two functions private def generateSongInfoAsCsvString( songs: Seq[Song], transformerFunction:(String) => String, filterFunction:(Song) => Boolean = defaultFilter): String = { val filteredSongs = songs.filter(filterFunction) // the rest of the method body here ...
A few highlights might make that more clear:
You can probably also define the default function inside the method signature, but for me, this approach is a little easier to read.
Discussion
To recap what’s going on there:
- I first define a function named
defaultFilter
, and all it does is returntrue
. This is a “default” behavior I need in the code that follows it. - The
generateSongInfoAsCsvString
method takes aSeq
and two functions as parameters. - The first method parameter is named
songs
, and its type isSeq[Song]
. - The second method parameter declares a function named
transformerFunction
. Its signature says that it must take aString
and return aString
. - The third method parameter is named
filterFunction
, and its signature says it must take a value of typeSong
and return aBoolean
, AND it also says thatdefaultFilter
is the default value for this parameter.
The one line I show in the method body shows why a default value for filterFunction
is needed: I’m going to use the filterFunction
when I call the filter
method on that songs
object. The way this works is that (a) if the caller passes in their own function it gets used inside filter
, otherwise (b) the default function is passed into filter
, with the result being that filteredSongs
is the same as songs
.
Note: I’m only working with a small data set here, so I’m not concerned about what the performance hit might be in using a “do nothing” function like this. (For all I know at the moment, the compiler may optimize that for me.) There are certainly other approaches to this problem, but for the purposes of this article I just want to show how to supply a default value for a parameter that is a function.
Summary
As this example shows, you can define a default value for a function parameter just like you can define a default value for an Int
or String
. That’s both cool, and useful.