Built-in Control Structures

1 For expression

val filesHere = (new java.io.File(".")).listFiles
for (file <- filesHere)
    println(file)

With the file <- filesHere syntax, which is called a generator. we iterate through the elements of filesHere.

// 结果是 1 2 3 4
for (i <- 1 to 4)
    println("Iteration " + i)
// 结果是 1 2 3
for (i <- 1 until 4)
    println("Iteration " + i)

1.1 Filtering

val filesHere = (new java.io.File(".")).listFiles
for (file <- filesHere if file.getName.endsWith(".scala"))
    println(file)
for (
    file <- filesHere
    if file.isFile
    if file.getName.endsWith(".scala")
) println(file)

1.2 Nested iteration

If you add multiple <- clauses, you will get nested "loops".

def fileLines(file: java.io.File) =
    scala.io.Source.fromFile(file).getLines().toList

def grep(pattern: String) =
    for (
        file <- filesHere
        if file.getName.endsWith(".scala");
        line <- fileLines(file)
        if line.trim.matches(pattern)
    ) println(file + ": " + line.trim)
grep(".*gcd.*")

1.3 Mid-stream variable bindings

def grep(pattern: String) =
    for (
        file <- filesHere
        if file.getName.endsWith(".scala");
        line <- fileLines(file)
        trimmed = line.trim
        if trimmed.matches(pattern)
    ) println(file + ": " + trimmed)
grep(".*gcd.*")

1.4 Producing a new collection

def scalaFiles = 
    for {
        file <- filesHere
        if file.getName.endsWith(".scala")
    } yield file

Transforming an Array[File] to Array[Int] with a for:

val forLineLengths = 
    for {
        file <- filesHere
        if file.getName.endsWith(".scala")
        line <- fileLines(file)
        trimmed = line.trim
        if trimmed.matches(".*for.*")
    } yield trimmed.length

2 Exception Handling with Try Expressions

var half = 
    if (n % 2 == 0)
        n / 2
    else
        throw new RuntimeException("n must be even")

2.1 Catching exceptions

import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException

try {
    val f = new FileReader("input.txt")
    // Use and close file
} catch {
    case ex: FileNotFoundException => // Handle missing file
    case ex: IOException => // Handle other I/O error
}

Note:

One different you'll quickly notice in Scala is that, unlike Java, Scala does not require you to catch checked exceptions or declare them in a throws clause. You can declare a throws if you wish with the @throwsannotation, but it is not required.

2.2 The finally clause

import java.io.FileReader

val file = new FileReader("input.txt")
try {
    // Use the file
} finally {
    file.close() // Be sure to close the file
}

3 Match Expressions

val firstArg = if (args.length > 0) args(0) else ""

firstArg match {
    case "salt" => pritnln("pepper")
    case "chips" => println("salsa")
    case _ => println("huh?")
}

4 Living Without break and continue

You may have noticed that there has been no mention of break or continue. Scala leaves out these commands because they do not mesh well with function literals.

If you still feel the need to use break, there's help in Scala's standard library:

import scala.util.control.Breaks._
val in = new BufferedReader(new InputStreamReader(System.in))

breakble {
    while (true) {
        println("? ")
        if (in.readLine() == "") break
    }
}

5 Variable Scope

val a = 1;
{
    val a = 2; // Compiles just fine
    println(a)
}
println(a)

results matching ""

    No results matching ""