Created
October 21, 2010 06:35
-
-
Save ymnk/638058 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
Sample programs for "Querying a Dataset with Scala's Pattern Matching", which | |
is available at | |
http://notes.langdale.com.au/Querying_a_Dataset_with_Scala_s_Pattern_Matching.html | |
$ scalac *.scala | |
$ scala | |
Welcome to Scala version 2.8.0.final (Java HotSpot(TM) Client VM, Java 1.6.0_16). | |
Type in expressions to have them evaluated. | |
Type :help for more information. | |
scala> import TheFamily._ | |
import TheFamily._ | |
scala> ADatasetAndAQuery.check("Hisahito") | |
res0: String = Hisahito's parents are: Set(Kiko, Fumihito) | |
scala> |
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 TheFamily.{Name, parents, children} | |
object ADatasetAndAQuery { | |
class Extractor[A,B]( f: A => Option[B] ) { | |
def unapply( a: A ) = f(a) | |
} | |
val Parents = new Extractor(parents.get) | |
val Children = new Extractor(children.get) | |
val check: Name => String = { | |
case s@Parents(p) => "%s's parents are: %s".format(s, p) | |
case s@Children(c) => "%s's parents are unknown but has children: %s".format(s, c) | |
case s => "Don't know any of %s's relatives".format(s) | |
} | |
/* | |
def check(s: Name) = s match { | |
case Parents(p) => "%s's parents are: %s".format(s, p) | |
case Children(c) => "%s's parents are unknown but has children: %s".format(s, c) | |
case _ => "Don't know any of %s's relatives".format(s) | |
} | |
*/ | |
} |
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 TheFamily.Name | |
import CreatingALanguage.{Brothers, Sisters, Siblings} | |
object ConjunctionsAndDisjunctions { | |
object & { def unapply[A](a: A) = Some(a, a) } | |
val check3: Name => String = { | |
case s@(Brothers(_) & Sisters(_)) => | |
"%s has both brother(s) and sister(s)".format(s) | |
case s@Siblings(x) => | |
"%s's siblings are all the same sex %s".format(s, x) | |
case s => "%s has no siblings".format(s) | |
} | |
} |
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 TheFamily.{Name, parents, children, male, female} | |
import TraversalsAndFilters.{Extractor, Flattener} | |
object CreatingALanguage { | |
def pattern[B](pf: PartialFunction[Name,B]) = | |
new Extractor(pf.lift) | |
val Parents = new Extractor(parents.get) | |
val Children = new Extractor(children.get) | |
val Female = pattern { case n if female contains n => n } | |
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)) if(siblings.size != 1) => | |
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 } | |
} |
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 TheFamily { | |
type Name = String | |
val male: Set[Name] = | |
Set("Hirohito", | |
"Akihito", "Masahito", | |
"Naruhito", "Fumihito", | |
"Hisahito") | |
val female: Set[Name] = | |
Set("Nagako", | |
"Michiko", "Shigeko", "Sachiko", "Atsuko", "Takako", | |
"Sayako", "Masako", "Kiko", | |
"Aiko", "Mako", "Kako") | |
val children: Map[Name, Set[Name]] = | |
Map("Hirohito" -> Set("Shigeko", "Sachiko", "Atsuko", | |
"Akihito", "Masahito", "Takako"), | |
"Nagako" -> Set("Shigeko", "Sachiko", "Atsuko", | |
"Akihito", "Masahito", "Takako"), | |
"Akihito" -> Set("Naruhito", "Fumihito", "Sayako"), | |
"Michiko" -> Set("Naruhito", "Fumihito", "Sayako"), | |
"Naruhito" -> Set("Aiko"), | |
"Masako" -> Set("Aiko"), | |
"Fumihito" -> Set("Mako", "Kako", "Hisahito"), | |
"Kiko" -> Set("Mako", "Kako", "Hisahito")) | |
private val empty = Map.empty[Name, Set[Name]] | |
private def invert(s: Map[Name, Set[Name]]) = s.foldLeft(empty){ | |
case (m, (key, set)) => | |
set.foldLeft(m){ (m, s) => | |
m + (s -> (m.get(s).getOrElse(Set.empty[Name])+key)) | |
} | |
} | |
val parents: Map[Name, Set[Name]] = invert(children) | |
} |
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 TheFamily.{Name, parents, children, male, female} | |
object TraversalsAndFilters { | |
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)) | |
} | |
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) | |
} | |
} | |
private def nonEmpty[T <: Traversable[_]]( t: T ) = | |
if( t isEmpty ) None else Some(t) | |
val Parents = new Extractor(parents.get) | |
val Children = new Extractor(children.get) | |
def check2: Name => String = { | |
case s@Children(Children(c)) => | |
"%s's grandchildren are: %s".format(s, c) | |
case s@Children(_) => | |
"%s has children but no grandchildren".format(s) | |
case s => | |
"%s is childless".format(s) | |
} | |
val Female = new Extractor((s:Name) => female.find(s == )) | |
def check3: Name => String = { | |
case s@Children(Children(Female(d))) => | |
"%s's granddaughters are: %s".format(s, d ) | |
case s@Children(Children(_)) => | |
"%s has grandchildren but no granddaughters".format(s) | |
case s => | |
"%s has no grandchildren".format(s) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment