How to define a default value for a method parameter that is a function

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 return true. This is a “default” behavior I need in the code that follows it.
  • The generateSongInfoAsCsvString method takes a Seq and two functions as parameters.
  • The first method parameter is named songs, and its type is Seq[Song].
  • The second method parameter declares a function named transformerFunction. Its signature says that it must take a String and return a String.
  • The third method parameter is named filterFunction, and its signature says it must take a value of type Song and return a Boolean, AND it also says that defaultFilter 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.