Skip to content

Instantly share code, notes, and snippets.

@srogalsky
Created May 1, 2011 06:24
Show Gist options
  • Save srogalsky/950295 to your computer and use it in GitHub Desktop.
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
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])
}
@dchenbecker
Copy link

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 ;)

@srogalsky
Copy link
Author

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