Transcript Miscellany
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