Code Examples for

Programming in Scala, Third Edition

Return to chapter index

7 Built-in Control Structures

Sample run of chapter's interpreter examples

7.1 If expressions


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

7.2 While loops


// In file built-in-control-structures/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 built-in-control-structures/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 built-in-control-structures/Misc.scala def gcd(x: Long, y: Long): Long = if (y == 0) x else gcd(y, x % y)

7.3 For expressions


// In file built-in-control-structures/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 built-in-control-structures/Files.scala // Not common in Scala... for (i <- 0 to filesHere.length - 1) println(filesHere(i))
// In file built-in-control-structures/Files.scala val filesHere = (new java.io.File(".")).listFiles for (file <- filesHere if file.getName.endsWith(".scala")) println(file)
// In file built-in-control-structures/Files.scala for (file <- filesHere) if (file.getName.endsWith(".scala")) println(file)
// In file built-in-control-structures/Files.scala for ( file <- filesHere if file.isFile if file.getName.endsWith(".scala") ) println(file)
// In file built-in-control-structures/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 built-in-control-structures/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 built-in-control-structures/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 built-in-control-structures/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 built-in-control-structures/Exceptions.scala throw new IllegalArgumentException
// In file built-in-control-structures/Exceptions.scala val half = if (n % 2 == 0) n / 2 else throw new RuntimeException("n must be even")
// In file built-in-control-structures/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 built-in-control-structures/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 built-in-control-structures/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 built-in-control-structures/Exceptions.scala def f(): Int = try return 1 finally return 2
// In file built-in-control-structures/Exceptions.scala def g(): Int = try 1 finally 2

7.5 Match expressions


// In file built-in-control-structures/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 built-in-control-structures/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 built-in-control-structures/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 built-in-control-structures/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 built-in-control-structures/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 built-in-control-structures/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 built-in-control-structures/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 built-in-control-structures/Misc.scala val a = 1; { val a = 2; { println(a) } }

7.8 Refactoring imperative-style code


// In file built-in-control-structures/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, Third Edition (the "Stairway Book"), please visit:

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

and:

http://booksites.artima.com/programming_in_scala_3ed

Copyright © 2007-2016 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.