Internal DSLs
APIs vs. internal DSLs
internal DSLAPI differencevs. not always clear
command-query API
fluent API
objects
sequence of method calls separate statements
chain of method calls each method returns an object
subsequent calls on this object
more concise code enforce a valid sequence of method calls
Graph g = graph("example1").directed().with(node("a").link(node("b")));
Java codemethods make little sense individually
Internal DSLs
internal DSL like fluent API no way to change syntax of method calls
inflexible syntax rules of the host language
host language with flexible syntax DSLs look like custom languages
IDE not aware of constraints of embedded DSLs
only checks by type system
not much in dynamically typed host languages
every 2.days, :at => ‘4:30 am’ do
reboot
end
Ruby code
do_something 24.hours.from_now
also Ruby code
Nested functions
Car car = new CarImpl();
Car.setColor(Color.WHITE);
Engine engine1 = new EngineImpl();
engine1.setType(EngineType.FUEL);
engine1.setPower(50);
car.addEngine(engine1);
Engine engine2 = new EngineImpl();
engine2.setType(EngineType.ELECTRIC);
engine2.setPower(75);
car.addEngine(engine2);
car(
color(Color.WHITE),
engine(
type(EngineType.FUEL),
power(50)
),
engine(
type(EngineType.ELECTRIC),
power(75)
)
);
command-query API
no need for context variables
arguments defined by position
inverted evaluation order
hierarchic structure echoed by function nesting
issues with
optional arguments
Method chaining
Car car = new CarImpl();
Car.setColor(Color.WHITE);
Engine engine1 = new EngineImpl();
engine1.setType(EngineType.FUEL);
engine1.setPower(50);
car.addEngine(engine1);
Engine engine2 = new EngineImpl();
engine2.setType(EngineType.ELECTRIC);
engine2.setPower(75);
car.addEngine(engine2);
car()
.color(Color.WHITE)
.engine()
.power(50)
.type(EngineType.FUEL)
.engine()
.power(75)
.end();
assume that default value of
engine type is electric
methods can be invoked in any order
hierarchy defined only by indentation convention
works with optional parameters
make modifier methods return the host object
multiple modifiers can be invoked in a single expression
Internal DSLs in Scala Money
http://github.com/lambdista/money

Internal domain-specific languages

  • 1.
  • 2.
    APIs vs. internalDSLs internal DSLAPI differencevs. not always clear command-query API fluent API objects sequence of method calls separate statements chain of method calls each method returns an object subsequent calls on this object more concise code enforce a valid sequence of method calls Graph g = graph("example1").directed().with(node("a").link(node("b"))); Java codemethods make little sense individually
  • 3.
    Internal DSLs internal DSLlike fluent API no way to change syntax of method calls inflexible syntax rules of the host language host language with flexible syntax DSLs look like custom languages IDE not aware of constraints of embedded DSLs only checks by type system not much in dynamically typed host languages every 2.days, :at => ‘4:30 am’ do reboot end Ruby code do_something 24.hours.from_now also Ruby code
  • 4.
    Nested functions Car car= new CarImpl(); Car.setColor(Color.WHITE); Engine engine1 = new EngineImpl(); engine1.setType(EngineType.FUEL); engine1.setPower(50); car.addEngine(engine1); Engine engine2 = new EngineImpl(); engine2.setType(EngineType.ELECTRIC); engine2.setPower(75); car.addEngine(engine2); car( color(Color.WHITE), engine( type(EngineType.FUEL), power(50) ), engine( type(EngineType.ELECTRIC), power(75) ) ); command-query API no need for context variables arguments defined by position inverted evaluation order hierarchic structure echoed by function nesting issues with optional arguments
  • 5.
    Method chaining Car car= new CarImpl(); Car.setColor(Color.WHITE); Engine engine1 = new EngineImpl(); engine1.setType(EngineType.FUEL); engine1.setPower(50); car.addEngine(engine1); Engine engine2 = new EngineImpl(); engine2.setType(EngineType.ELECTRIC); engine2.setPower(75); car.addEngine(engine2); car() .color(Color.WHITE) .engine() .power(50) .type(EngineType.FUEL) .engine() .power(75) .end(); assume that default value of engine type is electric methods can be invoked in any order hierarchy defined only by indentation convention works with optional parameters make modifier methods return the host object multiple modifiers can be invoked in a single expression
  • 6.
    Internal DSLs inScala Money http://github.com/lambdista/money