Control Structures and Functions in Scala
- 2.1 Conditional Expressions
- 2.2 Statement Termination
- 2.3 Block Expressions and Assignments
- 2.4 Input and Output
- 2.5 Loops
- 2.6 Advanced for Loops and for Comprehensions
- 2.7 Functions
- 2.8 Default and Named Arguments L1
- 2.9 Variable Arguments L1
- 2.10 Procedures
- 2.11 Lazy Values L1
- 2.12 Exceptions
- Exercises
Topics in This Chapter A1
- 2.1 Conditional Expressions — page 14
- 2.2 Statement Termination — page 15
- 2.3 Block Expressions and Assignments — page 16
- 2.4 Input and Output — page 17
- 2.5 Loops — page 18
- 2.6 Advanced for Loops and for Comprehensions — page 19
- 2.7 Functions — page 20
- 2.8 Default and Named Arguments L1 — page 21
- 2.9 Variable Arguments L1 — page 22
- 2.10 Procedures — page 23
- 2.11 Lazy Values L1 — page 23
- 2.12 Exceptions — page 24
- Exercises — page 26
In this chapter, you will learn how to implement conditions, loops, and functions in Scala. You will encounter a fundamental difference between Scala and other programming languages. In Java or C++, we differentiate between expressions (such as 3 + 4) and statements (for example, an if statement). An expression has a value; a statement carries out an action. In Scala, almost all constructs have values. This feature can make programs more concise and easier to read.
Here are the highlights of this chapter:
- An if expression has a value.
- A block has a value—the value of its last expression.
- The Scala for loop is like an “enhanced” Java for loop.
- Semicolons are (mostly) optional.
- The void type is Unit.
- Avoid using return in a function.
- Beware of missing = in a function definition.
- Exceptions work just like in Java or C++, but you use a “pattern matching” syntax for catch.
- Scala has no checked exceptions.
2.1 Conditional Expressions
Scala has an if/else construct with the same syntax as in Java or C++. However, in Scala, an if/else has a value, namely the value of the expression that follows the if or else. For example,
if (x > 0) 1 else -1
has a value of 1 or -1, depending on the value of x. You can put that value in a variable:
val s = if (x > 0) 1 else -1
This has the same effect as
if (x > 0) s = 1 else s = -1
However, the first form is better because it can be used to initialize a val. In the second form, s needs to be a var.
(As already mentioned, semicolons are mostly optional in Scala—see Section 2.2, “Statement Termination,” on page 15.)
Java and C++ have a ?: operator for this purpose. The expression
x > 0 ? 1 : -1 // Java or C++
is equivalent to the Scala expression if (x > 0) 1 else -1. However, you can’t put statements inside a ?: expression. The Scala if/else combines the if/else and ?: constructs that are separate in Java and C++.
In Scala, every expression has a type. For example, the expression if (x > 0) 1 else -1 has the type Int because both branches have the type Int. The type of a mixed-type expression, such as
if (x > 0) "positive" else -1
is the common supertype of both branches. In this example, one branch is a java.lang.String, and the other an Int. Their common supertype is called Any. (See Section 8.11, “The Scala Inheritance Hierarchy,” on page 94 for details.)
If the else part is omitted, for example in
if (x > 0) 1
then it is possible that the if statement yields no value. However, in Scala, every expression is supposed to have some value. This is finessed by introducing a class Unit that has one value, written as (). The if statement without an else is equivalent to
if (x > 0) 1 else ()
Think of () as a placeholder for “no useful value,” and think of Unit as the analog of void in Java or C++.
(Technically speaking, void has no value whereas Unit has one value that signifies “no value”. If you are so inclined, you can ponder the difference between an empty wallet and a wallet with a bill labeled “no dollars”.)