scala essentials - pattern matching and case classes

Post on 01-Sep-2014

4.719 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

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.

TRANSCRIPT

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

top related