Scala Miscellany Exceptions and other things Maps  scala> val m = Map("apple" -> "red", "banana" -> "yellow") m: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map((apple,red), (banana,yellow))      Notice that a.

Download Report

Transcript Scala Miscellany Exceptions and other things Maps  scala> val m = Map("apple" -> "red", "banana" -> "yellow") m: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map((apple,red), (banana,yellow))      Notice that a.

Scala Miscellany
Exceptions and other things
Maps

scala> val m = Map("apple" -> "red", "banana" -> "yellow")
m: scala.collection.immutable.Map[java.lang.String,java.lang.String]
= Map((apple,red), (banana,yellow))





Notice that a Map is really just a list of Tuples
The -> is provided as a more readable syntax
scala> m("banana")
res2: java.lang.String = yellow
scala> m contains "apple"
res3: Boolean = true
scala> m("cherry")
java.util.NoSuchElementException: key not found: cherry
Higher-order methods on Lists

map applies a one-parameter function to every element of a List, returning a
new List






scala> def double(n: Int) = 2 * n
double: (n: Int)Int
scala> val ll = List(2, 3, 5, 7, 11)
ll: List[Int] = List(2, 3, 5, 7, 11)
scala> ll map double
res5: List[Int] = List(4, 6, 10, 14, 22)
scala> ll map (n => 3 * n)
res6: List[Int] = List(6, 9, 15, 21, 33)
scala> ll map (n => n > 5)
res8: List[Boolean] = List(false, false, false, true, true)
filter applies a one-parameter test to every element of a List, returning a List
of those elements that pass the test


scala> ll filter(n => n < 5)
res10: List[Int] = List(2, 3)
scala> ll filter (_ < 5) // abbreviated function where parameter is used once
res11: List[Int] = List(2, 3)
More higher-order methods

def filterNot(p: (A) => Boolean): List[A]


def count(p: (A) => Boolean): Int


Tests whether a predicate holds for at least one of the elements of this list
def find(p: (A) => Boolean): Option[A]


Tests whether a predicate holds for every element of this list
def exists(p: (A) => Boolean): Boolean


Counts the number of elements in the list which satisfy a predicate
def forall(p: (A) => Boolean): Boolean


Selects all elements of this list which do not satisfy a predicate
Finds the first element of the list satisfying a predicate, if any
def sortWith(lt: (A, A) => Boolean): List[A]

Sorts this list according to a comparison function
The Option type


Scala has null because it interoperates with Java; it
shouldn’t be used any other time
Instead, use an Option type, with values Some(value)
and None


def max(list: List[Int]) = {
if (list.length > 0) {
val biggest = (list(0) /: list) { (a, b) => if (a > b) a else b }
Some(biggest)
} else {
None
}
max(myList) match {
case Some(x) => println("The largest number is " + x)
case None => println("There are no numbers here!!!")
}
The Either type

scala> def f(i: Int) =
|
if (i == 0) {
|
Left("Divide by zero")
|
} else {
|
Right(24 / i)
| }
scala> for (i <- -3 to 3) {
|
f(i) match {
|
case Left(x) => println(s"Left with $x")
|
case Right(x) => println(s"Right with half of ${2 * x}")
|
}
| }
Right with half of -16
Right with half of -24
Right with half of -48
Left with Divide by zero
Right with half of 48
Right with half of 24
Right with half of 16
6
The require and assert methods


require and assert are methods that throw an exception when
their argument is false
require is used to document something that must be true in order
for the code to work



def sqrt(x: Double) = { require(x >= 0); ... }
require is often used at the beginning of a method
assert is used to document something that you “know” to be true


takeCis554course
assert(languagesIKnow contains "Scala")
assert is often used as “executable documentation”
The ensuring method

The ensuring method applies a predicate to a value and, if the predicate result
is true, returns the value, otherwise throws an AssertionError







Syntax: value ensuring(predicate)
scala> 12 ensuring(true)
res1: Int = 12
scala> 12 ensuring(_ > 10)
res2: Int = 12
scala> def twice(x: Int) = 2 * x ensuring(_ > 0)
twice: (x: Int)Int
scala> twice(3)
res3: Int = 6
scala> twice(-5)
java.lang.AssertionError: assertion failed (+ many lines)
ensuring can be useful to guarantee the result of a method

Always use _ in the predicate to represent the method’s return value
Dealing with exceptions

Scala’s exception creation and throwing is like Java:



class RottenEggException extends Exception
throw new RottenEggException
Catching a thrown exception uses pattern matching:

try {
makeAnOmlet
} catch {
case ex: RottenEggException => println("#$%&#@")
case ex: Exception => println("What went wrong?")
}
File I/O

object TestIO {
def main(args: Array[String]) {
println("Testing file I/O")
import java.io._
import scala.io.Source
val file = new File("testio.txt")
val writer = new PrintWriter(file)
writer write "first\r\n"
writer write "second"
writer.close()



Use correct case for file names
(only Windows ignores case)
Use forward slashes, /, in paths,
which work on any platform, not
backslashes, \, which work only on
Windows
Windows, Mac, and Linux have
different end-of-line codes (\r\n is
Windows), and this causes
problems
val lines = Source.fromFile(file).getLines().toList
println(lines)
}

}
Testing file I/O
List(first, second)
Use the source, Luke



Books and tutorials are good for learning the syntax of Scala, but they
aren’t much help learning the API
Unfortunately, Scala’s API documentation isn’t very complete
The good news is, it’s easy to get to the source code—and in most cases,
the source code is easier to read than you might think
The End
12