Code Examples for

Programming in Scala, Second Edition

Return to chapter index

7 Built-in Control Structures

Sample run of chapter's interpreter examples

7.1 If expressions


// In file expressions-and-control-flow/Misc.scala var filename = "default.txt" if (!args.isEmpty) filename = args(0)
// In file expressions-and-control-flow/Misc.scala val filename = if (!args.isEmpty) args(0) else "default.txt"
// In file expressions-and-control-flow/Misc.scala println(if (!args.isEmpty) args(0) else "default.txt")

7.2 While loops


// In file expressions-and-control-flow/Misc.scala def gcdLoop(x: Long, y: Long): Long = { var a = x var b = y while (a != 0) { val temp = a a = b % a b = temp } b }
// In file expressions-and-control-flow/Misc.scala var line = "" do { line = readLine() println("Read: "+ line) } while (line != "")
scala> def greet() { println("hi") } greet: ()Unit scala> greet() == () hi res0: Boolean = true
var line = "" while ((line = readLine()) != "") // This doesn't work! println("Read: "+ line)
// In file expressions-and-control-flow/Misc.scala def gcd(x: Long, y: Long): Long = if (y == 0) x else gcd(y, x % y)

7.3 For expressions


// In file expressions-and-control-flow/Files.scala val filesHere = (new java.io.File(".")).listFiles for (file <- filesHere) println(file)
scala> for (i <- 1 to 4) | println("Iteration "+ i) Iteration 1 Iteration 2 Iteration 3 Iteration 4
scala> for (i <- 1 until 4) | println("Iteration "+ i) Iteration 1 Iteration 2 Iteration 3
// In file expressions-and-control-flow/Files.scala // Not common in Scala... for (i <- 0 to filesHere.length - 1) println(filesHere(i))
// In file expressions-and-control-flow/Files.scala val filesHere = (new java.io.File(".")).listFiles for (file <- filesHere if file.getName.endsWith(".scala")) println(file)
// In file expressions-and-control-flow/Files.scala for (file <- filesHere) if (file.getName.endsWith(".scala")) println(file)
// In file expressions-and-control-flow/Files.scala for ( file <- filesHere if file.isFile if file.getName.endsWith(".scala") ) println(file)
// In file expressions-and-control-flow/Files.scala 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.*")
// In file expressions-and-control-flow/Files.scala 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.*")
// In file expressions-and-control-flow/Files.scala def scalaFiles = for { file <- filesHere if file.getName.endsWith(".scala") } yield file
for clauses yield body
for (file <- filesHere if file.getName.endsWith(".scala")) { yield file // Syntax error! }
// In file expressions-and-control-flow/Files.scala val forLineLengths = for { file <- filesHere if file.getName.endsWith(".scala") line <- fileLines(file) trimmed = line.trim if trimmed.matches(".*for.*") } yield trimmed.length

7.4 Exception handling with try expressions


// In file expressions-and-control-flow/Exceptions.scala throw new IllegalArgumentException
// In file expressions-and-control-flow/Exceptions.scala val half = if (n % 2 == 0) n / 2 else throw new RuntimeException("n must be even")
// In file expressions-and-control-flow/Exceptions.scala 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 }
// In file expressions-and-control-flow/Exceptions.scala import java.io.FileReader val file = new FileReader("input.txt") try { // Use the file } finally { file.close() // Be sure to close the file }
// In file expressions-and-control-flow/Exceptions.scala import java.net.URL import java.net.MalformedURLException def urlFor(path: String) = try { new URL(path) } catch { case e: MalformedURLException => new URL("http://www.scala-lang.org") }
// In file expressions-and-control-flow/Exceptions.scala def f(): Int = try { return 1 } finally { return 2 }
// In file expressions-and-control-flow/Exceptions.scala def g(): Int = try { 1 } finally { 2 }

7.5 Match expressions


// In file expressions-and-control-flow/Match.scala val firstArg = if (args.length > 0) args(0) else "" firstArg match { case "salt" => println("pepper") case "chips" => println("salsa") case "eggs" => println("bacon") case _ => println("huh?") }
// In file expressions-and-control-flow/Match.scala val firstArg = if (!args.isEmpty) args(0) else "" val friend = firstArg match { case "salt" => "pepper" case "chips" => "salsa" case "eggs" => "bacon" case _ => "huh?" } println(friend)

7.6 Living without break and continue


// In file expressions-and-control-flow/Break.java int i = 0; // This is Java boolean foundIt = false; while (i < args.length) { if (args[i].startsWith("-")) { i = i + 1; continue; } if (args[i].endsWith(".scala")) { foundIt = true; break; } i = i + 1; }
// In file expressions-and-control-flow/Breakless1.scala var i = 0 var foundIt = false while (i < args.length && !foundIt) { if (!args(i).startsWith("-")) { if (args(i).endsWith(".scala")) foundIt = true } i = i + 1 }
// In file expressions-and-control-flow/Breakless2.scala def searchFrom(i: Int): Int = if (i >= args.length) -1 else if (args(i).startsWith("-")) searchFrom(i + 1) else if (args(i).endsWith(".scala")) i else searchFrom(i + 1) val i = searchFrom(0)
import scala.util.control.Breaks._ import java.io._ val in = new BufferedReader(new InputStreamReader(System.in)) breakable { while (true) { println("? ") if (in.readLine() == "") break } }

7.7 Variable scope


// In file expressions-and-control-flow/MultiTable.scala def printMultiTable() { var i = 1 // only i in scope here while (i <= 10) { var j = 1 // both i and j in scope here while (j <= 10) { val prod = (i * j).toString // i, j, and prod in scope here var k = prod.length // i, j, prod, and k in scope here while (k < 4) { print(" ") k += 1 } print(prod) j += 1 } // i and j still in scope; prod and k out of scope println() i += 1 } // i still in scope; j, prod, and k out of scope }
while (i <= 10) { var j = 1 ... }
val a = 1 val a = 2 // Does not compile println(a)
// In file expressions-and-control-flow/Misc.scala val a = 1; { val a = 2 // Compiles just fine println(a) } println(a)
scala> val a = 1 a: Int = 1 scala> val a = 2 a: Int = 2 scala> println(a) 2
// In file expressions-and-control-flow/Misc.scala val a = 1; { val a = 2; { println(a) } }

7.8 Refactoring imperative-style code


// In file expressions-and-control-flow/MultiTable2.scala // Returns a row as a sequence def makeRowSeq(row: Int) = for (col <- 1 to 10) yield { val prod = (row * col).toString val padding = " " * (4 - prod.length) padding + prod } // Returns a row as a string def makeRow(row: Int) = makeRowSeq(row).mkString // Returns table as a string with one row per line def multiTable() = { val tableSeq = // a sequence of row strings for (row <- 1 to 10) yield makeRow(row) tableSeq.mkString("\n") }

7.9 Conclusion

For more information about Programming in Scala, Second Edition (the "Stairway Book"), please visit:

http://www.artima.com/shop/programming_in_scala_2ed

and:

http://booksites.artima.com/programming_in_scala_2ed

Copyright © 2007-2010 Artima, Inc. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.