Scala Reassignment To Val Parameterization

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 9.2, “How to use functions as variables (values) in Scala.”

Back to top

Problem

You want to pass a Scala function around like a variable, just like you pass , , and other variables around in an object-oriented programming language.

Back to top

Solution

Use the syntax shown in Recipe 9.1 to define a function literal, and then assign that literal to a variable.

The following Scala code defines a function literal that takes an parameter and returns a value that is twice the amount of the that is passed in:

(i: Int) => { i * 2 }

As mentioned in Recipe 9.1, you can think of the symbol as a transformer. In this case, the function transforms the value to an value that is twice the value of .

You can now assign that function literal to a variable:

val double = (i: Int) => { i * 2 }

The variable is an instance, just like an instance of a , , or other type, but in this case, it’s an instance of a function, known as a function value. You can now invoke just like you’d call a method:

double(2) // 4 double(3) // 6

Beyond just invoking like this, you can also pass it to any method (or function) that takes a function parameter with its signature. For instance, because the method of a sequence is a generic method that takes an input parameter of type and returns a type , you can pass the method into the method of an sequence:

scala> val list = List.range(1, 5) list: List[Int] = List(1, 2, 3, 4) scala> list.map(double) res0: List[Int] = List(2, 4, 6, 8)

Welcome to the world of functional programming.

Back to top

Discussion

You can declare a function literal in at least two different ways. I generally prefer the following approach, which implicitly infers that the following function’s return type is :

val f = (i: Int) => { i % 2 == 0 }

In this case, the Scala compiler is smart enough to look at the body of the function and determine that it returns a value. As a human, it’s also easy to look at the code on the right side of the expression and see that it returns a , so I usually leave the explicit return type off the function declaration.

However, if you prefer to explicitly declare the return type of a function literal, or want to do so because your function is more complex, the following examples show different forms you can use to explicitly declare that your function returns a :

val f: (Int) => Boolean = i => { i % 2 == 0 } val f: Int => Boolean = i => { i % 2 == 0 } val f: Int => Boolean = i => i % 2 == 0 val f: Int => Boolean = _ % 2 == 0

A second example helps demonstrate the difference of these approaches. These functions all take two parameters and return a single value, which is the sum of the two input values:

// implicit approach val add = (x: Int, y: Int) => { x + y } val add = (x: Int, y: Int) => x + y // explicit approach val add: (Int, Int) => Int = (x,y) => { x + y } val add: (Int, Int) => Int = (x,y) => x + y

As shown, the curly braces around the body of the function in these simple examples are optional, but they are required when the function body grows to more than one expression:

val addThenDouble: (Int, Int) => Int = (x,y) => { val a = x + y 2 * a }Back to top

Using a method like an anonymous function

Scala is very flexible, and just like you can define an anonymous function and assign it to a variable, you can also define a method and then pass it around like an instance variable. Again using a modulus example, you can define a method in any of these ways:

def modMethod(i: Int) = i % 2 == 0 def modMethod(i: Int) = { i % 2 == 0 } def modMethod(i: Int): Boolean = i % 2 == 0 def modMethod(i: Int): Boolean = { i % 2 == 0 }

Any of these methods can be passed into collection methods that expect a function that has one parameter and returns a , such as the method of a :

val list = List.range(1, 10) list.filter(modMethod)

Here’s what that looks like in the REPL:

scala> def modMethod(i: Int) = i % 2 == 0 modMethod: (i: Int)Boolean scala> val list = List.range(1, 10) list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9) scala> list.filter(modMethod) res0: List[Int] = List(2, 4, 6, 8)

As noted, this is similar to the process of defining a function literal and assigning it to a variable. The following function works just like the previous method:

val modFunction = (i: Int) => i % 2 == 0 list.filter(modFunction)

At a coding level, the obvious difference is that is a method defined in a class, whereas is a function that’s assigned to a variable. Under the covers, is an instance of the trait, which defines a function that takes one argument. (The scala package defines other similar traits, including , , and so on, up to .)

Back to top

Assigning an existing function/method to a function variable

Continuing our exploration, you can assign an existing method or function to a function variable. For instance, you can create a new function named from the scala.math.cos method using either of these approaches:

scala> val c = scala.math.cos _ c: Double => Double = <function1> scala> val c = scala.math.cos(_) c: Double => Double = <function1>

This is called a partially applied function. It’s partially applied because the method requires one argument, which you have not yet supplied (more on this in Recipe 9.6).

Now that you have , you can use it just like you would have used :

scala> c(0) res0: Double = 1.0

If you’re not familiar with this syntax, this is a place where the REPL can be invaluable. If you attempt to assign the function/method to a variable, the REPL tells you what’s wrong:

scala> val c = scala.math.cos <console>:11: error: missing arguments for method cos in class MathCommon; follow this method with `_' to treat it as a partially applied function val c = scala.math.cos ^

The following example shows how to use this same technique on the scala.math.pow method, which takes two parameters:

scala> val p = scala.math.pow(_, _) pow: (Double, Double) => Double = <function2> scala> p(scala.math.E, 2) res0: Double = 7.3890560989306495

If this seems like an interesting language feature, but you’re wondering where it would be useful, see Recipe 9.6, “Using Partially Applied Functions”, for more information.

Back to top

Summary notes

  • Think of the symbol as a transformer. It transforms the input data on its left side to some new output data, using the algorithm on its right side.
  • Use to define a method, to create a function.
  • When assigning a function to a variable, a function literal is the code on the right side of the expression.
  • A function value is an object, and extends the traits in the main scala package, such as for a function that takes no parameters.
Back to top

See Also

Back to top

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:

Back to top

In the previous part of the Learning Scala series we looked at the different ways by which we can execute Scala code. In doing so we looked at how to print out Hello world in three ways, using the interactive interpreter, executing a script and by compiling and executing a console application. In order to build a console application we took a quick look at the object construct and also at how methods are defined in Scala. In this part we’ll begin to look at classes and constructors in particular.

Declaring and instantiating classes

In the previous post we created a script, hello.scala, which printed “Hello world” to the console when it was run using “scala hello.scala”.

// Inside hello.scala println("Hello world!")

Let’s rewrite that to use a class that does the same thing.

class Greeter { def SayHi() = println("Hello world!") } val greeter = new Greeter() greeter.SayHi()

In the above script we first declare a class named Greeter with a single method, SayHi. We then create a new variable named greeter whose SayHi method we finally invoke.

Considering that we looked at how methods are defined in the previous part there’s not really anything strange or funky in the class definition. The same goes for the instantiation of the class. Just like in C# and Java we create a new instance using the new keyword. We assign it to a variable which we create using the val keyword. That’s something new though. In Scala we create variables either using the val keyword or the var keyword. Using val we get a read-only variable that’s immutable. In other words, once it’s value is assigned it can’t change. If we on the other hand create a variable using the var keyword we get a mutable variable whose value we can later change. In this case an immutable variable is fine, but if we were to reassign the variable later on, like this…

class Greeter { def SayHi() = println("Hello world!") } val greeter = new Greeter() greeter.SayHi() greeter = new Greeter()

…then we’d get a compilation error:

c:\learningscala\Classes and methods>scala helloWithClass.scala
c:\learningscala\Classes and methods\helloWithClass.scala:7: error: reassignment
to val
greeter = new Greeter()
        ^
one error found

If we’d change the greeter variable to instead be a var, like in the snippet below, the code would compile and run just fine.

class Greeter { def SayHi() = println("Hello world!") } var greeter = new Greeter() greeter.SayHi() greeter = new Greeter()

Constructors in Scala

Let’s say that we want to provide the message that the Greeter class writes to the console upon instantiation. Then we’d need a constructor. Constructors are a bit different in Scala than in C# or Java. In Scala the primary constructor is the class’ body and it’s parameter list comes right after the class name. So, to provide the message that Greeter will print using a constructor we can modify our code to look like this:

class Greeter(message: String) { def SayHi() = println(message) } val greeter = new Greeter("Hello world!") greeter.SayHi()

To a C# or Java programmer (or at least to me) it looks like the message variable is a method parameter and it certainly is a parameter to the constructor. But, as proved by the fact that we can use it in the SayHi method, it is also a field in the class. That’s actually not entirely true though. The parameter isn’t a field, but the compiler will automatically create a field for us and take core of setting it’s value. Anyhow, the field is by default a val (immutable) and it’s access is public. That means that the above class definition in Scala is close to functionally equivalent to the below class definition in C#.

public class Greeter { public readonly string message; public Greeter(string message) { this.message = message; } public void SayHi() { Console.WriteLine(message); } }

How strange! But also a bit intriguing right? After all we accomplished what in C# took six lines (not counting lines with just curly braces) in just two lines in Scala. From a Java or C# perspective one might be a bit suspicious of that the message field was made public by default though. We’ll look into why that is, and why it’s sensible that it is that way, later.

As I mentioned before the class’ body is the primary constructor so if we wanted to perform some operations when an instance is created we would write that code directly in the class’ body.

class Greeter(message: String) { println("A greeter is being instantiated") def SayHi() = println(message) } val greeter = new Greeter("Hello world!") greeter.SayHi()

In the above example we added a call to println to print a message when a Greeter is being instantiated. Running this script produces the following output:

A greeter is being instantiated
Hello world!

If we would turn the message field into a var instead of a val we could also modify it when the class is instantiated.

class Greeter(var message: String) { println("A greeter is being instantiated") message = "I was asked to say " + message def SayHi() = println(message) } val greeter = new Greeter("Hello world!") greeter.SayHi()

The above script produces this output:

A greeter is being instantiated
I was asked to say Hello world!

Auxiliary constructors

While the class’ body is the primary constructor we are free to add as many additional auxiliary constructors as we want. There is a constraint for these though. An auxiliary constructor must, on the first line of it’s body, call either another auxiliary constructor that has been declared before before it or the primary constructor. To obey this rule each auxiliary constructor will, either directly or indirectly end up invoking the primary constructor.

Auxiliary constructors are created by defining methods named “this”. To illustrate the use of an auxiliary constructor let’s modify our previous example to include a second message in the primary constructor that the SayHi method will append to the first message when printing it out.

class Greeter(message: String, secondaryMessage: String) { def SayHi() = println(message + secondaryMessage) } val greeter = new Greeter( "Hello world!", " I'm a bit more chatty than my predecessors.") greeter.SayHi()

Running this script produces the following output:

Hello world! I'm a bit more chatty than my predecessors.

Now, suppose we would want to add another constructor that only requires the first message. To do so we add a method named “this” that accepts a single parameter. To satisfy the previously mentioned rules for auxiliary constructors it must call the primary constructor and thereby supply values for each of it’s parameters. In other words, in Scala the primary constructor defines all of the values that is required to create an instance of the class and, in contrast with C# and Java, all other constructors must also supply these values even if they don’t themselves require them as parameters.

Our script modified to include, and use, the auxiliary constructor looks like this:

class Greeter(message: String, secondaryMessage: String) { def this(message: String) = this(message, "") def SayHi() = println(message + secondaryMessage) } val greeter = new Greeter("Hello world!") greeter.SayHi()

Abstract classes

Abstract classes works just like in Java or C# and we declare them using the abstract keyword. To illustrate, let’s modify our previous example so that the Greeter class is abstract, having a concrete implementation of the SayHi method that prints the value of an abstract field. We then create a class, SwedishGreeter, that extends Greeter and defines the message to say “Hej världen!” which means hello world in Swedish.

abstract class Greeter { val message: String def SayHi() = println(message) } class SwedishGreeter extends Greeter{ message = "Hej världen!" } val greeter = new SwedishGreeter() greeter.SayHi()

Recap and a look at the next part

In this post we took a look at how we can declare classes in Scala which is very similar to C# and Java. We also looked at constructors which works a bit differently in Scala than in Java and C#. In the next part we’ll look closer at methods which have some interesting characteristics in Scala.

About this post and the Learning Scala series

This post is a part of a series of posts in which I describe my experiences while trying to learn Scala. I try to do it in the form of a tutorial as I find doing so is an excellent way of consolidating knowledge and hopefully I can also help others. However, keep in mind that I’m in no way an expert on Scala. This is just a way to document what I’ve learned so far and there might be some things that I’ve misunderstood. If you’ve found such a thing and would like to help me correct that misunderstanding, or if you would like to leave any other kind of feedback don’t hesitate to leave a comment!

You can find links to all posts in this series at the bottom of the first post.

PS. For updates about new posts, sites I find useful and the occasional rant you can follow me on Twitter. You are also most welcome to subscribe to the RSS-feed.

Joel Abrahamsson

I'm a passionate web developer and systems architect living in Stockholm, Sweden. I work as CTO for a large media site and enjoy developing with all technologies, especially .NET, Node.js, and ElasticSearch. Read more

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *