Scala DSL

                2010 5       18
                         (    Lab)




2010   5   18
Scala

       •


       •


       •


       •


       • JVM          Java


       • Scalable ≒ DSL


2010   5   18
DSL

       • Domain Specific Language


       •


       •


       •


       • OSMU (One Source Multi Use)




2010   5   18
Scala DSL




2010   5   18
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
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
SimpleModeler




2010   5   18
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
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
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
DSL




2010   5   18
class MyTodo extends Todo {
             name = "         "
            }



           abstract class Todo {
             var name: String = _
           }



2010   5   18
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
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)
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
class MyTodo extends Todo {
        name = "         "

           "                         " until 20100505
           "                         " until 20100606
           "                " until 20100707

           task("               ") {
               todo("PC                  ")
               "IDE                  " until 20100707
           }
       }




2010   5       18
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
class MyTodo extends Todo {
            name = "         "

               "                            " until 20100505
               "                            " until 20100606
               "                      " until 20100707

               task("                     ") {
                   until = 20100808
                   todo("PC                      ")
                   "IDE                      " until 20100707
               }
           }




2010   5       18
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
2010   5   18
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
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
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
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
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
•          •


       •          •


           •      • XML


           •      •


       • apply    •       (2.8)


       • update   •         (2.8)



2010   5   18
• DSL              Scala


       • Scala     Java           …


           •


       • Scala DSL


           •


       •         Scala



2010   5   18
End




2010   5   18

Scala DSLの作り方

  • 1.
    Scala DSL 2010 5 18 ( Lab) 2010 5 18
  • 2.
    Scala • • • • • JVM Java • Scalable ≒ DSL 2010 5 18
  • 3.
    DSL • Domain Specific Language • • • • OSMU (One Source Multi Use) 2010 5 18
  • 4.
  • 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.
    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.
  • 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.
    class MyTodo extendsTodo { • 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.
    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.
  • 12.
    class MyTodo extendsTodo { name = " " } abstract class Todo { var name: String = _ } 2010 5 18
  • 13.
    class MyTodo extendsTodo { 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.
    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.
    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.
    class MyTodo extendsTodo { name = " " " " until 20100505 " " until 20100606 " " until 20100707 task(" ") { todo("PC ") "IDE " until 20100707 } } 2010 5 18
  • 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.
    class MyTodo extendsTodo { name = " " " " until 20100505 " " until 20100606 " " until 20100707 task(" ") { until = 20100808 todo("PC ") "IDE " until 20100707 } } 2010 5 18
  • 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.
    2010 5 18
  • 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.
    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.
    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.
    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.
    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.
    • • • • • XML • • • apply • (2.8) • update • (2.8) 2010 5 18
  • 27.
    • DSL Scala • Scala Java … • • Scala DSL • • Scala 2010 5 18
  • 28.