Skip to content

Instantly share code, notes, and snippets.

@sndyuk
Created June 26, 2012 02:58
Show Gist options
  • Save sndyuk/2992994 to your computer and use it in GitHub Desktop.
Save sndyuk/2992994 to your computer and use it in GitHub Desktop.
Scalaでタスク管理DSL
package trampoline
import java.text.SimpleDateFormat
import java.util.Date
/**
* Simple Unit test DSL.
*/
class UnitTestContext(val limit: Date)
class UnitTestDsl
object UnitTestDsl {
val dateFormat = new SimpleDateFormat("yyyy/MM/dd")
implicit def toTask[C](task: Bearer[C] => Bearer[C]) = new Task[C] { val f = task }
implicit def limitToContext(limit: String) = new UnitTestContext(dateFormat.parse(limit))
import Specs._
def main(args: Array[String]) {
// --- Test cases
(`開発環境を整える` << "2012/03/09")(
(`PCをインストールする` ~ `IDEをインストールする`) < "2012/01/07",
(`コーヒータイム`) < "2012/02/01",
(`ひたすら待つ`) < "2012/02/03",
(`開発環境を整える` << "2012/02/05")(
(`PCをインストールする` ~ `IDEをインストールする`) < "2012/02/07",
(`ひたすら待つ`) < "2012/03/03",
(`コーヒータイム` << "2012/03/04")(
(`コーヒータイム` ~ `ひたすら待つ`~ `コーヒータイム`) < "2012/03/05",
(`コーヒータイム`) < "2012/03/06",
(`ひたすら待つ`) < "2012/03/07"
)
)
) run ("2012/03/10")
}
}
object Specs {
val `開発環境を整える` = (bearer: Bearer[UnitTestContext]) => {
println("開発環境を整える: unitl " + bearer.context.limit + ", celler limit: " + bearer.celler.limit)
"""
"""
bearer
}
val `PCをインストールする` = (bearer: Bearer[UnitTestContext]) => {
println("PCをインストールする: unitl " + bearer.context.limit + ", celler limit: " + bearer.celler.limit)
"""
"""
bearer
}
val `IDEをインストールする` = (bearer: Bearer[UnitTestContext]) => {
println("IDEをインストールする: unitl " + bearer.context.limit + ", celler limit: " + bearer.celler.limit)
"""
"""
bearer
}
val `ひたすら待つ` = (bearer: Bearer[UnitTestContext]) => {
println("ひたすら待つ: unitl " + bearer.context.limit + ", celler limit: " + bearer.celler.limit)
"""
"""
bearer
}
val `コーヒータイム` = (bearer: Bearer[UnitTestContext]) => {
println("コーヒータイム: unitl " + bearer.context.limit + ", celler limit: " + bearer.celler.limit)
"""
"""
bearer
}
}
// ---
class Bearer[C](val context: C, val celler: C)
trait Task[C] {
val f: Bearer[C] => Bearer[C]
def ~[A](g: Bearer[C] => A): Bearer[C] => A = f andThen g
def <(c: C) = new Tasks[C] {
val context = c
val task = Option(f)
val sub = Nil
}
def <<(c: C)(s: Tasks[C]*) = new Tasks[C] {
val context = c
val task = Option(f)
val sub = s.toList
}
}
trait Tasks[C] {
val context: C
val task: Option[Bearer[C] => Bearer[C]]
val sub: List[Tasks[C]]
final def run(c: C): Unit = {
var celler: C = c
task.foreach(_.apply(new Bearer(context, celler)))
celler = context
val s = new scala.collection.mutable.Queue[Tasks[C]]
s ++= sub
while (!s.isEmpty) {
val t = s.dequeue
t.task.foreach(
_.apply(new Bearer(t.context, celler))
)
celler = t.context
s ++= (t.sub.flatMap { v =>
v.task.foreach { vt =>
vt.apply(new Bearer(v.context, celler))
celler = v.context
}
v.sub
})
}
}
}
@sndyuk
Copy link
Author

sndyuk commented Jun 26, 2012

実行結果
$ scala UnitTestDsl
$ test
$ PCをインストールする: unitl Sun Jan 01 00:00:00 JST 2012
$ DEをインストールする: unitl Sun Jan 01 00:00:00 JST 2012

@sndyuk
Copy link
Author

sndyuk commented Jun 26, 2012

タスクをnestできるようにした

実行結果
$ 開発環境を整える: unitl Mon Mar 05 00:00:00 JST 2012
$ PCをインストールする: unitl Sat Jan 07 00:00:00 JST 2012
$ IDEをインストールする: unitl Sat Jan 07 00:00:00 JST 2012
$ ひたすら待つ: unitl Sat Mar 03 00:00:00 JST 2012

@sndyuk
Copy link
Author

sndyuk commented Jun 26, 2012

Tasks#runメソッドを末尾再帰最適化できない…誰か...

@sndyuk
Copy link
Author

sndyuk commented Jun 26, 2012

Task#untilAllの引数に可変長引数で渡してるけど、

  (`PCをインストールする` ~ `IDEをインストールする`) until "2012/01/07",
  (`ひたすら待つ`) until "2012/03/03"

カンマ区切りはカッコ悪いので、こんな感じのDSLにしたい。

  (`PCをインストールする` ~ `IDEをインストールする`) until "2012/01/07" |
  (`ひたすら待つ`) until "2012/03/03"

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