Upload
czech-scala-enthusiasts
View
4.719
Download
0
Tags:
Embed Size (px)
DESCRIPTION
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.
Citation preview
CTU-FIT-SCA/scalaonfit
If you’re gonna code,download the following Gist
https://gist.github.com/ksmutny/5439360
Czech Scala Enthusiasts–April 23 2013
Scala Essentials: Pattern Matching and Case ClassesKarel Smutný–Agile Developer & Coach
switch statement
switch (whatIsThis) { case 8: case 10: doSomething(); break; case 12: doSomethingElse(); break; default: doDefault();}
match expression
whatIsThis match { case 8 | 10 => something case 12 => somethingElse case _ => default}
Pattern Matchinga.k.a.
Switch on steroids
Pattern Matchinga.k.a.
Batman’s toolbelt
https://gist.github.com/ksmutny/5439360sealed trait Character { def name: String}
case class Civilian( name: String, wealth: Wealth) extends Character
case class SuperHero( name: String, powers: List[Power], alterEgo: Option[Civilian]) extends Character
The ProblemWhat are the super powers of an unknown person if it is a super hero who’s alter ego is Tony Stark?
Javaif (unknownChar instanceof SuperHero) { final SuperHero hero = (SuperHero) unknownChar; if (hero.alterEgo.equals(tonyStark)) { return hero.powers; } else { return null; }} else { return null;}
ScalaunknownPerson match { case SuperHero(_, powers, Some(TonyStark)) => Some(powers) case _ => None}
ScalaunknownPerson match { case SuperHero(_, powers, Some(TonyStark)) => Some(powers) case _ => None}
How cool is that?
JavaScript
unknownPerson.hasOwnPropery(“powers”) ? unknownPerson[“powers”] : null;
Kinds of patterns
Wildcard patternwhatIsThis match { case _ => “anything!”}
Constant pattern
whatIsThis match { case 42 => “a magic no.” case “Hello!” => “a greeting” case math.Pi => “another magic no.” case _ => “something else”}
Constant patternevaluating { BruceWayne match { case 42 => “a magic no.” case “Hello!” => “a greeting” case math.Pi => “another magic no.” }} should produce[MatchError]
Variable pattern
whatIsThis match { case something => “not very useful?”}
Variable pattern
whatIsThis match { case whatIsThis => “not very useful?”}
Typed pattern
whatIsThis match { case n: Int => “aah, a number” case c: Character => “it’s ” + c.name}
Constructor pattern
unknownPerson match { case SuperHero(_, powers, Some(TonyStark)) => Some(powers) case _ => None}
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?”}
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”}
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”}
Constructor patternval powers = unknownPerson match { case SuperHero(_, powers, Some(TonyStark)) => Some(powers) case _ => None}
val firstPower = powers match { case Some(power :: rest) => power case _ => Genius}
Constructor patternval powers = unknownPerson match { case SuperHero(_, powers, Some(TonyStark)) => Some(powers) case _ => None}
val firstPower = powers match { case Some(power :: rest) => power case _ => Genius}
Constructor patternval powers = unknownPerson match { case SuperHero(_, powers, Some(TonyStark)) => Some(powers) case _ => None}
val firstPower = powers match { case Some(power :: rest) => power case _ => Genius}
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”}
Sequence pattern
powers match { case List(SuperStrength, _, _*) => “at least two”}
Pattern guard
aGuy match { case Civilian(_, Cash(money)) if cash >= 10000 => “Rich guy” case _ => “anybody else”}
Patterns everywhere
Variable definitionval (a, b) = someTupleval List(Flight, second, rest @ _*) = powersval Civilian(name, wealth: Cash) = clarkKent
Is this pattern matching, too?
val a = 3
Exceptions
try { doSomethingStupid()} catch { case e: IOException => … case e: SQLException => …}
Partial functionval numToStr: PartialFunction[Int, String] = { case 8 => “eight” case 10 => “ten”}
numToStr.isDefinedAt(12)
evaluating { numToStr(12)} should produce[??????????????]
For comprehensionsval lines = List( “1\t2,3\t3,12”, “2\t1,3\t3,15”, “3\t1,12\t2,15”)
val edges = for { line <- lines Array(srcNode, edges @ _*) = line split “\t” edge <- edges Array(destNode, length) = edge split “,”} yield Edge(srcNode.toInt, destNode.toInt, length.toInt)
For comprehensions. Beware!
val egos = for { hero : SuperHero <- characters // does not work} yield hero.alterEgo
val egos = for { hero @ (h : SuperHero) <- characters} yield hero.alterEgo
Extractors
Extractors
trait Person { def name: String def age: Int}
object Person { def unapply(person: Person): Option[(String, Int)] = Some((person.name, age))}
somePerson match { case Person(“Moses”, _) => 969 case Person(name, age) => age}
trait Person { def name: String def age: Int}
object Person { def unapply(person: Person): Option[(String, Int)] = Some((person.name, age))}
somePerson match { case Person(“Moses”, _) => 969 case Person(name, age) => age}
Case Classes
No need for val in parameters
case class Villain( val name: String, val archenemy: SuperHero) extends Character
No need for val in parameters
case class Villain( val name: String, val archenemy: SuperHero) extends Character
No need for new keyword
new Villain(“Mandarin”, tonyStark)
object Villain { def apply(name: String, archenemy: SuperHero) = new Villain(name, archenemy)}
No need for new keyword
new Villain(“Mandarin”, tonyStark)
object Villain { def apply(name: String, archenemy: SuperHero) = new Villain(name, archenemy)}
No need for new keyword
new Villain(“Mandarin”, tonyStark)
object Villain { def apply(name: String, archenemy: SuperHero) = new Villain(name, archenemy)}
equals and hashCodeval mandarin = Villain(“Mandarin”, tonyStark)
mandarin == Villain(“Mandarin”, tonyStark)
val villainRank = Map(mandarin -> 81)
Intuitive toString
TonyStark.toString == “Civilian(Tony Stark,Fortune)”
Handy copy method
val batman = SuperHero(“Batman”, List(Genius, Gadgets), Civilian(“Bruce Wayne”, Fortune))
val sixPack = batman.copy(powers = Nil)
…and pattern matching
How the heck ispattern matching done
for case classes?
Sealed classes
sealed trait Wealth
case class Cash(n: Int) extends Wealth
case object Fortune extends Wealth
Any questions?
Next meetup May 28, 2013Java 8• How does it compare to
Scala?• A closer look at λ-
expressions implementation• Influences on future
Scala versions, benefits for Scala developers
Scala 2.10• String Interpolation• Value Classes• Implicit Classes• Macros
Next coding dojo–May 14, 2013