66
CHAPTER 3
■ COLLECTIONS AND THE JOY OF IMMUTABILITY
Listing 3-5. Roman Numerals
def roman(in: List[Char]): Int = in match {
case 'I' :: 'V' :: rest => 4 + roman(rest)
case 'I' :: 'X' :: rest => 9 + roman(rest)
case 'I' :: rest => 1 + roman(rest)
case 'V' :: rest => 5 + roman(rest)
case 'X' :: 'L' :: rest => 40 + roman(rest)
case 'X' :: 'C' :: rest => 90 + roman(rest)
case 'X' :: rest => 10 + roman(rest)
case 'L' :: rest => 50 + roman(rest)
case 'C' :: 'D' :: rest => 400 + roman(rest)
case 'C' :: 'M' :: rest => 900 + roman(rest)
case 'C' :: rest => 100 + roman(rest)
case 'D' :: rest => 500 + roman(rest)
case 'M' :: rest => 1000 + roman(rest)
case _ => 0
}
case 'I' :: 'V' :: rest => 4 + roman(rest)
tests the first two characters, and if they are
IV, the method returns 4 plus the Roman numeral conversion of the rest of the
List[Char].
If the test falls through to
case _ => 0, there are no more Roman numerals, 0 is returned,
and there’s no more recursion—no more calls back into the
roman() method. Without explicit
looping or length testing or explicit branching logic, we’ve written a concise, readable
method.
Scala’s
List and other sequential collections provide powerful ways to define business
logic in a concise, maintainable way. In the next section, we’re going to explore Tuples,
which are fixed-length collections where each element can be a different type.
Tuples
Have you ever written a method that returns two or three values? Let’s write a method that
takes a
List[Double] and returns the count, the sum, and the sum of squares returned in a
three-element Tuple, a
Tuple3[Int, Double, Double]:
def sumSq(in: List[Double]): (Int, Double, Double) =
in.foldLeft((0, 0d, 0d))((t, v) => (t._1 + 1, t._2 + v, t._3 + v * v))
The sumSq method takes a List[Double] as input and returns a Tuple3[Int, Double, Double].
The compiler desugars
(Int, Double, Double) into Tuple3[Int, Double, Double]. The
compiler will treat a collection of elements in parenthesis as a Tuple. We seed the
foldLeft
with
(0, 0d, 0d), which the compiler translates to a Tuple3[Int, Double, Double]. The
function takes two parameters:
t and v. t is a Tuple3, and v is a Double. The function returns
19897ch03.fm Page 66 Thursday, April 16, 2009 4:54 PM