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. What is DSL?
Domain-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. 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.
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. 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. 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. 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. Fluent API examples
Mockito http://code.google.com/p/mockito/
Guava http://code.google.com/p/guava-libraries/
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. 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 names
Implicit conversions
Advanced type system
By-name parameters and
currying
14. 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
15. 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))
}
16. 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()
}
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. 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()
}
}