Skip to content

Instantly share code, notes, and snippets.

@arnolddevos
Created September 19, 2010 05:33
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save arnolddevos/586429 to your computer and use it in GitHub Desktop.
Save arnolddevos/586429 to your computer and use it in GitHub Desktop.
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"
}
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
}
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
}
}
@arnolddevos
Copy link
Author

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

@mjhopkins
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment