Domain Specific Languages #DUSE-3
Peter Maas  ~ Developer at Ebay Classifieds, working at the Marktplaats.nl migration. Likes programming languages. whoami
Agenda <ul><li>What is a DSL?
What makes Scala a good language for DSLs
Internal DSL
External DSL </li></ul>ACTUAL CODE!
Questions? Feel free to interrupt!
So, what is a DSL <ul>a  D omain- S pecific  L anguage (DSL) is a programming language or specification language dedicated...
A language which feels natural to a specialist in the targeted domain
Internal / External <ul><li>Internal DSLs are built using the language itself. </li><ul><li>Buildr
Gradle
Routing configuration in Apache Camel </li></ul><li>External DSLs are 'mini' programming languages with their own compiler...
Velocity </li></ul></ul>
Why is Scala good at that <ul><li>Concise and tolerant syntax
Function objects (closures, currying etc)
Default arguments
Operator overloading
Implicit conversions
Upcoming SlideShare
Loading in …5
×

Domain Specific Languages In Scala Duse3

2,876 views

Published on

Presentation on creating DSLs with Scala 2.8 which I presented at the Dutch Scala Enthousiasts meeting at Ebay/Marktplaats

Published in: Technology
  • Be the first to comment

Domain Specific Languages In Scala Duse3

  1. 1. Domain Specific Languages #DUSE-3
  2. 2. Peter Maas ~ Developer at Ebay Classifieds, working at the Marktplaats.nl migration. Likes programming languages. whoami
  3. 3. Agenda <ul><li>What is a DSL?
  4. 4. What makes Scala a good language for DSLs
  5. 5. Internal DSL
  6. 6. External DSL </li></ul>ACTUAL CODE!
  7. 7. Questions? Feel free to interrupt!
  8. 8. So, what is a DSL <ul>a D omain- S pecific L anguage (DSL) is a programming language or specification language dedicated to a particular problem domain, a particular problem representation technique, and/or a particular solution technique. </ul>
  9. 9. A language which feels natural to a specialist in the targeted domain
  10. 10. Internal / External <ul><li>Internal DSLs are built using the language itself. </li><ul><li>Buildr
  11. 11. Gradle
  12. 12. Routing configuration in Apache Camel </li></ul><li>External DSLs are 'mini' programming languages with their own compiler/interpreter </li><ul><li>SQL
  13. 13. Velocity </li></ul></ul>
  14. 14. Why is Scala good at that <ul><li>Concise and tolerant syntax
  15. 15. Function objects (closures, currying etc)
  16. 16. Default arguments
  17. 17. Operator overloading
  18. 18. Implicit conversions
  19. 19. Built-in support for building parsers
  20. 20. Due to it's functional nature it is good at handling syntax trees. </li></ul>
  21. 21. Concise? val toGreet = &quot; Marktplaats developers&quot;  &quot;Hello&quot; . + ( toGreet )   &quot;Hello&quot; + toGreet   &quot;Hello&quot; . concat ( toGreet ) &quot;Hello&quot; concat toGreet   // methods are objects...   val greetMethod = &quot;hello %s&quot;.format(_:String) greetMethod(toGreet)
  22. 22. Implicit conversions class StringReducer(s:String) { def acronym = s.filter(_.isUpper) } implicit def string2StringReducer(s:String) = new StringReducer(s) &quot;Sun Certified Java Programmer&quot;.acronym == &quot;SCJP&quot;
  23. 23. Or... case class Route(source:String, target:String) class RouteBuilder(s:String) { def --> (target:String) = Route(s, target) } implicit def string2Route(s:String) = new RouteBuilder(s) &quot;a&quot; --> &quot;b&quot; == Route( &quot;a&quot; , &quot;b&quot; )
  24. 24. Let's build a DSL we all know SQL http://github.com/p3t0r/scala-sql-dsl
  25. 25. Pure Scala // Simple query with sorting SQL select &quot;*&quot; from (&quot;user&quot;) order Asc(&quot;name&quot;) // More complex query with and/or including precedence SQL select &quot;*&quot; from (&quot;user&quot;) where ((&quot;name&quot;,&quot;peter&quot;) and ((&quot;active&quot;, true) or (&quot;role&quot;, &quot;admin&quot;))) Overriding the '=' operator was a no-go ;-)
  26. 26. Syntax Tree
  27. 27. case class Where( val clauses: Clause*) trait Clause { def and (otherField: Clause): Clause = And(this, otherField) def or (otherField: Clause): Clause = Or(this, otherField) } case class StringEquals(val f: String, val value: String) extends Clause case class NumberEquals(val f: String, val value: Number) extends Clause case class BooleanEquals(val f: String, val value: Boolean) extends Clause case class In(val field: String, val values: String*) extends Clause case class And(val lClause:Clause, val rClause:Clause) extends Clause case class Or(val lClause:Clause, val rClause:Clause) extends Clause AST for the Where clause
  28. 28. Some Implicits & Helpers object QueryBuilder { implicit def tuple2field(t: (String, String)): StringEquals = StringEquals(t._1, t._2) implicit def tuple2field(t: (String, Int)): NumberEquals = NumberEquals(t._1, t._2) implicit def tuple2field(t: (String, Boolean)): BooleanEquals = BooleanEquals(t._1, t._2) implicit def from2query(f: From): Query = Query(f.operation.get, f, Option(Where())) /** entrypoint for starting a select query */ def select(fields:String*) = Select(fields:_*) def select(symbol: Symbol): Select = symbol match { case 'all => select(&quot;*&quot;) case _ => throw new RuntimeException(&quot;Only 'all allowed as symbol&quot;) } def in(field: String, values: String*) = In(field, values: _*) }
  29. 29. That looks like a lot of code :( The entire builder is only 54 lines, including whitespace and comments! >> CONTINUE IN IDEA <<
  30. 30. And external? class SQLParser extends JavaTokenParsers { def query:Parser[Query] = operation ~ from ~ opt(where) ~ opt(order) ^^ { case operation ~ from ~ where ~ order => Query(operation, from, where, order) } def operation:Parser[Operation] = { (&quot;select&quot; | &quot;update&quot; | &quot;delete&quot;) ~ repsep(ident, &quot;,&quot;) ^^ { case &quot;select&quot; ~ f => Select(f:_*) case _ => throw new IllegalArgumentException(&quot;Operation not implemented&quot;) } } def from:Parser[From] = &quot;from&quot; ~> ident ^^ (From(_)) def where:Parser[Where] = &quot;where&quot; ~> rep(clause) ^^ (Where(_:_*)) /* more in idea */ }

×