• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Pattern Matching in Scala
 

Pattern Matching in Scala

on

  • 4,271 views

An igNite presentation for DOSUG igNite, October 5th, 2010

An igNite presentation for DOSUG igNite, October 5th, 2010

Statistics

Views

Total Views
4,271
Views on SlideShare
4,265
Embed Views
6

Actions

Likes
1
Downloads
28
Comments
0

3 Embeds 6

http://www.linkedin.com 3
http://speakerrate.com 2
https://duckduckgo.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Pattern Matching in Scala Pattern Matching in Scala Presentation Transcript

    • Derek Chen-BeckerPattern Matching in Scala DOSUG IgNite Presentation October 5th, 2010
    • I Believe Youve Met Mr. “switch”...switch(foo) {case 1 : doBar("two"); break;case 2 : doBar("one"); break;default: doBar("forty-two");} I can feel the excitement! 2
    • Scala Merges OO and Functional Features 3
    • Scalas “match” Like “switch” var foo : Int = 5 foo match { case 1 => doBar("two") case 2 => { doBar("one"); doBar("two") } case _ => doBar("lemon curry?") } No “break”. Each clause is self-contained Matches are tried in order, first match wins What in the heck is this “_” nonsense? 4
    • Match Against Broader Range of Types def literalMatch (in: Any) { in match { case 1 => doBar("One") case "test" => doBar("test") case x => doBar("x") case 2.2f => doBar("float") case _ => doBar("lemon curry?") } } You can think of this like nested “if” statements 5
    • Alternate Patterns def literalMatch (in: Any) { in match { case 1 | 2 | 3 => doBar("One to three") case "this" | "that" => doBar("the other") case _ => doBar("lemon curry?") } } “|” allows clause to match multiple values 6
    • Binding Variables in Matches def literalMatch (in: Any) { in match { case n @ (1 | 2 | 3) => doBar("1-3:" + n) case t @ ("this" | "that") => DoBar(t + " and the other") case x => doBar("We defaulted on " + x) } } You can bind a complex pattern with “x @ pattern” Just a variable as a pattern matches anything 7
    • Matching on Typedef typeMatch (in: Any) { in match { case i : Int => doBar("Int : " + i) case s : String => doBar(s) case _ => // NOOP }} 8
    • Matching on Generic Typesdef typeMatch (in: Any) { in match { case ls : List[String] => doBar("danger!") case li : List[Int] => doBar("never happens") case _ => // NOOP }} You cant match on generic types because of erasure The compiler will warn about unchecked conversions if you do this 9
    • Guards Permit Fine-Grained Selection 10
    • <Ahem> Guards Permit Fine-Grained Selectiondef fifenator (in: Any) { in match { case i : Int if i > 12 && i < 47 => doBar("Int : " + i) case s : String if s.startsWith("DOSUG") => doBar(s) case _ => // NOOP }} A guard is just a conditional clause for the match Because the type is being matched on the left, you have direct access to the type methods and fields without casts 11
    • A Brief Digression into Case Classescase class Character(show : String, name : String) A Case Class is a special type of class that automatically adds methods for equals, hashcode, toString, and PATTERN MATCHING 12
    • A Brief Digression into Case Classesdef tvTime (c : Character) = c match { case Character(title, "Fred") => doBar("Fred from " + title) case Character("Flintstones", n) => doBar(n) case c @ Character(_,_) => doBar(c.name)} Constructor arguments automatically become properties that you can match against 13
    • But Wait, Theres More! Custom Extractors Sealed class hierarchy enforcement Cleans Tough Stains! Gentle on Hands! Repels Cougars! And more! 14
    • Sealed Hierarchy Enforcementsealed abstract class EntityType(val name : String)case class Animal(n : String) extends EntityType(n)case class Vegetable(n : String) extends EntityType(n)case class Mineral(n : String) extends EntityType(n) “sealed” indicates that all direct subclasses are defined in the same source file Provides the compiler with a guaranteed bound on the type hierarchy: scala> def questionOne(t : EntityType) = t match { | case Animal(name) => println("Animal: " + name) | case Vegetable(name) => println("Veggie: " + name) |} <console>:8: warning: match is not exhaustive! missing combination Mineral def questionOne(t : EntityType) = t match { 15
    • Custom Extraction Basicsobject Something { def unapply(input : Foo) : Option[Bar] = { if (input.bar) Some(input.toBar) else None }} An “object” is a singleton in the VM, defined as you would a class Methods on an object equivalent to “static” methods in Java 16
    • Custom Extraction Basicsobject Something { def unapply(input : Foo) : Option[Bar] = { if (input.bar) Some(input.toBar) else None }} Option is a predefined Scala type that has only two subclasses: Some and None A Some holds a typed value 17
    • Custom Extraction Basicsobject Something { def unapply(input : Foo) : Option[Bar] = { if (input.bar) Some(input.toBar) else None }} The “unapply” method holds special significance to the compiler Is used to attempt an extraction/match from a given input Returning Some(something) indicates a match Returning None indicates no match 18
    • Custom Extraction: IP Addressobject Octet { def unapply(input : String) = try { val octet = input.toInt if (octet >= 0 && octet < 256) Some(octet) else None } catch { case _ => None }} First we just define what an octet in an IP is: An Int... Between 0 and 255 19
    • Custom Extraction: IP Addressobject IP {def unapplySeq(input : String) : Option[Seq[Int]] = input.split(.) match { case Array(Octet(a), Octet(b), Octet(c), Octet(d)) => Some(List(a,b,c,d)) case _ => None }} “unapplySeq” allows us to return a sequence of results on a match We nest our Octet matcher to match each IP component 20
    • Custom Extraction in Actionscala> def sumIP (address : String) = address match { | case IP(7, b, c, d) => println("Jackpot!"); Some(7 + b + c + d) | case IP(a,b,c,d) ⇒ Some(a + b + c + d) | case _ => None |}sumIP: (address: String)Option[Int]scala> sumIP("12.25.233.61")res5: Option[Int] = Some(331)scala> sumIP("12.25.233")res6: Option[Int] = Nonescala> sumIP("7.25.233.61")Jackpot!res7: Option[Int] = Some(326) 21
    • Still With Me? 22
    • 23