Skip to content

Instantly share code, notes, and snippets.

@rirakkumya
Created May 2, 2012 08:48
Show Gist options
  • Save rirakkumya/2575219 to your computer and use it in GitHub Desktop.
Save rirakkumya/2575219 to your computer and use it in GitHub Desktop.
羊さんコード
case class Sheep(name:String,father:Option[Sheep],mother:Option[Sheep])
object SampleBase {
def father(sheep:Sheep):Option[Sheep] = sheep match {
case Sheep(_, s, _) => s
case _ => None
}
def mother(sheep:Sheep):Option[Sheep] = sheep match {
case Sheep(_, _, s) => s
case _ => None
}
}
object Sample1 {
import SampleBase._
def maternalGrandfather(sheep:Sheep):Option[Sheep] = mother(sheep) match {
case None => None
case Some(s) => father(s)
}
def mothersPaternalGrandfather(sheep:Sheep):Option[Sheep] = mother(sheep) match {
case None => None
case Some(s) => father(s) match {
case None => None
case Some(ss) => father(ss)
}
}
}
object Sample2 {
import SampleBase._
case class Comb[a](x:Option[a]) {
def comb[b](f:a => Option[b]):Option[b] = x flatMap f
}
implicit def sheep2Comb(s:Option[Sheep]):Comb[Sheep] = Comb(s)
def mothersPaternalGrandfather(sheep:Sheep):Option[Sheep] =
Option(sheep) comb mother comb father comb father
}
object Main extends App {
val first = Sheep("1st",None,None)
val second = Sheep("2nd",Some(first),None)
val third = Sheep("3rd",Some(first),Some(second))
val fourth = Sheep("4th",Some(second),Some(third))
val fifth = Sheep("5th",Some(third),Some(fourth))
for { s <- Sample1.maternalGrandfather(fifth) } assert(s.name == "2nd",s)
for { s <- Sample1.mothersPaternalGrandfather(fifth) } assert(s.name == "1st",s)
for { s <- Sample2.mothersPaternalGrandfather(fifth) } assert(s.name == "1st",s)
}
@rirakkumya
Copy link
Author

@xuwei-k
Copy link

xuwei-k commented May 4, 2012

単にこの場合に短く書くとしたら

case class Sheep(name:String,father:Option[Sheep],mother:Option[Sheep])

def maternalGrandfather(sheep:Sheep):Option[Sheep] = {
  sheep.mother.flatMap{_.father}
}

def mothersPaternalGrandfather(sheep:Sheep):Option[Sheep] = {
  sheep.mother.flatMap{_.father.flatMap{_.father}}
}

とかですかね

@rirakkumya
Copy link
Author

なるほど。その方が処理が分かりやすく、パフォーマンスの面でも有利ですね。

今思ったんですが、macroを使えばもう少しすっきり書けるような気がします。
例えば

nest"sheep.mother >> father >> father"

sheep.mother.flatMap{_.father.flatMap{_.father}}

に変換するのはどうでしょう。
nest型のcase classで汎用的に使えそうです。
文字リテラルなのでIDEの補完が効かないのは致命的ですが…

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