Beauty of Pattern Matching
-
Upload
czech-scala-enthusiasts -
Category
Technology
-
view
1.716 -
download
0
description
Transcript of Beauty of Pattern Matching
Beauty of pattern matching in ScalaKarel Smutný
Czech Scala Enthusiast1st meet-up, September 20, 2011
Agenda• Scala match expression v Java switch• What is pattern matching• Pattern types• Extractors• Other uses
▫ Variables declaration▫ for expressions▫ catch clauses▫ Regular expressions▫ XML
• Pattern matching v Visitor Pattern
Scala match v Java switchmatch switchsomeFlag match {
case 1 | 2 => doSomething()
case 3 => doSomethingElse()
case _ => doSomethingDefault()
}
switch (someFlag) {case 1:case 2:
doSomething();break;
case 3:doSomethingElse();break;
default:doSomethingDefault();
}
Scala match v Java switchmatch switch• Expression• Returns value of the first
matched alternative• Much, much, much more
powerful
• Statement• Pesky break keyword• Only some primitive types,
String and enum, only literals/constants
What is pattern matching?•Wiki:
“…pattern matching is the act of checking some sequence of tokens for the presence of the constituents of some pattern.”
Wildcard patternobj match {case _ => ...
}
•Matches anything•Used as a default; if not present, compiler
emits a warning
Variable patternobj match {case anotherName => ...
}
•Matches anything, creates new variable•Uses type inference
Type patternobj match {case str: String => …
}
if ((obj instanceof String) && (obj != null)) {String str = (String) obj;…
}
Constant patternobj match {case 4 => …case DasObject => …case `existingVariable` => …
}
•Matches exact value, in terms of ==
Tuple patternobj match {case (4, _, “some text”) => …case (a: Int, b: Double) => …
}
•Matches if obj is proper TupleX and all its fields match
Constructor patterncase class Person(name: String, age: Int)
obj match {case Person(_, 25) => …case Person(“Jarda”, age) => …case Person(_, age) if age >= 18 => …
}
• Matches if value.isInstance[Person] and appropriate attributes match (imagine this in Java)
• Works only for case classes (does it?)
Sequence patternobj match {case List(_, 2, x) => …case List(1, 2, 3, _*) => …case head :: tail => …
}
• Matches variable number of arguments (vararg)• _* matches any number of other arguments,
including none
Extractor• What about non-case classes?
class Person(val name: String, val age: Int)object Person { def unapply(p: Person): Option[(String, Int)] = Some(p.name, p.age)}
obj match {case Person(_, 25) => …case Person(“Jarda”, age) => …case Person(_, age) if age >= 18 => …
}
Other types of extractors• Sequence pattern matching
def unapplySeq(a: SomeClass): Option[Seq[?]]
• One argument only (there is no Tuple1)def unapply(a: SomeClass): Option[Int]
• Note the parentheses (otherwise it would be constant pattern)def unapply(a: SomeClass): Boolean
value match {case SomeClass() => …
}
Other uses: Variable declaration• You may use pattern matching to declare variables:
val (a, b, c) = (5, “text”, someFunction)val (a, _) = (5, “to be forgotten forever”)val Person(name, age) = somePerson
• Geez! Look at this. It’s a pattern matching!
val a = 5
Other uses: for expression• You may use pattern matching in for
expressions:
val personList: List[Person] = ...for (Person(name, age) <- personList) ...
• Don’t forget unapply() on iterated elements
Other uses: catch clause• This is pattern matching, too:
try { doSomethingStupid()}catch { case e: IllegalArgumentException => ... case SomeCustomException(someDetail) => ... case _ => ...}
Other uses: Regular expressions• Guess where is the unapply() method:
val person = “““^(\w)+,(\d)+$”””.rsomeInput match { case person(name, age) => ...}
• Here it is:
class Regex { def unapplySeq(target: Any): Option[List[String]]}
Other uses: XML• Just a teaser (XML pattern matching is out of scope of this
talk):
catalog match { case <catalog>{therms @ _*}</catalog> => for (therm @ <cctherm>{_*}</cctherm> <- therms) ...}
Topic for discussion: Visitor pattern