Scala DSLの作り方

5,979 views

Published on

JJUG CCC 2010 Spring

Published in: Technology, Business
0 Comments
15 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,979
On SlideShare
0
From Embeds
0
Number of Embeds
109
Actions
Shares
0
Downloads
60
Comments
0
Likes
15
Embeds 0
No embeds

No notes for slide

Scala DSLの作り方

  1. 1. Scala DSL 2010 5 18 ( Lab) 2010 5 18
  2. 2. Scala • • • • • JVM Java • Scalable ≒ DSL 2010 5 18
  3. 3. DSL • Domain Specific Language • • • • OSMU (One Source Multi Use) 2010 5 18
  4. 4. Scala DSL 2010 5 18
  5. 5. Specs object CsvEntityTest extends Specification { • BDD val TestReadDir = "/tmp/goldenport.d/read" val TestCreateDir = "/tmp/goldenport.d/create/CsvEntity" • Behavior Driven val readonlyCsvFileName = GoldenportTestUtility.readonlyCsvFileName Development "CsvEntity Read" should { "CsvEntity DefaultEntitySpace FileDataSource open" in { • val space = new DefaultEntitySpace space.addEntityClass(new CsvEntityClass()) val datasource = new FileDataSource(readonlyCsvFileName, space.context) val mayCsv: Option[GEntity] = space.reconstitute(datasource) mayCsv must beSome[GEntity] val csv = mayCsv.get.asInstanceOf[CsvEntity] csv.open() csv.width must be(3) csv.height must be(2) csv.get(0, 0) must be_==("A") • Specs csv.get(1, 0) must be_==("B") csv.get(2, 0) must be_==("C") csv.get(0, 1) must be_==("X") csv.get(1, 1) must be_==("Y") • Scala csv.get(2, 1) must be_==("Z") csv.close() } 2010 5 18
  6. 6. SimpleModeler case class DER extends DomainResource { • DSL term = " " caption = " " brief = <t></t> description = <text></text> • Scala DSL id(" Id", DVI Id()) attribute(" Name", DVN Name()) } Google App case class DVI Id extends DomainValueId { Engine Java term = " Id" caption = " Id" brief = <t></t> description = <text></text> attribute("value", XString) } 2010 5 18
  7. 7. SimpleModeler 2010 5 18
  8. 8. g3 • class Join extends G3Application { agent('compute) { case x: Int => x + 100 • Scala DSL } start(List(1, 2, 3, 4, 5)) split() publish("compute") join() aggregate() } 2010 5 18
  9. 9. class MyTodo extends Todo { • TODO name = " " Scala DSL " " until 20100505 • Scala DSL HTML " " until 20100606 " " until 20100707 task(" ") { until = 20100808 todo("PC ") "IDE " until 20100707 } } 2010 5 18
  10. 10. DSL HTML <html> <head> <title>TODO </title> </head> <body> <ul> <li> (20100505)</li> <li> (20100606)</li> <li> (20100707)</li> <li>PC (20100808) [ ]</li> <li>IDE (20100808) [ ]</li> </ul> </body> </html> 2010 5 18
  11. 11. DSL 2010 5 18
  12. 12. class MyTodo extends Todo { name = " " } abstract class Todo { var name: String = _ } 2010 5 18
  13. 13. class MyTodo extends Todo { name = " " import scala.collection.mutable.ArrayBuffer todo(" ") todo(" ") abstract class Todo { var name: String = _ todo(" ") val items = new ArrayBuffer[TodoItem] } def todo(title: String) { val item = new TodoItem(title) items += item } } class TodoItem(val title: String) { } 2010 5 18
  14. 14. import scala.collection.mutable.ArrayBuffer class MyTodo extends Todo { name = " " abstract class Todo { var name: String = _ val items = new ArrayBuffer[TodoItem] todo(" ") until 20100505 def todo(title: String): TodoItem = { todo(" ") until 20100606 val item = new TodoItem(title) todo(" ") until 20100707 items += item item } } } class TodoItem(val title: String) { var untilDate: Int = _ def until(date: Int): TodoItem = { untilDate = date this } } 2010 5 18 (fluent interface)
  15. 15. import scala.collection.mutable.ArrayBuffer class MyTodo extends Todo { name = " " abstract class Todo { var name: String = _ val items = new ArrayBuffer[TodoItem] " " until 20100505 def todo(title: String): TodoItem = { " " until 20100606 val item = new TodoItem(title) items += item " " until 20100707 item } } implicit def todoWrapper(title: String): TodoItem = todo(title) } class TodoItem(val title: String) { var untilDate: Int = _ def until(date: Int): TodoItem = { untilDate = date this } } 2010 5 18
  16. 16. class MyTodo extends Todo { name = " " " " until 20100505 " " until 20100606 " " until 20100707 task(" ") { todo("PC ") "IDE " until 20100707 } } 2010 5 18
  17. 17. import scala.collection.mutable.ArrayBuffer class TodoItem(var title: String) { abstract class Todo { var untilDate: Int = _ var name: String = _ val items = new ArrayBuffer[TodoItem] def until(date: Int): TodoItem = { val tasks = new ArrayBuffer[Task] untilDate = date private[this] var currentTask: Option[Task] = None this } def todo(title: String): TodoItem = { } val item = new TodoItem(title) currentTask match { class Task(var title: String) { case Some(tk) => tk.items += item val items = new ArrayBuffer[TodoItem] case None => items += item var untilDate: Int = _ } } item } def task(title: String)(p: => Unit): Task = { val tk = new Task(title) tasks += tk currentTask = Some(tk) p currentTask = None tk } implicit def todoWrapper(title: String): TodoItem = todo(title) } 2010 5 18 Stack
  18. 18. class MyTodo extends Todo { name = " " " " until 20100505 " " until 20100606 " " until 20100707 task(" ") { until = 20100808 todo("PC ") "IDE " until 20100707 } } 2010 5 18
  19. 19. import scala.collection.mutable.ArrayBuffer def until: Int = { abstract class Todo { currentTask.get.untilDate var name: String = _ } val items = new ArrayBuffer[TodoItem] val tasks = new ArrayBuffer[Task] def until_=(value: Int) { private[this] var currentTask: Option[Task] = None currentTask.get.untilDate = value } def todo(title: String): TodoItem = { val item = new TodoItem(title) implicit def todoWrapper(title: String): TodoItem = todo(title) currentTask match { } case Some(tk) => tk.items += item case None => items += item class TodoItem(var title: String) { } var untilDate: Int = _ item } def until(date: Int): TodoItem = { untilDate = date def task(title: String)(p: => Unit): Task = { this val tk = new Task(title) } tasks += tk } currentTask = Some(tk) p class Task(var title: String) { currentTask = None val items = new ArrayBuffer[TodoItem] tk var untilDate: Int = _ } } this } } 2010 5 18
  20. 20. 2010 5 18
  21. 21. MakeTodoDsl import scala.xml.{XML, Node} private def makeList(todo: Todo): List[Node] = { object MakeTodoDsl { (for (item <- todo.items) yield <li>{ def main(args: Array[String]) { "%s(%s)".format(item.title, item.untilDate) val input = args(0) }</li>).toList ::: val output = args(1) (for (task <- todo.tasks; item <- task.items) yield <li>{ "%s(%s) [%s]".format(item.title, task.untilDate, task.title) val appClass = Class.forName(input) }</li>).toList val todo = appClass.newInstance.asInstanceOf[Todo] } } val html = <html> <head> <title>TODO </title> </head> <body> <ul> { makeList(todo) } </ul> </body> </html> XML.save(output, html, "utf-8") } 2010 5 18
  22. 22. def main(args: Array[String]) { val input = args(0) val output = args(1) val appClass = Class.forName(input) val todo = appClass.newInstance.asInstanceOf[Todo] 2010 5 18
  23. 23. XML val html = <html> <head> <title>TODO </title> </head> <body> <ul> { makeList(todo) } </ul> </body> </html> XML.save(output, html, "utf-8") } 2010 5 18
  24. 24. private def makeList(todo: Todo): List[Node] = { (for (item <- todo.items) yield <li>{ "%s(%s)".format(item.title, item.untilDate) }</li>).toList ::: (for (task <- todo.tasks; item <- task.items) yield <li>{ "%s(%s) [%s]".format(item.title, task.untilDate, task.title)}</li> ).toList } 2010 5 18
  25. 25. DSL HTML <html> • <head> <title>TODO </title> </head> <body> <ul> <li> (20100505)</li> <li> (20100606)</li> <li> (20100707)</li> <li>PC (20100808) [ ]</li> <li>IDE (20100808) [ ]</li> </ul> </body> </html> 2010 5 18
  26. 26. • • • • • • XML • • • apply • (2.8) • update • (2.8) 2010 5 18
  27. 27. • DSL Scala • Scala Java … • • Scala DSL • • Scala 2010 5 18
  28. 28. End 2010 5 18

×