How to create a method that returns a function in Scala

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 9.7, “How to create a method that returns a function in Scala.”

Problem

You want to return a function (algorithm) from another Scala function or method.

Solution

Define a function that returns an algorithm (an anonymous function), assign that to a new function, and then call that new function.

The following code declares an anonymous function that takes a String argument and returns a String:

(s: String) => { prefix + " " + s }

You can return that anonymous function from the body of another function as follows:

def saySomething(prefix: String) = (s: String) => {
    prefix + " " + s
}

Because saySomething returns a function, you can assign that resulting function to a variable. The saySomething function requires a String argument, so give it one as you create the resulting function sayHello:

val sayHello = saySomething("Hello")

The sayHello function is now equivalent to your anonymous function, with the prefix set to hello. Looking back at the anonymous function, you see that it takes a String parameter and returns a String, so you pass it a String:

sayHello("Al")

Here’s what these steps look like in the REPL:

scala> def saySomething(prefix: String) = (s: String) => {
     |   prefix + " " + s
     | }
saySomething: (prefix: String)String => java.lang.String

scala> val sayHello = saySomething("Hello")
sayHello: String => java.lang.String = <function1>

scala> sayHello("Al")
res0: java.lang.String = Hello Al

Discussion

If you’re new to functional programming, it can help to break this down a little. You can break the expression down into its two components. On the left side of the = symbol you have a normal method declaration:

def saySomething(prefix: String)

On the right side of the = is a function literal (also known as an anonymous function):

(s: String) => { prefix + " " + s }

Another example

As you can imagine, you can use this approach any time you want to encapsulate an algorithm inside a function. A bit like a Factory or Strategy pattern, the function your method returns can be based on the input parameter it receives. For example, create a greeting method that returns an appropriate greeting based on the language specified:

def greeting(language: String) = (name: String) => {
    language match {
        case "english" => "Hello, " + name
        case "spanish" => "Buenos dias, " + name
    }
}

If it’s not clear that greeting is returning a function, you can make the code a little more explicit:

def greeting(language: String) = (name: String) => {
    val english = () => "Hello, " + name
    val spanish = () => "Buenos dias, " + name
    language match {
        case "english" => println("returning 'english' function")
                          english()
        case "spanish" => println("returning 'spanish' function")
                          spanish()
    }
}

Here’s what this second method looks like when it’s invoked in the REPL:

scala> val hello = greeting("english")
hello: String => java.lang.String = <function1>

scala> val buenosDias = greeting("spanish")
buenosDias: String => java.lang.String = <function1>

scala> hello("Al")
returning 'english' function
res0: java.lang.String = Hello, Al

scala> buenosDias("Lorenzo")
returning 'spanish' function
res1: java.lang.String = Buenos dias, Lorenzo

You can use this recipe any time you want to encapsulate one or more functions behind a method, and is similar in that effect to the Factory and Strategy patterns.

See Also

The Scala Cookbook

This tutorial is sponsored by the Scala Cookbook, which I wrote for O’Reilly:

You can find the Scala Cookbook at these locations:

Add new comment

The content of this field is kept private and will not be shown publicly.

Anonymous format

  • Allowed HTML tags: <em> <strong> <cite> <code> <ul type> <ol start type> <li> <pre>
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.