internal dsls in scala

27
Internal DSLs in Scala Andrey Adamovich Aestas/IT

Upload: aestas-it

Post on 21-Jan-2015

1.900 views

Category:

Technology


4 download

DESCRIPTION

This presentation was given at JUG.lv 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.

TRANSCRIPT

Page 1: Internal DSLs in Scala

Internal DSLs in Scala

Andrey Adamovich

Aestas/IT

Page 2: Internal DSLs in Scala

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

Page 3: Internal DSLs in Scala

WORLD OF DSLSWORLD OF DSLSWORLD OF DSLSWORLD OF DSLS

Page 4: Internal DSLs in Scala

What is DSL?

DDDDomain-SSSSpecific LLLLanguage

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).

Page 5: Internal DSLs in Scala

Examples of DSL

� Examples of domain-specific languages include:

� HTMLHTMLHTMLHTML,

� LogoLogoLogoLogo for children,

� VerilogVerilogVerilogVerilog and VHDLVHDLVHDLVHDL hardware description languages,

� MataMataMataMata for matrix programming,

� MathematicaMathematicaMathematicaMathematica and MaximaMaximaMaximaMaxima for symbolic mathematics,

� spreadsheet formulas and macros,

� SQLSQLSQLSQL for relational database queries,

� YACCYACCYACCYACC grammars for creating parsers,

� regularregularregularregular expressionsexpressionsexpressionsexpressions for specifying lexers,

� the GenericGenericGenericGeneric EclipseEclipseEclipseEclipse ModelingModelingModelingModeling SystemSystemSystemSystem for creating

diagramming languages,

� CsoundCsoundCsoundCsound for sound and music synthesis,

� and the input languages of GraphVizGraphVizGraphVizGraphViz and GrGenGrGenGrGenGrGen,

software packages used for graph layout and graph

rewriting.

Page 6: Internal DSLs in Scala

Goals of DSL

� Use a more expressive more expressive more expressive more expressive language than a general-

purpose one

� Share a common metaphor of common metaphor of common metaphor of common metaphor of understanding understanding understanding understanding

between developers and subject matter experts

� Have domain experts help domain experts help domain experts help domain experts help with the design of the

business logic of an application

� Avoid cluttering business code with too much too much too much too much

boilerplate technical boilerplate technical boilerplate technical boilerplate technical code code code code thanks to a clean

separation

� Let business rules have their own lifecycleown lifecycleown lifecycleown lifecycle

Guillaume LaforgeGroovy Project Manager

Page 7: Internal DSLs in Scala

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

Page 8: Internal DSLs in Scala

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

Page 9: Internal DSLs in Scala

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).

Page 10: Internal DSLs in Scala

Fluent API examples

Mockito

Guava http://code.google.com/p/guava-libraries/

http://code.google.com/p/mockito/

Page 11: Internal DSLs in Scala

SCALASCALASCALASCALA

Page 12: Internal DSLs in Scala

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

Page 13: Internal DSLs in Scala

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

Page 14: Internal DSLs in Scala

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

Page 15: Internal DSLs in Scala

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))

}

Page 16: Internal DSLs in Scala

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()

}

Page 17: Internal DSLs in Scala

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 chain of functions chain of functions chain of functions each with

a single argument (partial application).

Page 18: Internal DSLs in Scala

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()

}

}

Page 19: Internal DSLs in Scala

Advanced type system

Page 20: Internal DSLs in Scala

DSL DSL DSL DSL EXAMPLESEXAMPLESEXAMPLESEXAMPLES

Page 21: Internal DSLs in Scala

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:

Page 22: Internal DSLs in Scala

Time DSL

import 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

Page 23: Internal DSLs in Scala

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")

Page 24: Internal DSLs in Scala

READING MATERIALREADING MATERIALREADING MATERIALREADING MATERIAL

Page 25: Internal DSLs in Scala

Books

DSLs in Action

Debasish Ghosh

Programming in Scala, Second Edition

Martin Odersky, Lex Spoon, and Bill Venners

Page 26: Internal DSLs in Scala

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/

Page 27: Internal DSLs in Scala

QUESTIONSQUESTIONSQUESTIONSQUESTIONS