Created
September 19, 2010 05:33
-
-
Save arnolddevos/586429 to your computer and use it in GitHub Desktop.
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
import Pattern._ | |
import Family._ | |
def pattern[B](pf: PartialFunction[Name,B]) = new Extractor(pf.lift) | |
val Parents = new Extractor(parents.get) | |
val Children = new Extractor(children.get) | |
"Julie" match { | |
case Parents(p) => "Julies parents are: " + p | |
case Children(c) => "Julies parents are unknown but has children: " + c | |
case _ => "Don't know any of Julie's relatives" | |
} | |
parents.get("Julie") map { p => "Julies parents are: " + p } getOrElse { | |
children.get("Julie") map { c => "Julies parents are unknown but has children: " + c } getOrElse { | |
"Don't know any of Julie's relatives" | |
} | |
} | |
"Nalda" match { | |
case Children(Children(c)) => "Nalda's grandchildren are: " + c | |
case Children(_) => "Nalda has children but no grandchildren" | |
case _ => "Nalda is childless" | |
} | |
val Female = pattern { case n if female contains n => n } | |
"Nalda" match { | |
case Children(Children(Female(d))) => "Nalda's granddaughters are: " + d | |
case Children(Children(_)) => "Nalda has grandchildren but no granddaughters" | |
case _ => "Nalda has no grandchildren" | |
} | |
val GrandChildren = pattern { case Children(Children(c)) => c } | |
val GrandDaughters = pattern { case GrandChildren(Female(c)) => c } | |
val Mother = pattern { case Parents(Female(p)) => p } | |
val Siblings = pattern { case self @ Parents(Children(siblings)) => siblings - self } | |
val Sisters = pattern { case Siblings(Female(s)) => s } | |
val Male = pattern { case n if male contains n => n } | |
val Brothers = pattern { case Siblings(Male(b)) => b } | |
"Julie" match { | |
case Brothers(_) & Sisters(_) => "Julie has both brother(s) and sister(s)" | |
case Siblings(_) => "Julie's siblings are all the same sex" | |
case _ => "Julie has no siblings" | |
} |
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
object Family { | |
type Name = String | |
type Assoc = Map[Name, Set[Name]] | |
val male = Set( "John", "David", "Peter", "Arnold", "Chris", "Craig", "James") | |
val female = Set( "Julie", "Lisa", "Nalda", "Pauline", "Annette", "Mel", "Candy", "Zoe", "Haley", "Katey" ) | |
val basis = Map( | |
Set("Nalda", "John") -> Set("Julie", "Lisa", "Arnold", "Annette", "Pauline"), | |
Set("Julie", "Adrian") -> Set("David"), | |
Set("Lisa", "Peter") -> Set("Mel", "Candy"), | |
Set("Pauline", "Chris") -> Set( "James", "Zoe"), | |
Set("Annette", "Craig") -> Set( "Haley", "Katey") | |
) | |
val children: Assoc = for( (ps, cs) <- basis; p <- ps ) yield p -> cs | |
val parents: Assoc = for( (ps, cs) <- basis; c <- cs ) yield c -> ps | |
} |
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
object Pattern { | |
class Extractor[A,B](f: A => Option[B]) { | |
def unapply( a: A) = f(a) | |
def unapply[C]( ta: Traversable[A])(implicit g: Flattener[B,C]): Option[C] = g(ta.view.map(f)) | |
object Pick { | |
def unapply( ta: Traversable[A]) = pick(ta)(f) | |
} | |
} | |
class Tester[A](p: A => Boolean) { | |
def unapply(a: A) = p(a) | |
def unapply(t: Traversable[A]) = t forall p | |
object Exists { | |
def unapply(t: Traversable[A]) = t exists p | |
} | |
} | |
object & { | |
def unapply[A](a: A) = Some(a, a) | |
} | |
object Select { | |
def unapply[A](t : Traversable[A]) = t.headOption | |
} | |
object Single { | |
def unapply[A](t : Traversable[A]) = if( t.size == 1 ) Some( t.head ) else None | |
} | |
trait Flattener[B,C] extends (Traversable[Option[B]] => Option[C]) | |
class DefaultFlattener { | |
implicit def defaultFlattener[B] = new Flattener[B,Traversable[B]] { | |
def apply( tb: Traversable[Option[B]]): Option[Traversable[B]] = nonEmpty(tb.flatten) | |
} | |
} | |
object Flattener extends DefaultFlattener { | |
implicit def flattenSets[E] = new Flattener[Set[E],Set[E]] { | |
def apply( tb: Traversable[Option[Set[E]]]): Option[Set[E]] = nonEmpty(tb.flatten.flatten.toSet) | |
} | |
} | |
def nonEmpty[T <: Traversable[_]]( t: T )= if( t isEmpty ) None else Some(t) | |
def pick[A,B](ta: Traversable[A])(f: A => Option[B]): Option[B] = { | |
for( a <- ta) { | |
val b = f(a) | |
if(b.isDefined) | |
return b | |
} | |
None | |
} | |
} |
That link has now moved to https://notes.backgroundsignal.com/Querying_a_Dataset_with_Scala_s_Pattern_Matching.html
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The explanation for these pattern constructors and combinators and the examples is here: http://notes.langdale.com.au/Querying_a_Dataset_with_Scala_s_Pattern_Matching.html