pattern matching. the match statement c and java have a switch statement which uses a small integer...

18
Pattern Matching

Upload: malcolm-manning

Post on 18-Dec-2015

215 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

Pattern Matching

Page 2: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

The match statement

C and Java have a switch statement which uses a small integer value to choose among alternatives

In Java 7, it is now possible to use switch with Strings switch is rarely used in Java programs

The Scala “equivalent” is the match expression scala> val n = 4n: Int = 4

scala> n match { | case 1 => "one" | case 2 => "two" | case _ => "many" | }res0: String = many

2

Page 3: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

Matching on values scala> object Obj

defined module Obj scala> val d = 5.0

d: Double = 5.0 scala> val lst = List(1, 2, 3)

lst: List[Int] = List(1, 2, 3) scala> def valMatch(x: Any) = x match {

| case 5 => println("Int") | case 5.0 => println("Double") | case "abc" => println("String") | case List(1, 2, 3) => println("List") | case Obj => println("User-defined Obj") | case _ => println("None of the above") | }valMatch: (x: Any)Unit

scala> valMatch(5)Int

scala> valMatch(Obj)User-defined Obj

scala> valMatch("abc")String

3

Page 4: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

Matching on types scala> def whatKind(x: Any) = x match {

| case s: String => s"This is the string [$s]" | case d: Double => s"$d is a Double" | case i: Int => s"$i is an Int" | case x => s"I don't know what $x is" | }whatKind: (x: Any)String

scala> whatKind(5.0)res3: String = 5.0 is a Double

scala> whatKind(List(1, 2, 3))res4: String = I don't know what List(1, 2, 3) is

4

Page 5: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

Matching with guards scala> def oddOrEven(n: Any) = n match {

| case n: Int if n % 2 == 0 => "Even integer" | case n: Int => "Odd integer" | case x => x + " is something else" | }oddOrEven: (n: Any)String

scala> oddOrEven(5)res18: String = Odd integer

scala> oddOrEven(6)res19: String = Even integer

scala> oddOrEven(7.0)res20: String = 7.0 is something else

5

Page 6: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

Matching on user-defined types For user-defined classes, you can match on the type

scala> class Person(val name: String)defined class Person

scala> val dave = new Person("Dave")dave: Person = Person@234bb715

scala> dave match { | case n: Person => "ok" | case _ => "nope!" | }res2: String = ok

But you can’t match on the particular object of a plain (non-case) class scala> dave match {

| case Person("Dave") => "ok" | case _ => "nope!" | }<console>:14: error: not found: value Person

6

Page 7: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

Matching on objects of case classes scala> val dave = new Person("Dave")

dave: Person = Person(Dave)

scala> val beth = new Person("Beth")beth: Person = Person(Beth)

scala> def sayHi(p: Person) = p match { | case Person("Dave") => "Oh, it's just Dave." | case Person(name) => s"Hi, $name!" | }sayHi: (p: Person)String

scala> sayHi(dave)res7: String = Oh, it's just Dave.

scala> sayHi(beth)res8: String = Hi, Beth!

7

Page 8: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

Matching on exceptions

Scala’s try-catch-finally is similar to Java’s, but the catch clauses are case expressions

try { val f = new FileReader("input.txt")} catch { case ex: FileNotFoundException => { println("Missing file exception") } case ex: IOException => { println("IO Exception") }} finally { println("Exiting finally...")}

Source: http://www.tutorialspoint.com/scala/scala_exception_handling.htm 8

Page 9: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

Matching on optional values

The Option type is used frequently in Scala Scala’s None is used in places where Java might use null

scala> val scores = List(78, 43, 82, 67, 55)scores: List[Int] = List(78, 43, 82, 67, 55)

scala> scores find (_ > 90)res0: Option[Int] = None

scala> scores find (_ < 70)res1: Option[Int] = Some(43)

scala> (scores find (_ < 30)) match { | case None => "Everyone is passing" | case Some(n) => n + " isn't very good" | }res2: String = Everyone is passing

9

Page 10: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

Matching in assignments scala> val jean = new Person("Jean", 23)

jean: Person = Person(Jean,23)

scala> jean match { | case Person(n, a) => s"$n is $a years old" | }res5: String = Jean is 23 years old

scala> val Person(n, a) = jeann: String = Jeana: Int = 23

scala> val list = List(1, 2, 3, 4, 5)list: List[Int] = List(1, 2, 3, 4, 5)

scala> val h :: hh :: t = listh: Int = 1hh: Int = 2t: List[Int] = List(3, 4, 5)

10

Page 11: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

Matching in for expressions scala> val capitals = Map("France" -> "Paris", "Japan" ->

"Tokyo")capitals: scala.collection.immutable.Map[String,String] = Map(France -> Paris, Japan -> Tokyo)

scala> for ((country, city) <- capitals) { | println(s"The capital of $country is $city.") | }The capital of France is Paris.The capital of Japan is Tokyo.

Values that don’t match are simply filtered out scala> val scores = List(("John", 90), ("Mary", 100),

("Bill", 95), ("Jane", 100))scores: List[(String, Int)] = List((John,90), (Mary,100), (Bill,95), (Jane,100))

scala> for ((name, 100) <- scores) println(name)MaryJane

11

Page 12: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

Patterns as partial functions

A sequence of cases is a partial function, and may be used anywhere a function literal may be used

scala> val factorial: Int => Int = { | case 1 => 1 | case n => n * factorial(n - 1) | }factorial: Int => Int = <function1>=

scala> factorial(5)res14: Int = 120

scala> (1 to 10) map { | case n if n % 2 == 0 => n / 2 | case n => 3 * n + 1 | }res16: scala.collection.immutable.IndexedSeq[Int] = Vector(4, 1, 10, 2, 16, 3, 22, 4, 28, 5)

12

Page 13: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

Failing to match

It’s an error if no case in a pattern match is satisfied There are two basic choices for the last case:

case _ will match anything, and you don’t care what case variable will match anything, and you can use the value

of the variable in the body of the case

13

Page 14: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

isDefinedAt A Map is a partial function from keys to values The method isDefinedAt determines whether a partial

function is defined for a particular input value scala> val scores = List(("John", 90), ("Mary", 100),

("Bill", 95), ("Jane", 100))scores: List[(String, Int)] = List((John,90), (Mary,100), (Bill,95), (Jane,100))

scala> val mapScores = scores.toMapmapScores: scala.collection.immutable.Map[String,Int] = Map(John -> 90, Mary -> 100, Bill -> 95, Jane -> 100)

scala> mapScores.isDefinedAt("William")res1: Boolean = false

scala> mapScores.isDefinedAt("Bill")res2: Boolean = true 14

Page 15: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

collect collect is a partial function that takes an iterator and returns a new iterator

over only defined values

def collect[B](pf: PartialFunction[A, B]): Iterator[B]

scala> val scores = Map(("John", 90), ("Mary", 100), ("Bill", 95), ("Jane", 100))scores: scala.collection.immutable.Map[String,Int] = Map(John -> 90, Mary -> 100, Bill -> 95, Jane -> 100)

scala> val names = List("John", "Frank", "Jane", "Joe")names: List[String] = List(John, Frank, Jane, Joe)

scala> names collect scoresres10: List[Int] = List(90, 100)

15

Page 16: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

Sealed classes

A class is sealed if (1) it is declared with the keyword sealed, and (2) all subclasses are declared on the same file

This allows Scala to check for missing cases scala> sealed class Person // omitting responses to save space

scala> class Man extends Personscala> class Woman extends Personscala> class Child extends Person

scala> val p: Person = new Womanp: Person = Woman@12efc0ee

scala> p match { | case m: Man => "male" | case f: Woman => "female" | }<console>:12: warning: match may not be exhaustive.It would fail on the following inputs: Child(), Person() p match { ^res5: String = female

16

Page 17: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

@ and _*

In pattern matching, val @ pattern_part captures the value of the pattern part in the value

In matching a sequence, _* matches the remainder of the sequence

scala> list match { | case a @ List(b @ _, c @ _*) => s"After $b in $a comes $c" | }res7: String = After 1 in List(1, 2, 3, 4, 5) comes List(2, 3, 4, 5)

17

Page 18: Pattern Matching. The match statement C and Java have a switch statement which uses a small integer value to choose among alternatives In Java 7, it is

18

The End