Pattern Matching The match statement n C and


















- Slides: 18
Pattern Matching
The match statement n C and Java have a switch statement which uses a small integer value to choose among alternatives n n n 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 n scala> val n = 4 n: Int = 4 scala> n match { | case 1 => "one" | case 2 => "two" | case _ => "many" | } res 0: String = many 2
Matching on values n n n n 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 val. Match(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") | } val. Match: (x: Any)Unit scala> val. Match(5) Int scala> val. Match(Obj) User-defined Obj scala> val. Match("abc") String 3
Matching on types n scala> def what. Kind(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" | } what. Kind: (x: Any)String scala> what. Kind(5. 0) res 3: String = 5. 0 is a Double scala> what. Kind(List(1, 2, 3)) res 4: String = I don't know what List(1, 2, 3) is 4
Matching with guards n scala> def odd. Or. Even(n: Any) = n match { | case n: Int if n % 2 == 0 => "Even integer" | case n: Int => "Odd integer" | case x => x + " is something else" | } odd. Or. Even: (n: Any)String scala> odd. Or. Even(5) res 18: String = Odd integer scala> odd. Or. Even(6) res 19: String = Even integer scala> odd. Or. Even(7. 0) res 20: String = 7. 0 is something else 5
Matching on user-defined types n For user-defined classes, you can match on the type n n scala> class Person(val name: String) defined class Person scala> val dave = new Person("Dave") dave: Person = Person@234 bb 715 scala> dave match { | case n: Person => "ok" | case _ => "nope!" | } res 2: String = ok But you can’t match on the particular object of a plain (non-case) class n scala> dave match { | case Person("Dave") => "ok" | case _ => "nope!" | } <console>: 14: error: not found: value Person 6
Matching on objects of case classes n n n scala> val dave = new Person("Dave") dave: Person = Person(Dave) scala> val beth = new Person("Beth") beth: Person = Person(Beth) scala> | | | say. Hi: def say. Hi(p: Person) = p match { case Person("Dave") => "Oh, it's just Dave. " case Person(name) => s"Hi, $name!" } (p: Person)String scala> say. Hi(dave) res 7: String = Oh, it's just Dave. scala> say. Hi(beth) res 8: String = Hi, Beth! 7
Matching on exceptions n Scala’s try-catch-finally is similar to Java’s, but the catch clauses are case expressions n try { val f = new File. Reader("input. txt") } catch { case ex: File. Not. Found. Exception => { println("Missing file exception") } case ex: IOException => { println("IO Exception") } } finally { println("Exiting finally. . . ") } n Source: http: //www. tutorialspoint. com/scala_exception_handling. htm 8
Matching on optional values n n The Option type is used frequently in Scala’s None is used in places where Java might use null n n scala> val scores = List(78, 43, 82, 67, 55) scores: List[Int] = List(78, 43, 82, 67, 55) scala> scores find (_ > 90) res 0: Option[Int] = None scala> scores find (_ < 70) res 1: Option[Int] = Some(43) scala> (scores find (_ < 30)) match { | case None => "Everyone is passing" | case Some(n) => n + " isn't very good" | } res 2: String = Everyone is passing 9
Matching in assignments n 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" | } res 5: String = Jean is 23 years old scala> val Person(n, a) = jean n: String = Jean a: 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 = list h: Int = 1 hh: Int = 2 t: List[Int] = List(3, 4, 5) 10
Matching in for expressions n 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. n Values that don’t match are simply filtered out n n 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) Mary Jane 11
Patterns as partial functions n n n 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 = <function 1>= scala> factorial(5) res 14: Int = 120 scala> | | | res 16: 1, 10, (1 to 10) map { case n if n % 2 == 0 => n / 2 case n => 3 * n + 1 } scala. collection. immutable. Indexed. Seq[Int] = Vector(4, 2, 16, 3, 22, 4, 28, 5) 12
Failing to match n n It’s an error if no case in a pattern match is satisfied There are two basic choices for the last case: n n 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
is. Defined. At n n A Map is a partial function from keys to values The method is. Defined. At determines whether a partial function is defined for a particular input value n n 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 map. Scores = scores. to. Map map. Scores: scala. collection. immutable. Map[String, Int] = Map(John -> 90, Mary -> 100, Bill -> 95, Jane -> 100) scala> map. Scores. is. Defined. At("William") res 1: Boolean = false scala> map. Scores. is. Defined. At("Bill") res 2: Boolean = true 14
collect n collect is a partial function that takes an iterator and returns a new iterator over only defined values n n def collect[B](pf: Partial. Function[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 scores 10: List[Int] = List(90, 100) 15
Sealed classes n n 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 n n n scala> sealed class Person // omitting responses to save space scala> class Man extends Person scala> class Woman extends Person scala> class Child extends Person scala> val p: Person = new Woman p: Person = Woman@12 efc 0 ee 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 { ^ res 5: String = female 16
@ and _* n n n 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" | } res 7: String = After 1 in List(1, 2, 3, 4, 5) comes List(2, 3, 4, 5) 17
The End 18


















