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"> 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">
Download presentation
Presentation is loading. Please wait.
Published byMalcolm Manning Modified over 9 years ago
1
Pattern Matching
2
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 = 4 n: Int = 4 scala> n match { | case 1 => "one" | case 2 => "two" | case _ => "many" | } res0: String = many 2
3
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
4
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
5
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
6
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!" | } :14: error: not found: value Person 6
7
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
8
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
9
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 (_ "Everyone is passing" | case Some(n) => n + " isn't very good" | } res2: String = Everyone is passing 9
10
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) = 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
11
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) Mary Jane 11
12
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 = = 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
13
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
14
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.toMap mapScores: 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
15
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 scores res10: List[Int] = List(90, 100) 15
16
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 Person scala> class Woman extends Person scala> class Child extends Person scala> val p: Person = new Woman p: Person = Woman@12efc0ee scala> p match { | case m: Man => "male" | case f: Woman => "female" | } :12: warning: match may not be exhaustive. It would fail on the following inputs: Child(), Person() p match { ^ res5: String = female 16
17
@ 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
18
18 The End
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.