Scala Essentials - Pattern Matching and Case Classes

9,746 views
9,484 views

Published on

In-depth presentation about basics of pattern matching and case classes given by Karel Smutný at the April's Czech Scala Enthusiasts meetup held at Faculty of Information Technology in Prague.

Published in: Technology, Business

Scala Essentials - Pattern Matching and Case Classes

  1. 1. CTU-FIT-SCA/scalaonfitIf you’re gonna code,download the following Gisthttps://gist.github.com/ksmutny/5439360Czech Scala Enthusiasts–April 23 2013Scala Essentials: Pattern Matching and Case ClassesKarel Smutný–Agile Developer & Coach
  2. 2. switch statementswitch (whatIsThis) {case 8:case 10:doSomething();break;case 12:doSomethingElse();break;default:doDefault();}match expressionwhatIsThis match {case 8 | 10 => somethingcase 12 => somethingElsecase _ => default}
  3. 3. Pattern Matchinga.k.a.Switch on steroids
  4. 4. Pattern Matchinga.k.a.Batman’s toolbelt
  5. 5. https://gist.github.com/ksmutny/5439360sealed trait Character {def name: String}case class Civilian(name: String,wealth: Wealth) extends Charactercase class SuperHero(name: String,powers: List[Power],alterEgo: Option[Civilian]) extends Character
  6. 6. The ProblemWhat are the super powers of anunknown person if it is a superhero who’s alter ego is TonyStark?
  7. 7. Javaif (unknownChar instanceof SuperHero) {final SuperHero hero = (SuperHero) unknownChar;if (hero.alterEgo.equals(tonyStark)) {return hero.powers;} else {return null;}} else {return null;}
  8. 8. ScalaunknownPerson match {case SuperHero(_, powers, Some(TonyStark)) =>Some(powers)case _ => None}
  9. 9. ScalaunknownPerson match {case SuperHero(_, powers, Some(TonyStark)) =>Some(powers)case _ => None}How cool is that?
  10. 10. JavaScriptunknownPerson.hasOwnPropery(“powers”) ?unknownPerson[“powers”] : null;
  11. 11. Kinds of patterns
  12. 12. Wildcard patternwhatIsThis match {case _ => “anything!”}
  13. 13. Constant patternwhatIsThis match {case 42 => “a magic no.”case “Hello!” => “a greeting”case math.Pi => “another magic no.”case _ => “something else”}
  14. 14. Constant patternevaluating {BruceWayne match {case 42 => “a magic no.”case “Hello!” => “a greeting”case math.Pi => “another magic no.”}} should produce[MatchError]
  15. 15. Variable patternwhatIsThis match {case something => “not very useful?”}
  16. 16. Variable patternwhatIsThis match {case whatIsThis => “not very useful?”}
  17. 17. Typed patternwhatIsThis match {case n: Int => “aah, a number”case c: Character => “it’s ” + c.name}
  18. 18. Constructor patternunknownPerson match {case SuperHero(_, powers, Some(TonyStark)) =>Some(powers)case _ => None}
  19. 19. Constant v Variable patternval TonyStark = Civilian(“Tony Stark”, Fortune)val BruceWayne = Civilian(“Bruce Wayne”, Fortune)val clarkKent = Civilian(“Clark Kent”, Cash(1000))TonyStark match {case BruceWayne => “Batman!”case clarkKent => “isn’t this Superman?”case _ => “is he?”}
  20. 20. Constant v Variable patternval TonyStark = Civilian(“Tony Stark”, Fortune)val BruceWayne = Civilian(“Bruce Wayne”, Fortune)val clarkKent = Civilian(“Clark Kent”, Cash(1000))TonyStark match {case BruceWayne => “Batman!”case `clarkKent` => “Superman!”case _ => “anybody”}
  21. 21. Constant v Variable patternval TonyStark = Civilian(“Tony Stark”, Fortune)val BruceWayne = Civilian(“Bruce Wayne”, Fortune)val clarkKent = Civilian(“Clark Kent”, Cash(1000))TonyStark match {case BruceWayne => “Batman!”case `clarkKent` => “Superman!”case _ => “anybody”}
  22. 22. Constructor patternval powers = unknownPerson match {case SuperHero(_, powers, Some(TonyStark)) =>Some(powers)case _ => None}val firstPower = powers match {case Some(power :: rest) => powercase _ => Genius}
  23. 23. Constructor patternval powers = unknownPerson match {case SuperHero(_, powers, Some(TonyStark)) =>Some(powers)case _ => None}val firstPower = powers match {case Some(power :: rest) => powercase _ => Genius}
  24. 24. Constructor patternval powers = unknownPerson match {case SuperHero(_, powers, Some(TonyStark)) =>Some(powers)case _ => None}val firstPower = powers match {case Some(power :: rest) => powercase _ => Genius}
  25. 25. Tuple patternaPair match {case (42, math.Pi, _) => “magic numbers + anything”case (IronMan, Mandarin) => “hate each other”case Tuple2(IronMan, Mandarin) => “alike”case (v: Villain, MaryJane) =>“are cheating on Peter”}
  26. 26. Sequence patternpowers match {case List(SuperStrength, _, _*) =>“at least two”}
  27. 27. Pattern guardaGuy match {case Civilian(_, Cash(money))if cash >= 10000 => “Rich guy”case _ => “anybody else”}
  28. 28. Patterns everywhere
  29. 29. Variable definitionval (a, b) = someTupleval List(Flight, second, rest @ _*) = powersval Civilian(name, wealth: Cash) = clarkKentIs this pattern matching, too?val a = 3
  30. 30. Exceptionstry {doSomethingStupid()} catch {case e: IOException => …case e: SQLException => …}
  31. 31. Partial functionval numToStr: PartialFunction[Int, String] = {case 8 => “eight”case 10 => “ten”}numToStr.isDefinedAt(12)evaluating {numToStr(12)} should produce[??????????????]
  32. 32. For comprehensionsval lines = List(“1t2,3t3,12”,“2t1,3t3,15”,“3t1,12t2,15”)val edges = for {line <- linesArray(srcNode, edges @ _*) = line split “t”edge <- edgesArray(destNode, length) = edge split “,”} yield Edge(srcNode.toInt, destNode.toInt, length.toInt)
  33. 33. For comprehensions. Beware!val egos = for {hero : SuperHero <- characters // does not work} yield hero.alterEgoval egos = for {hero @ (h : SuperHero) <- characters} yield hero.alterEgo
  34. 34. ExtractorsExtractors
  35. 35. trait Person {def name: Stringdef age: Int}object Person {def unapply(person: Person): Option[(String, Int)] =Some((person.name, age))}somePerson match {case Person(“Moses”, _) => 969case Person(name, age) => age}
  36. 36. trait Person {def name: Stringdef age: Int}object Person {def unapply(person: Person): Option[(String, Int)] =Some((person.name, age))}somePerson match {case Person(“Moses”, _) => 969case Person(name, age) => age}
  37. 37. CaseClasses
  38. 38. No need for val in parameterscase class Villain(val name: String,val archenemy: SuperHero) extends Character
  39. 39. No need for val in parameterscase class Villain(val name: String,val archenemy: SuperHero) extends Character
  40. 40. No need for new keywordnew Villain(“Mandarin”, tonyStark)object Villain {def apply(name: String, archenemy: SuperHero) =new Villain(name, archenemy)}
  41. 41. No need for new keywordnew Villain(“Mandarin”, tonyStark)object Villain {def apply(name: String, archenemy: SuperHero) =new Villain(name, archenemy)}
  42. 42. No need for new keywordnew Villain(“Mandarin”, tonyStark)object Villain {def apply(name: String, archenemy: SuperHero) =new Villain(name, archenemy)}
  43. 43. equals and hashCodeval mandarin =Villain(“Mandarin”, tonyStark)mandarin ==Villain(“Mandarin”, tonyStark)val villainRank =Map(mandarin -> 81)
  44. 44. Intuitive toStringTonyStark.toString == “Civilian(Tony Stark,Fortune)”
  45. 45. Handy copy methodval batman = SuperHero(“Batman”,List(Genius, Gadgets),Civilian(“Bruce Wayne”, Fortune))val sixPack = batman.copy(powers = Nil)
  46. 46. …and pattern matchingHow the heck ispattern matching donefor case classes?
  47. 47. Sealed classessealed trait Wealthcase class Cash(n: Int) extends Wealthcase object Fortune extends Wealth
  48. 48. Anyquestions?
  49. 49. Next meetup May 28, 2013Java 8• How does it compare toScala?• A closer look at λ-expressionsimplementation• Influences on futureScala versions, benefitsfor Scala developersScala 2.10• String Interpolation• Value Classes• Implicit Classes• Macros
  50. 50. Next coding dojo–May14, 2013

×