Copyright © Cay S. Horstmann 2015
switch
statement:
sign = ch match { case '+' => 1 case '-' => -1 case _ => 0 }
if
.break
.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) }
import scala.math._ x match { case Pi => ... ... }
`...`
:
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 }
var.isInstanceOf[Type]
obj match { case BigInt => -1 // Matches the BigInt object of type Class .. }
case
syntax:
try { ... } catch { case e: IOException => println("Caught " + e) }
try { ... } catch { case _: Throwable => println("Oh noes!") }
pair match { case (0, _) => "0 ..." case (y, 0) => y + " 0" case _ => "neither is 0" }
arr match { case Array(0) => "0" case Array(x, y) => x + " " + y case Array(0, _*) => "0 ..." case _ => "something else" }
case
clause:
val (uppercase, lowercase) = "Hello, World".partition(Character.isUpperCase(_)) // partition returns a pair val Array(first, second, _*) = arr
for
expressions:
for ((key, value) <- map) // a map is a sequence of pairs println(key + "->" + value)
_*
:
val Array(first, second, rest @ _*) = arr
abstract class Amount case class Dollar(value: Double) extends Amount case class Currency(value: Double, unit: String) extends Amount case object Nothing extends Amount
amt match { case Dollar(v) => "$" + v case Currency(_, u) => "Oh noes, I got " + u case Nothing => "" }
val
:
case class Currency(value: Double, unit: String) extends Amount
apply
factory method:
Currency(1000, "EUR")
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
.Some[T]
that wraps a value.None
that indicates that there is no value.Map[K, V].get
returns an Option[V]
, either Some(v)
or
None
.val scores = Map("Alice" -> 1, "Bob" -> 2) scores.get("Alice") match { case Some(score) => println(score) case None => println("No score") }
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
val e = Product(Num(3), Sum(Num(4), Num(5)))
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) }
abstract class Expr { def eval: Int } class Sum(val left: Expr, val right: Expr) extends Expr { def eval: Int = left.eval + right.eval }
swap
that receives a pair of integers and returns the pair with the components swapped.swap
that receives an Array[Int]
and returns the array with the first two elements swapped, provided the length is at least two.abstract class Item case class Article(description: String, price: Double) extends Item case class Bundle(description: String, discount: Double, items: Item*) extends ItemDeclare an
Article
: the book “Scala for the Impatient” for $39.95:
val book = ...
val gift = ...
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?price(book)
? price(gift)
?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.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
TypeOption
type for Double
values. Provide classes DoubleOption
, SomeDouble
, and NoDouble
. What are they?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)
?Double => DoubleOption
, yielding another function of the same type. The composition should yield NoDouble
if either function does. For example, with
def f(x: Double) = if (x <= 1) SomeDouble(sqrt(1 - x)) else NoDouble val h = compose(inv, f) // inv(f(x)) when definedthe result of
h(1)
and h(2)
are NoDouble
, but h(0)
is SomeDouble(1)
.isEmpty
that returns true
for NoDouble
and false
for SomeDouble
. Use pattern matching.get
that returns the value wrapped in SomeDouble
and throws a NoSuchElementException
if there is no value. Use pattern matching.DoubleOption
and override them in SomeDouble
and NoDouble
.