AestasIT - Internal DSLs in Scala
-
Upload
neueda -
Category
Technology
-
view
1.356 -
download
3
Transcript of AestasIT - Internal DSLs in Scala
Internal DSLs in ScalaAndrey AdamovichAestas/IT
What’s in this presentation?Definition and usage of DSLsOverview of Scala features that
can be used to create internal DSL
Examples of Scala-based DSLsSome links and reading materialQuestions
WORLD OF DSLS
What is DSL?
Domain-Specific LanguageA 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).
”
Examples of DSL
Examples of domain-specific languages include: 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,
software packages used for graph layout and graph rewriting.
”
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 LaforgeGroovy Project Manager
”
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
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
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).
”
Fluent API examplesMockito
Guava http://code.google.com/p/guava-libraries/
http://code.google.com/p/mockito/
SCALA
Features of ScalaLightweight syntaxCombines functional and object-
oriented aproachesAdvanced type system:
everything has a typeStrong type inferencePerformance comparable to JavaFully interoperable with Java
What makes internal DSL possible in Scala?”Dot-free”, infix and postfix
operator notation”Bracket-free” function calls(Almost) any character can be
used in method namesImplicit conversionsAdvanced type systemBy-name parameters and
currying
Lightweight syntax
val numbers = List(1, 2, 3)
numbers map { x => x + 1 }
numbers sortWith { (x, y) => x > y }
numbers map { _ + 1 } sortWith { _ > _ }
numbers size
Implicit conversions
Map( "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))}
By-name parameters
debug("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() }
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).
”
Curryng II
using(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() }}
Advanced type system
DSL EXAMPLES
Baysick
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}
ScalaBasicRunner.scala:
Time DSLimport org.scala_tools.time.Imports._
DateTime.now
DateTime.now.hour(2).minute(45).second(10)
DateTime.now + 2.months
DateTime.nextMonth < DateTime.now + 2.months
DateTime.now to DateTime.tomorrow
(DateTime.now to DateTime.nextSecond).millis
2.hours + 45.minutes + 10.seconds
(2.hours + 45.minutes + 10.seconds).millis
2.months + 3.days
Spring Integration DSL
val messageFlow = filter using { payload: String => payload == "World" } --> transform using { payload: String => "Hello " + payload } --> handle using { payload: String => println(payload) } messageFlow.send("World")
READING MATERIAL
Books
DSLs in ActionDebasish Ghosh
Programming in Scala, Second EditionMartin Odersky, Lex Spoon, and Bill
Venners
Links http://www.scala-lang.org/
https://github.com/jorgeortiz85/scala-time
http://blog.springsource.org/2012/03/05/introducing-spring-integration-scala-dsl/
http://blog.fogus.me/2009/03/26/baysick-a-scala-dsl-implementing-basic/
http://habrahabr.ru/post/98288/
QUESTIONS