From Get Programming with Scala by Daniela Sfregola

After reading this article, you will be able to:

  • Differentiate between pure and impure functions
  • Provide code examples in which impure functions cause unpredicted code behavior.

Take 37% off Get Programming with Scala by entering fccsfregola into the discount code box at checkout at

In this article, you’ll learn about purity: a fundamental principle of functional programming. In particular, you’ll see that a pure function is total and it has no side effects: you’ll discover what these terms mean in detail. Distinguishing between pure and impure functions can help you identify and prevent bugs in your code. For example, consider the following scenario:

Suppose you are developing the software for a smart thermostat. Your business requirements dictate that your thermostat never reach temperatures below freezing (0°C or 32°F) because it could damage its mechanical parts. If this happens, your program should trigger an emergency recovery plan that changes the target temperature to a default value that the user can configure. You could translate this with the following function:

def monitorTemperature(current: Double, recovery: Double): Double =
  		if (current >= 0) current else recovery

This function monitorTemperature behaves in different ways depending on the “purity” of its parameters. Consider the following function invocations:

scala> monitorTemperature(current = 5, recovery = 10)
res0: Double = 5.0

scala> monitorTemperature(
            current = 5, 
            recovery = {println("EMERGENCY! triggering recovery"); 10})
EMERGENCY! triggering recovery
res1: Double = 5.0

Both function calls are valid, but the second one behaves unpredictably: even when the current temperature is above the freezing threshold, an unexpected (and confusing!) message appears in the console.

Consider this: Can you think of another example in which your function may suffer from some unexpected behavior because of the possibly impure values you have passed as parameters?

A definition of Purity

First, let’s discuss purity and how it differs from impurity. A pure function is total, and it has no side effects. Let’s see what each of these terms mean.


A function is total if it is well-defined for every input: it must terminate for every parameter value and return an instance that matches its return type.

Let’s consider the following functions:

def plus2(n: Int): Int = n + 2				// total

def div(n: Int): Int = 42 / n				// non-total

def rec(n: Int): Int = if (n > 0) n else rec(n - 1) 	// non-total

The function plus2 is total because for every possible integer passed as its parameter, it terminates, and it returns an integer value as the result of its evaluation. The div function is not total because even if it always ends, it doesn’t always return a value of type Int: it throws an ArithmeticException its parameter n equal to zero. A thrown exception is an unexpected value not represented in its return type. Finally, the rec function is not total because it never terminates for any integer less or equal to zero.

Which ones of the following functions are total? Why?

  1. def opsA(n: Int): Int = if(n <= 0) n else n + 1
  2. def opsB(n: Int): Int = if(n <= 0) n else opsB(n + 1)
  3. def selectException(predicate: Boolean): Exception = if (predicate) new IllegalStateException("msg here") else new ArithmeticException("another msg here")
  4. def anotherToString(obj: AnyRef): String = { Thread.sleep(1000) // measured in millis obj.toString }
  5. def validateDistance(dist: Double): Double = if (dist < 0) { throw new IllegalStateException("Distance cannot be negative") } else dist


A side effect is an operation that has an observable interchange with elements outside its local scope: it affects (i.e. write side effect) or is affected by (i.e. read side effect) the state of your application by interacting with the outside world. A few examples are the following:

def negate(predicate: Boolean): Boolean = !predicate	// no side effect

class Counter {
  private var counter = 0

  def incr(): Unit = counter += 1		// (write) side effect
  def get(): Int = counter			// (read) side effect

def hello(name: String): String = {
  val msg = s"Hello $name"
  println(msg)				// (write) side effect

The function negate has no side effects: its only instruction acts on its parameter to produce a return value. The function Counter.incr contains a (write) side effect: every time you invoke the function, it changes the assignment for the variable counter, which is a code element that lives outside of its local scope. Counter.get also has a (read) side effect: given the same input, it returns a different integer depending on the variable counter’s current assignment. The function hello has a (write) side effect because its println instruction produces a message into the console, a component shared across your application that lives independently from its local scope.

Which ones of the following functions have side effects? Why?

1.	def div(a: Int, b: Int): Int = {
  	if (b == 0) throw new Exception("Cannot divide by zero")
 	else a / b
2.	def getUserAge(id: Int): Int = {
  	val user = getUser(id) // gets data for a database
3.	def powerOf2(d: Double): Double = Math.pow(2, d)
4.	def anotherPowerOf2(d: Double): Double = {
  	println(s"Computing 2^$d...")
  	Math.pow(2, d)
5.	def getCurrentTime(): Long = System.currentTimeMillis()

A pure function is total and has no side effects. Consider the code snippets provided in Quick Check 1 and Quick Check 2: which ones of them are pure?

Differentiating between pure and impure functions

In the previous section, you discovered that a function is pure if total, and without side effects. You can describe this concept in a less formal way as follows: a function is pure if nothing else but its parameters determine its behavior, which its return type entirely describes (see figure 1).

Figure 1: A visual representation of the differences between pure and impure functions. Given an input, a pure function returns an output. On the other hand, an impure one also produces additional effects not represented in its return value.

A pure function guarantees that it always returns the same output given the same input parameters. In other words, you can replace its invocation with its return value and obtain the same outcome: This concept is called “referential transparency”, and it has several practical implications.

Suppose you have the following two functions, called pureF and impureF, which take a string as their parameter and return another string as the result of some computation:

  def pureF(name: String): String = s"Hi $name!"

  def impureF(name: String): String = {
    println("...doing something here...")
    s"Hi $name!"

The function pureF is pure, while the function impureF is impure.

You can substitute the function call pureF(“Bob”) with the string “Hi Bob!”. On the other side, swapping the function call impureF(“Bob”) with the string “Hi Bob!” would not produce the same result because the print instruction in the console would be missing.
Functions with no parameters: parentheses or no parentheses?

When declaring a function with no parameters, you should omit the parentheses if the function is pure (i.e., def f = ???). Vice versa, you should specify them if the function is impure (i.e., def f() = ???).

This rule is a style suggestion rather than a law imposed by the compiler.

Which ones of the following statements are true?

  • Pure functions do more than just computing a value
  • You can replace calls to impure functions with their return value without losing functionalities.
  • Pure functions are total
  • A function that throws exceptions is pure
  • A function with side effects is impure
    In this article, my objective was to teach you about the functional concept of purity.
  • You have learned that pure functions are total and have no side effects.
  • You have also discovered referential transparency and how you can use it to differentiate between pure and impure functions.

Let’s see if you got this!

Which ones of the following functions are pure? Which ones are impure?

  1. def welcome(n: String): String = s"Welcome $n!"
  2. def printWelcome(n: String): Unit = println(s"Welcome $n!")
  3. def slowMultiplication(a: Int, b: Int): Int = { Thread.sleep(1000) // 1 second a * b }
  4. def saveUser(user: User): User = { insertUser(user) // inserts in a database user }
  5. def getUser(id: Int): User = { selectUser(id) // searches in a database }

Answers to Quick Checks

The answers are as follows:

  1. The function opsA is total because it always terminates and returns an integer for every integer passed as its parameter.
  2. The function opsB is not total: it calls itself recursively and never terminates for positive integers.
  3. The function selectException is total because it returns an instance of exception: it computes a value that matches its return type for every input. The keyword throw is missing, so the function does not throw the exception, but it returns it as a class instance.
  4. The function anotherToString is total: for every input, it eventually terminates after sleeping for 1 second (or 1000 milliseconds) and returning a string. What if the function was to block for a much more extended period (e.g., ten years), would you still consider it total?
  5. The function validateDistance is not total because it throws an exception for any negative double number.

The answers are the following:

  1. The function div has no side effects: throwing exceptions is not a side effect because it does not change the state of components external to the function.
  2. The function getUserAge returns different results depending on which objects are in the database, which is a (read) side effect.
  3. The function powerOf2 has no side effects as its return value depends entirely on its input.
  4. The function anotherPowerOf2 has a (write) side effects: every time you call it, it produces a new message to the console, changing its state.
  5. The function getCurrentTime returns a value that depends on your machine’s internal clock, which is a (read) side effect.

In Quick Check 1, the functions opsAselectExceptionanotherToString are pure. In Quick Check 2, there is only one pure function, which is powerOf2.

The answers are as follows:

  1. False
  2. False
  3. True
  4. False
  5. True

That’s all for this article. If you want to learn more about the book, you can check it out on Manning’s browser-based liveBook platform here.