I was excited to see the description of a “builder” syntax in the “upcoming Java-compatible JVM language Kotlin”:http://confluence.jetbrains.net/display/Kotlin/Welcome, from the folks at “JetBrains”:http://jetbrains.com.
Builder syntax is an expressive way to build tree-like object structures in languages that are more typically seen expressing code than data. (Lispers, don’t watch.) I first saw this when I found Jim Weirich’s “Builder”:https://github.com/jimweirich/builder library in Ruby a few years ago. It lets you build XML (or HTML) like this:
require 'rubygems'
require 'builder'
x = Builder::XmlMarkup.new :indent => 2
x.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
record = x.person {
x.name {
x.first 'Falstad'
x.last 'Wildhammer'
}
x.address {
x.street 'Redshirt'
x.state 'MI'
}
}
puts record
This produces:
Falstad
Wildhammer
Redshirt
MI
This was a pretty neat idea at the time, and I’ve always kept my eye out for this sort of syntax when building tree structures. Since that time, I’ve stumbled across quite a few other implementations. In 2008, Atomic considered the Cheri library to make some of the interfaces for a desktop JRuby app. I don’t recommend Cheri as it seems to be broken and abandoned, but it was the first time I was introduced to the idea of what Cheri called a builder-builder, which is a builder syntax you can use to create other builders. Cheri has a broken builder-builder implementation, but I soon found a much better one in the Groovy language: the MetaBuilder.
h2. Groovy
Groovy has deep support for this declarative style and has become somewhat of a de facto standard among other implementations, with some mentioning it as direct inspiration. Its cleanliness really shines when wrangling cumbersome Java APIs like Swing. (With–what else–a “SwingBuilder”.) For me, MetaBuilder is the real jewel, because it allows anyone to create their own builder DSLs in idiomatic fashion.
Here’s an example of building some XML with Groovy:
def writer = new StringWriter()
def builder = new groovy.xml.MarkupBuilder(writer)
builder.person() {
name() {
first("Falstad")
last("Wildhammer")
}
history() {
event("Freed Alextrasza")
event("Survived")
event("Lead Aerie Peak")
}
}
println writer.toString()
And here’s the SwingBuilder I mentioned, in action:
// From http://groovy.codehaus.org/Swing+Builder
import groovy.swing.SwingBuilder
import java.awt.BorderLayout as BL
count = 0
new SwingBuilder().edt {
frame(title:'Frame', size:[300,300], show: true) {
borderLayout()
textlabel = label(text:"Click the button!", constraints: BL.NORTH)
button(text:'Click Me', actionPerformed: {
count++
textlabel.text = "Clicked ${count} time(s)."
println "clicked"
},
constraints:BL.SOUTH)
}
}
h2. Building On the Web
Most of my current everyday use of builder syntax is in templates. With great libraries like “Haml”:http://haml.info/ or “Slim”:http://slim-lang.com/, I can build HTML with a very fluid, purpose-built builder syntax. Haml has become the template language of choice around Atomic.
Too bad these template-focused libraries take the approach of putting the builder on the outside and the code “snippets” inside. Remeniscent of the Rails Way, I appreciate this separation when I write templates in web apps, but it leaves me wishing I could use similar syntax in the language directly. “Jaml”:https://github.com/edspencer/jaml, for Javascript, is an example of a sort of hybrid approach. For example:
Jaml.register('simple', function() {
div(
h1("Some title"),
p("Some exciting paragraph text"),
br(),
ul(
li("First item"),
li("Second item"),
li("Third item")
)
);
});
Jaml.render('simple');
I appreciate this blurry line between data, code, and structure.
h2. Kotlin and the JVM crowd
Finding out that “Kotlin”:http://blog.jetbrains.com/kotlin/ will have “support for builders out-of-the-box”:http://confluence.jetbrains.net/display/Kotlin/Type-safe+Groovy-style+builders was exciting. It’s a great way to show off your budding language and, to me, the surge of JVM language choices is the most exciting thing in the Java world now. They’re all off to a good start and improving quickly. Similar to implementing Mock Objects, languages are stressed and stretched in positive directions by implementing builders, especially metabuilders. You need great DSL expressability, clean closures, and lightweight function calls. It helps language users express nested object structures quickly. It also keeps scripting languages sharp when put up against “Lisps”:https://bitbucket.org/ksojat/neman/src/88f8fc21c2c9/examples/swing1.clj and lightweight data markup like YAML and JSON.
h2. Did I Forget Any?
Anyone know of a great builder implementation that I left out? I’d love to hear from you!
I once wrote a Python library “withxml”, which would generate XML data using a series of context managers (the “with” statement), so you’d have:
It generated an ElementTree and had support for things like namespaces (based on packages), xml:id, XMLBase, and a few other things. I’ve never used it in a project, so I’ve never published it.