Copyright © Cay S. Horstmann 2015
This work is licensed under a Creative Commons Attribution 4.0 International License
switch
switch
val ch: Char = ... ch match { case '+' => println("Positive") case '-' => println("Negative") case _ => println("Zero") }
break
, no fallthrough—only the first match is executedcase _
is equivalent of default
if
, match
is an expression:
val sign = ch match { case '+' => 1 case '-' => -1 case _ => 0 }
case ch => An expression using ch
case _
as a special case with unused variablecase ch if Character.isDigit(ch) => ...
case Pi => ... // Matches constant Pi case ch => ... // Matches variable ch
case
variable :
Type
obj match { case x: Int => x case s: String => Integer.parseInt(s) case _: BigInt => Int.MaxValue case _ => 0 }
obj match { case _: BigInt => ... // Matches if obj is a BigInt instance case BigInt => ... // Matches if obj is the BigInt companion object
x
Never Be?x match { case Foo => 1 case y: Foo => 2 case foo => 3 case _ => 4 }
apply
, unapply
, toString
, equals
, hashCode
, copy
val
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(x, "CHF") => x + " swiss francs" case Nothing => "" }
Option[T]
is a safe alternative to “T
or null
”Some[T]
that wraps a valueNone
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") }
getOrElse
:
println(scores.get("Alice").getOrElse("No score"))
getOrElse
of the map:
println(scores.getOrElse("Alice", "No score"))
pair match {
case (x, 0) => ... // Matches if pair._2
is 0
}
_
to match any value
case Array(x, _) => ...
_*
to match a sequence (such as the tail of an array):
case Array(0, _*) => ...
case Array(1, x@_*) => ... // Binds x
to tail
Seq
, can instead use
case 0 +: x
Classname(args)
, apply
turns args into an objectval p = ... // some Point val Point(x, y) = p
p match { case Point(x, y) => ... }
x
and y
that, when passed to Point
, make p
unapply
method:
object Point { def unapply(input: Point) = Some((input.x, input.y)) ... }
Option
, in case the match failsval t1 = Tuple2(3, 4) val t2 = new Tuple2(3, 4) val t3 = Tuple2.apply(3, 4) val t4 = new Tuple2.apply(3, 4) val Tuple2(x, y) = t1 val Tuple2(a, b) = Tuple2.unapply(t1) val t5 = Tuple2.unapply(t1)
unapply
yields a pair:
case x Point y => ...
case head :: tail => ...
::
is a class!case first :: second :: rest => ... // Same as case ::(first, ::(second, rest))
Option
TypeOption
type for Double
values. Provide Option
, Some
, and None
. What are they?inv
that maps x into its inverse (1 / x), returning an Option
. Return None
when x is zero. What is your function? What happens when you call inv(2)
? inv(0)
?isEmpty
that returns true
for None
and false
for Some
.get
that returns the value wrapped in Some
and throws a NoSuchElementException
if there is no value. There are two ways of defining methods on an Option
. You can either define a method in Option
, using pattern matching. Or you can leave the method abstract in Option
and override it in Some
and None
. In this step, use whichever approach you didn't use in the preceding step.getOrElse
that returns the value wrapped in Some
and a default if there is no value. Do this by calling isEmpty
/get
List
type for Double
values. A list is either Nil
or a node with a head that's a Double
and a tail that's again a List
. Such a node is traditionally called a Cons
node. Define the types List
, Nil
, and Cons
.Cons(3, Cons(4, Cons(5, Nil)))
.List
called ::
that lets you make a list as 3.0 :: 4.0 :: 5.0 :: Nil
. What special rule for operators (briefly mentioned in Unit 7) makes this work?3.0 :: 4.0 :: 5.0 :: Nil
is printed in the worksheet. Fix it by defining toString
so that it shows up as 3.0 :: 4.0 :: 5.0 :: Nil
.case Cons(h, t) => ...It would be prettier to write
case h :: t => ...That's achieved by renaming the class
Cons
into ::
. Do that, and fix up the sum
function to match. Don't change the name of the ::
method. There is both a ::
method (used for construction) and a ::
class (for extraction). You may run into a problem in your definition of the ::
method. If you do, fix it by adding new
.
unapply
method in the preceding step?Num
and Op
so that one can make expressions such as
Op("+", Op("*", Num(2), Num(3)), Num(4))Hint: You need a common superclass, like this:
abstract class Expr case class Op(...) extends Expr
eval
that evaluates an expression such as the one given above. Use pattern matching and recursion:
def eval(e: Expr): Int = e match { ... }
Do this as individual work, not with your partner
When all done, email the signed zip files to Fatemeh.Borran@heig-vd.ch