Copyright © Cay S. Horstmann 2015

- Match is a deluxe version of the
`switch`

statement:sign = ch match { case '+' => 1 case '-' => -1 case _ => 0 }

- An expression, like
`if`

. - No
`break`

. - Guards:
ch match { case '+' => sign = 1 case '-' => sign = -1 case _

**if Character.isDigit(ch)**=> digit = Character.digit(ch, 10) case _ => sign = 0 }

`case`

`var`assigns the match expression to the variable:str(i) match { case '+' => sign = 1 case '-' => sign = -1 case

**ch**if Character.isDigit(**ch**) => digit = Character.digit(**ch**, 10) }- Unfortunately, that conflicts with the following:
import scala.math._ x match { case Pi => ... ... }

- Icky rule: Variable must start with a lowercase letter.
- Include lowercase constants in
``...``

:import java.io.File._ str match { case `pathSeparator` => ... ... }

`case`

`var``:`

`Type`matches if`var`has the given type:obj match { case x: Int => x case s: String => Integer.parseInt(s) case _: BigInt => Int.MaxValue case _ => 0 }

- Preferred over
`var`.isInstanceOf[`Type`] - Caution: If you omit the variable, you match the
*companion object*!obj match { case BigInt => -1 // Matches the BigInt object of type Class .. }

- Uses
`case`

syntax:try { ... } catch { case e: IOException => println("Caught " + e) }

- Use wildcard if you don't care about the exception object:
try { ... } catch { case _: Throwable => println("Oh noes!") }

- Can “extract” contents from tuples (i.e., bind variables to the contents):
pair match { case (0, _) => "0 ..." case (y, 0) => y + " 0" case _ => "neither is 0" }

- Also with arrays:
arr match { case Array(0) => "0" case Array(x, y) => x + " " + y case Array(0, _*) => "0 ..." case _ => "something else" }

- Define variables just like in
`case`

clause:val (uppercase, lowercase) = "Hello, World".partition(Character.isUpperCase(_)) // partition returns a pair val Array(first, second, _*) = arr

- Also works in
`for`

expressions:for ((key, value) <- map) // a map is a sequence of pairs println(key + "->" + value)

- Special syntax for binding to
`_*`

:val Array(first, second,

**rest @**_*) = arr

- Case class: class that is optimized for use in pattern
matching.
abstract class Amount case class Dollar(value: Double) extends Amount case class Currency(value: Double, unit: String) extends Amount case object Nothing extends Amount

- Extractors work out of the box:
amt match { case Dollar(v) => "$" + v case Currency(_, u) => "Oh noes, I got " + u case Nothing => "" }

- Each of the constructor parameters becomes a
`val`

:case class Currency(

**value**: Double,**unit**: String) extends Amount - The companion object gets an
`apply`

factory method:Currency(1000, "EUR")

- Methods
`toString`

,`equals`

,`hashCode`

,`unapply`

, and`copy`

are generated. `unapply`

makes extractors work.`copy`

lets you copy values:val amt = Currency(1000, "EUR") val price = amt.copy() val price2 = amt.copy(unit = "CHF")

`Option[T]`

is a safe alternative to providing a value of type`T`

or`null`

.- Case class
`Some[T]`

that wraps a value. - Case object
`None`

that indicates that there is no value. - Example:
`Map[K, V].get`

returns an`Option[V]`

, either`Some(v)`

or`None`

. - Can use pattern matching to process:
val scores = Map("Alice" -> 1, "Bob" -> 2) scores.get("Alice") match { case Some(score) => println(score) case None => println("No score") }

- An expression is either a number, sum, or product:
abstract class Expr case class Num(value: Int) extends Expr case class Sum(left: Expr, right: Expr) extends Expr case class Product(left: Expr, right: Expr) extends Expr

- Sample instance:
val e = Product(Num(3), Sum(Num(4), Num(5)))

- Want to evaluate expressions:
def eval(e: Expr): Int = e match { case Num(v) => v case Sum(l, r) => eval(l) + eval(r) case Product(l, r) => eval(l) * eval(r) }

- In OO programming, one would have used polymorphism for expressions:
abstract class Expr { def eval: Int } class Sum(val left: Expr, val right: Expr) extends Expr { def eval: Int = left.eval + right.eval }

- Polymorphism is appropriate for an
*open-ended*collection of subclasses. - Case classes and pattern matching are best for a
*bounded*collection. - Code is more concise with case classes.
- All cases are in one place.
- Use what works: Scala is functional
*and*object oriented.

- Files and regular expressions A1
- Collections A2
- Annotations A2
- Type parameters (generics, variance) L2
- Advanced types L2 L3
- Implicits L3
- Futures and actors A3

- Using pattern matching, write a function
`swap`

that receives a pair of integers and returns the pair with the components swapped. - Using pattern matching, write a function
`swap`

that receives an`Array[Int]`

and returns the array with the first two elements swapped, provided the length is at least two.

- A store sells items. Some are articles. Others are bundles of articles—stuff that you buy together for a discount.
abstract class Item case class Article(description: String, price: Double) extends Item case class Bundle(description: String, discount: Double, items: Item*) extends Item

Declare an`Article`

: the book “Scala for the Impatient” for $39.95:val book = ...

- Declare a bundle, sold at a $10 discount: the book from before, and a bottle of Old Potrero Straight Rye Whiskey for $79.95:
val gift = ...

- Write a function
`price(it: Item): Double`

that computes the price of an item. Use pattern matching. Start with filling in the case for`Article`

. What is your code? - What happens when you call
`price(book)`

?`price(gift)`

? - Now add the
`Bundle`

case to`price`

. The hard part is to match the varargs. Use`case Bundle(_, disc, its @ _*)`

. You want to recursively compute the sum of the prices of the items (Hint:`map`

,`sum`

), and subtract the discount. - Suppose you have a bundle made up of an article and another bundle, like this:
val special = Bundle("Father's day special", 20.0, Article("Scala for the Impatient", 39.95), Bundle("Anchor Distillery Sampler", 10.0, Article("Old Potrero Straight Rye Whiskey", 79.95), Article("Junípero Gin", 32.95)))

Write a one-line assigment that extracts the description and price of the first article:val ...(descr, price)... = special

`Option`

Type- In this part, we will reimplement the
`Option`

type for`Double`

values. Provide classes`DoubleOption`

,`SomeDouble`

, and`NoDouble`

. What are they? - Write a function
`inv`

that maps`x`into its inverse (1 /`x`), returning a`DoubleOption`

. Return`NoDouble`

when`x`is zero. What is your function? What happens when you call`inv(2)`

?`inv(0)`

? - Write a function that composes two functions of type
`Double => DoubleOption`

, yielding another function of the same type. The composition should yield`NoDouble`

if either function does. For example, withdef f(x: Double) = if (x <= 1) SomeDouble(sqrt(1 - x)) else NoDouble val h = compose(inv, f) // inv(f(x)) when defined

the result of`h(1)`

and`h(2)`

are`NoDouble`

, but`h(0)`

is`SomeDouble(1)`

. - Define a method
`isEmpty`

that returns`true`

for`NoDouble`

and`false`

for`SomeDouble`

. Use pattern matching. - Define a method
`get`

that returns the value wrapped in`SomeDouble`

and throws a`NoSuchElementException`

if there is no value. Use pattern matching. - Repeat the previous two steps, using polymorphism. Define abstract methods in
`DoubleOption`

and override them in`SomeDouble`

and`NoDouble`

.