Statements vs expressions
- statements are used for side-effects
- expressions always yield a result
“Statements do not return results and are executed solely for their side effects, while expressions always return a result and often do not have side effects at all.”
- All Scala control structures can be used as expressions (except
println("hi") if a == b then println("equal")
if/then is an expression:
val min = if a < b then a else b def min(a: Int, b: Int): Int = if a < b then a else b
match is an expression:
val evenOrOdd = i match case 1 | 3 | 5 | 7 | 9 => "odd" case 2 | 4 | 6 | 8 | 10 => "even" case _ => "other"
for is an expression:
val xs = List(1, 2, 3) val ys = for x <- xs yield x * 2
try/catch is an expression:
def makeInt(s: String): Int = try s.toInt catch case e: Exception => 0
Expressions can be used as the body of functions
Because all of these can be used as expressions, they can also be used as the body of a function, and you’ll see this all the time:
def makeInt(s: String): Option[Int] = try Some(s.toInt) catch case _: NumberFormatException => None def isTrue(a: Matchable): Boolean = a match case 0 | "" | "0" | false => false case _ => true def min(a: Int, b: Int): Int = if a < b then a else b
Because expressions always return a result and generally don’t have side effects, there are several benefits to EOP:
- The code is easier to write, read, and test. Inputs go into a pure function, a result is returned, it’s assigned to an immutable variable, and there are no side effects.
- Pure functions are easier to test. You don’t have to set up some mutable global state to test them.
- Combined with Scala’s syntax, EOP results in concise, expressive code.
- Although it’s only been hinted at in these examples, expressions can often be executed in any order. This subtle feature lets you execute expressions in parallel, which is a huge bonus when you’re trying to take advantage of multicore CPUs.