A block is a sequence of semi-colon-separated declarations and expressions surrounded by curly braces:
scala> {val x = 10; def square(x: Double)
= x * x; square(x + 3)}
res23: Double = 169.0
The scope of all declarations inside of a block extends to the end of the block. In the example above square and x disappear as soon as the block terminates:
scala>
square(x)
<console>:8: error: not found: value square
square(x)
^
<console>:8: error: not found: value x
square(x)
^
A block is an expression. Its value is the value of its last sub-expression:
scala> {1;
2; 3; 4; 5}
res25: Int = 5
Scala conditional expressions are similar to Java's x?y:z expression:
scala> def max(x: Int, y: Int) = if (x > y) x else y
max: (x: Int, y: Int)Int
scala> max(2, 3)
res26: Int = 3
Scala's match is a powerful
improvement to switch.
Format:
key match {
case guard1 => branch1
case guard2 => branch2
case guard3 => branch3
// etc
case _ => default
}
var day = 3
day match {
case 0 => println("Sunday")
case 1 => println("Monday")
case 2 => println("Tueaday")
case 3 => println("Wednesday")
case 4 => println("Thursday")
case 5 => println("Friday")
case 6 => println("Saturday")
case _ => throw new Exception("Invalid day")
}
day match {
case 0 | 1 => println("Weekend")
case 2 | 3 | 4 | 5 => println("Weekday")
}
var shape:
Shape = new Triangle(20, 10)
shape match {
case shape: Triangle => println(shape.area)
case shape: Rectangle => println(shape.area)
case _
=> throw new Exception("Invalid shape")
}
try { ... }
catch {
case e: NegativeAmountException
=> println("amount must be positive")
case e: InsufficientFundsException
=> println("Insufficient funds")
case e: BadCommandException => println("Invalid command, type help")
case _: Throwable => println("unknown error")
}
income match {
case income if income < 100 => .1 *
income
case income if income < 1000 => .2 *
income
case income if income < 10000 => .3 *
income
case _ => .1 * income
}
We can use a regular expression
to extract matching elements from a string. (More on this later.)
val
expPattern = """([0-9]+)\s*(\+|\*|-|/)\s*([0-9]+)""".r
def eval(exp: String) =
exp match {
case expPattern(arg1, "+", arg2) => arg1.toInt + arg2.toInt
case expPattern(arg1, "-", arg2) => arg1.toInt - arg2.toInt
case expPattern(arg1, "*", arg2) => arg1.toInt * arg2.toInt
case expPattern(arg1, "/", arg2) => arg1.toInt / arg2.toInt
case _
=> throw new Exception("Invalid expression")
}
Scala has the same while and do loops as Java:
while (condition) expression
do expression while (condition)
The for loop is like Java's enhanced for loop:
for(i
<- init to end) expression // while(i <= end) ...
for(i <- init until end)
expression // while(i < end) ...
Here are a few examples:
scala> for
(i <- 0 to 10) println(i)
0
1
2
3
4
5
6
7
8
9
10
scala> for(i <- 0 to 3; j <- 0 to 3) println(i + j)
0
1
2
3
1
2
3
4
2
3
4
5
3
4
5
6
scala> val greeting = "bon jour"
greeting: String = bon jour
scala> for(i <- 0
until greeting.length) println(greeting(i))
b
o
n
j
o
u
r
scala>
for(c <- greeting) println(c)
b
o
n
j
o
u
r
The for loop can have multiple generators and guards:
scala> for(i <- 0 to 15 if i % 3 == 0) println(i)
0
3
6
9
12
15
scala> for(i
<- 0 until 5; j <- 0 until 5 if i != j) { println("" + i + "
+ " + j + " = " + (i + j)); }
0 + 1 = 1
0 + 2 = 2
0 + 3 = 3
0 + 4 = 4
1 + 0 = 1
1 + 2 = 3
1 + 3 = 4
1 + 4 = 5
2 + 0 = 2
2 + 1 = 3
2 + 3 = 5
2 + 4 = 6
3 + 0 = 3
3 + 1 = 4
3 + 2 = 5
3 + 4 = 7
4 + 0 = 4
4 + 1 = 5
4 + 2 = 6
4 + 3 = 7
A comprehension yields a collection:
scala> for(i <- 2 until 10) yield 3 * i +
2
res3: scala.collection.immutable.IndexedSeq[Int] = Vector(8, 11, 14, 17, 20, 23, 26, 29)
Defining and traversing fixed-length arrays:
val
days = Array("Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday",
"Sunday")
for(i <-
0 until days.length)
{
println(days(i))
}
for(day
<- days) {
println(day)
}
val squares = new Array[Int](10)
/
for(i <- 0 until 10) {
squares(i) = i * i
}
Scala functions can throw exceptions just like Java methods. One difference is that the types of exceptions thrown do not need to be declared.
In Scala we use a try/catch/finally block to handle exceptions. One difference with Java is that we can use pattern-driven control in a single catch clause to determine the type of exception caught and how to handle it.
We'll see an example of this in the ATM project that follows.
break
continue
goto
Do we need 'em?
return
most semi-colons
specifying types other than parameter and return types of recursive functions.
empty parentheses when calling a parameterless function
Although break and continue aren't in the Scala, a more general form of break can be imported from the scala library:
import scala.util.control.Breaks._
object TestBreak
{
def main(args:
Array[String]): Unit = {
println("entering main")
breakable {
println("A")
breakable {
println("B")
break
println("C")
}
println("D")
break
println("E")
}
println("exiting main")
}
}
Output:
entering main
A
B
D
exiting main