Created
May 1, 2011 06:24
-
-
Save srogalsky/950295 to your computer and use it in GitHub Desktop.
Complete code from Derek's Pattern Matching presentation with some implicits thrown in to clean up the output. Scala in 2 Days Meetup - Boulder, CO, April 2011
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package PatternMatching | |
import scala.Predef._ | |
object MatchingExamples { | |
def main(args: Array[String]) { | |
// Some implicits thrown in to print the outputs | |
trait NicePrinting { | |
def printNiceHeading() : Unit | |
def printIndented(IndentedSpaces : Int = 2) : Unit | |
} | |
implicit def stringToNicePrinting(s : String ) = new NicePrinting { | |
def printNiceHeading() = { | |
println("") | |
println(s) | |
for (i <- 1 to s.length) | |
print("-") | |
println("") | |
} | |
def printIndented(indentedSpaces : Int = 2) = { | |
for (i <- 1 to indentedSpaces) | |
print(" ") | |
println(s) | |
} | |
} | |
// Basic Matching (notice that the "." isn't required in printNiceHeading) | |
"Basic Matching" printNiceHeading() | |
var foo: Int = 6 | |
val result = foo match { | |
case 1 => "one".printIndented() | |
case 2 => "two".printIndented() | |
case _ => "lemon curry?".printIndented() | |
} | |
// Match against broader range of types | |
"Type Matching".printNiceHeading() | |
def literalMatch (in: Any) = in match { | |
case 1 => "One" | |
case "test" => "test" | |
case 'x' => "x" | |
case 2.2f => "float" | |
case _ => "lemon curry?" | |
} | |
literalMatch(foo).printIndented() | |
literalMatch("test").printIndented() | |
literalMatch('x').printIndented() | |
literalMatch(foo).printIndented() | |
// Alternate Matching | |
"Alternate Matching".printNiceHeading() | |
def literalMatch2 (in: Any) = in match { | |
case 1 | 2 | 3 => "One Two Three" | |
case "this" | "that" => "test" | |
case _ => "lemon curry?" | |
} | |
literalMatch2(2).printIndented() | |
literalMatch2("2").printIndented() | |
//Binding in Matching | |
"Binding in Matching".printNiceHeading() | |
def literalMatch3 (in: Any) = in match { | |
case n @ (1 | 2 | 3) => "1-3 " + n | |
case t @ ("this" | "that") => t + " and the other" | |
case x => "We defaulted on " + x | |
} | |
literalMatch3(1).printIndented() | |
literalMatch3("hi").printIndented() | |
literalMatch3("this").printIndented() | |
//Matching on Type | |
"Matching on Type".printNiceHeading() | |
def typeMatch (in: Any) = in match { | |
case i: Int => "Int : " + i | |
case s: String => s | |
case _ => "(none)" | |
} | |
typeMatch(5).printIndented() | |
typeMatch("hello").printIndented() | |
typeMatch(5.0).printIndented() | |
//Fine Grained Matching | |
"Fine Grained Matching".printNiceHeading() | |
def typeMatch2 (in: Any) = in match { | |
case i: Int if i % 2 == 0 => "Its even!" | |
case s: String if s.startsWith("Scala") => "Its scala!" | |
case _ => "(none)" | |
} | |
typeMatch2(1).printIndented() | |
typeMatch2(200).printIndented() | |
typeMatch2("Scala is great").printIndented() | |
typeMatch2("I like Scala").printIndented() | |
//Matching against case classes | |
"Matching against cases in an object".printNiceHeading() | |
def areYouDead(c: Character) = c match { | |
case Character("Fred", health) if health <= 0 => "Gotcha Fred - you're dead" | |
case Character(name, health) if health <= 0 => name + " is dead" | |
case Character(name, health) if health <= 10 => "You are almost dead " + name | |
case Character(name, _) => name + " is alive and in good health" | |
} | |
areYouDead(new Character("Fred", 1)).printIndented() | |
areYouDead(new Character("Fred", 0)).printIndented() | |
areYouDead(new Character("Bob", 0)).printIndented() | |
areYouDead(new Character("Bob", 9)).printIndented() | |
areYouDead(new Character("Bob", 10)).printIndented() | |
areYouDead(new Character("Bob", 11)).printIndented() | |
areYouDead(new Character("Bob", -1)).printIndented() | |
//Extraction as General Concept | |
"Extractions, Options, Some, None".printNiceHeading() | |
def extraction[A](in : Option[A]) = in match{ | |
case Some(Creature("Fred", None)) => "Fred has no magic" | |
case Some(Creature(name, None)) => name + " has no magic!" | |
case Some(Creature(name, _)) => name + " has magic!" | |
case Some(_) => "Not a creature" | |
case None => "Nothing!" | |
} | |
extraction(Some(new Creature("Fred", None))).printIndented() | |
extraction(Some(new Creature("Fred", Some(2)))).printIndented() | |
extraction(Some(new Creature("Bob", Some(3)))).printIndented() | |
extraction(Some(new Creature("Bob", None))).printIndented() | |
// Match Sequences | |
"Match Sequences".printNiceHeading() | |
def matchSequences(in : List[Creature]) = in match { | |
case singleton :: Nil => singleton.name | |
case one :: two :: others if others.size == 1 => "%s and %s and %d other".format(one.name, two.name, others.size) | |
case one :: two :: others => "%s and %s and %d others".format(one.name, two.name, others.size) | |
case _ => "No magical creatures" | |
// Note: others is *not* a key word - it gets the rest of the list. others.name would not compile | |
} | |
val characterFred = new Creature("Fred", None) | |
val characterBob = new Creature("Bob", Some(1)) | |
val characterHenry = new Creature("Henry", Some(2)) | |
val characterGeorge = new Creature("George", None) | |
matchSequences(characterFred :: Nil).printIndented() | |
matchSequences(characterFred :: characterBob :: Nil).printIndented() | |
matchSequences(characterFred :: characterBob :: characterHenry :: Nil).printIndented() | |
matchSequences(characterFred :: characterBob :: characterHenry :: characterGeorge :: Nil).printIndented() | |
// Patterns can nest | |
"Paterns can Nest".printNiceHeading() | |
def soloMagicCreatures(locations : List[Location]) = { | |
locations.flatMap { | |
// Looks for any location with only one magical creature and returns a list of those creatures | |
case Location(_, List(c @ Creature(_,Some(_)))) => c :: Nil | |
case _ => Nil | |
} | |
} | |
val locationDungeon = new Location("Dungeon", characterBob :: Nil) // 1 magical creature | |
val loneCreatures = soloMagicCreatures(locationDungeon :: Nil) | |
matchSequences(loneCreatures).printIndented() | |
val locationCastle = new Location("Castle", characterFred :: characterGeorge :: Nil) // 2 creatures, one magical | |
val locationGarden = new Location("Garden", characterHenry :: Nil) // 1 magical creature | |
val locationStable = new Location("Stable", characterFred :: characterGeorge :: Nil) | |
val loneCreatures2 = soloMagicCreatures(locationDungeon :: locationCastle :: locationStable :: locationGarden :: Nil) | |
matchSequences(loneCreatures2).printIndented() // Should print out Bob and Henry | |
} | |
case class Character(name: String, health : Int) | |
case class Creature(name: String, magicalAttack: Option[Int]) | |
case class Location(name : String, creatures: List[Creature]) | |
} |
You are too kind - thanks. Give some thought to presenting pattern matching up here in October - then I can buy you a beer instead!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Steve, you rock! Any time you feel like driving 18 hours down to Boulder again I'm going to have to take you out for a beer ;)