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
this post is sponsored by my books: | |||
![]() #1 New Release |
![]() FP Best Seller |
![]() Learn Scala 3 |
![]() Learn FP Fast |