Internal DSLs in Scala


Published on

This presentation was given at meeting on 3rd of May in 2012. It tries to give audience a distinction between internal DSL and fluent interface, gives overview of Scala features that make internal DSLs possible in Scala and gives some examples of those DSLs.

Published in: Technology

Internal DSLs in Scala

  1. 1. Internal DSLs in ScalaAndrey AdamovichAestas/IT
  2. 2. What’s in this presentation? Definition and usage of DSLs Overview of Scala features that can be used to create internal DSL Examples of Scala-based DSLs Some links and reading material Questions
  4. 4. What is DSL? SDomain-Specific Language” A Domain-Specific Language is a programming language or executable specification language that offers, through appropriate notations and abstractions, expressive power focused on, and usually restricted to, a particular problem domain.” The opposite is: • a general-purpose programming language, such as C, Java or Python, • or a general-purpose modeling language such as the Unified Modeling Language (UML).
  5. 5. Examples of DSL” Examples of domain-specific languages include: HTML, HTML Logo for children, Verilog and VHDL hardware description languages, Mata for matrix programming, Mathematica and Maxima for symbolic mathematics, spreadsheet formulas and macros, SQL for relational database queries, YACC grammars for creating parsers, regular expressions for specifying lexers, the Generic Eclipse Modeling System for creating diagramming languages, Csound for sound and music synthesis, and the input languages of GraphViz and GrGen GrGen, software packages used for graph layout and graph rewriting.
  6. 6. Goals of DSL” Use a more expressive language than a general- purpose one Share a common metaphor of understanding between developers and subject matter experts Have domain experts help with the design of the business logic of an application Avoid cluttering business code with too much boilerplate technical code thanks to a clean separation Let business rules have their own lifecycle Guillaume Laforge Groovy Project Manager
  7. 7. What is internal DSL?” Internal DSLs are particular ways of using a host language to give the host language the feel of a particular language Martin Fowler
  8. 8. Library vs. DSL Is there any difference between a well-structured library or API and an internal DSL? Not much, except for the following: • Internal DSL does not look like code in host language • It’s more readable in general and is much closer to natural language
  9. 9. Fluent API” In software engineering, a fluent interface (as first coined by Eric Evans and Martin Fowler) is an implementation of an object oriented API that aims to provide for more readable code.” A fluent interface is normally implemented by using method chaining to relay the instruction context of a subsequent call (but a fluent interface entails more than just method chaining).
  10. 10. Fluent API examplesMockito
  11. 11. SCALA
  12. 12. Features of Scala Lightweight syntax Combines functional and object- oriented aproaches Advanced type system: everything has a type Strong type inference Performance comparable to Java Fully interoperable with Java
  13. 13. What makes internal DSL possiblein Scala? ”Dot-free”, infix and postfix operator notation ”Bracket-free” function calls (Almost) any character can be used in method names Implicit conversions Advanced type system By-name parameters and currying
  14. 14. Lightweight syntaxval numbers = List(1, 2, 3)numbers map { x => x + 1 }numbers sortWith { (x, y) => x > y }numbers map { _ + 1 } sortWith { _ > _ }numbers size
  15. 15. Implicit conversionsMap( "first" -> "Test", "second" -> "Code" )/* Defines a new method sort for array objects */object implicits extends Application { implicit def arrayWrapper[A : ClassManifest](x: Array[A]) = new { def sort(p: (A, A) => Boolean) = { util.Sorting.stableSort(x, p); x } } val x = Array(2, 3, 1, 4) println("x = "+ x.sort((x: Int, y: Int) => x < y))}
  16. 16. By-name parametersdebug("This" + " is" + " very" + " costly!")def debug(msg: => String): Unit = if (isDebugEnabled()) println(msg)spawn(println("I run in different thread!"))def spawn(p: => Unit) = { val t = new Thread() { override def run() = p } t.start() }
  17. 17. Curryng I” In mathematics and computer science, currying is the technique of transforming a function that takes multiple arguments (or an n-tuple of arguments) in such a way that it can be called as a chain of functions each with a single argument (partial application).
  18. 18. Curryng IIusing(new BufferedReader(new FileReader("file"))) { r => var count = 0 while (r.readLine != null) count += 1 println(count)}def using[T <: { def close() }] (resource: T) (block: T => Unit){ try { block(resource) } finally { if (resource != null) resource.close() }}
  19. 19. Advanced type system
  20. 20. DSL EXAMPLES
  21. 21. BaysickScalaBasicRunner.scala:object ScalaBasicRunner extends Baysick with Application { 10 PRINT "Scala" 20 LET (number := 1) 30 IF number > 0 THEN 50 40 PRINT "Java" 50 PRINT "rulez!" 60 END RUN}
  22. 22. Time DSLimport + 2.monthsDateTime.nextMonth < + to DateTime.tomorrow( to DateTime.nextSecond).millis2.hours + 45.minutes + 10.seconds(2.hours + 45.minutes + 10.seconds).millis2.months + 3.days
  23. 23. Spring Integration DSLval messageFlow = filter using { payload: String => payload == "World" } --> transform using { payload: String => "Hello " + payload } --> handle using { payload: String => println(payload) }messageFlow.send("World")
  25. 25. Books Programming in Scala, Second EditionMartin Odersky, Lex Spoon, and Bill Venners DSLs in Action Debasish Ghosh
  26. 26. Links ucing-spring-integration-scala-dsl/ scala-dsl-implementing-basic/
  27. 27. QUESTIONS