Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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

This comment has been minimized.

Copy link
Owner Author

@arnolddevos arnolddevos commented Sep 19, 2010

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

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.