The documentation for Kotlin is now located on the new site. This page is kept for historical reasons
Skip to end of metadata
Go to start of metadata
The documentation for Kotlin is now located on the new site. This page is kept for historical reasons

The concept of builders is rather popular in the Groovy community. Builders allow for defining data in a semi-declarative way. Builders are good for generating XML, laying out UI components, describing 3D scenes and more...

For many use cases, Kotlin allows to type-check builders, which makes them even more attractive than the dynamically-typed implementation made in Groovy itself.

For the rest of the cases, Kotlin supports [dynamic] builders.

A type-safe builder example

Consider the following code that is taken from here and slightly adapted:

import html.* 
 
fun result(args : Array<String>) = 
  html { 
    head { 
      title {+"XML encoding with Kotlin"} 
    } 
    body { 
      h1 {+"XML encoding with Kotlin"} 
      p {+"this format can be used as an alternative markup to XML"} 
 
      // an element with attributes and text content 
      a(href = "http://jetbrains.com/kotlin") {+"Kotlin"} 
 
      // mixed content 
      p { 
        +"This is some" 
        b {+"mixed"} 
        +"text. For more see the" 
        a(href = "http://jetbrains.com/kotlin") {+"Kotlin"} 
        +"project" 
      } 
      p {+"some text"} 
 
      // content generated by 
      p { 
        for (arg in args) 
          +arg 
      } 
    } 
  }

This is a completely legitimate Kotlin code. Click on names to navigate to definitions of function used in this example (they appear below in this page).
You can play with this code online (modify it and run in the browser) here.

How it works

Let's walk through the mechanisms of implementing type safe builders in Kotlin. First of all we need to define the model we want to build, in this case we need to model HTML tags. It is easily done with a bunch of classes. For example, HTML is a class that describes the <html> tag, i.e. it defines children like <head> and <body>.
(See its declaration below.)

Now, let's recall why we can say something like this in the code:

html { 
 // ... 
}

This is actually a function call that takes a function literal as an argument (see this page for details). Actually, this function is defined as follows:

fun html(init : HTML.() -> Unit) : HTML { 
  val html = HTML() 
  html.init() 
  return html 
}

This function takes one parameter named init, which is itself a function. Actually, it is an extension function that has a receiver of type HTML (and returns nothing interesting, i.e. Unit). So, when we pass a function literal to as an argument to html, it is typed as an extension function literal, and there's this reference available:

html { 
  this.head { /* ... */ } 
  this.body { /* ... */ } 
}

(head and body are member functions of HTML.)
Now, this can be omitted, as usual, and we get something that looks very much like a builder already:

html { 
  head { /* ... */ } 
  body { /* ... */ } 
}

So, what does this call do? Let's look at the body of html function as defined above. It creates a new instance of HTML, then it initializes it by calling the function that is passed as an argument (in our example this boils down to calling body on the HTML instance), and then it returns this instance. This is exactly what a builder should do.

The head and body functions in the HTML class are defined similarly to html. The only difference is that they add the built instanced to the children collection of the enclosing HTML instance:

fun head(init : Head.() -> Unit) { 
  val head = Head() 
  head.init() 
  children.add(head) 
  return head 
} 
 
fun body(init : Body.() -> Unit) { 
  val body = Body() 
  body.init() 
  children.add(body) 
  return body 
}

Actually these two functions do just the same thing, so we can have a generic version, initTag:

protected fun initTag<T: Element>(tag: T, init: T.() -> Unit): T { 
    tag.init() 
    <ref="children:>children.add(tag) 
    return tag 
  }

So, now our functions are very simple:

fun head(init : Head.() -> Unit) = initTag(Head(), init) 
 
fun body(init : Body.() -> Unit) = initTag(Body(), init)

And we can use them to build <head> and <body> tags.

One other thing to be discussed here is how we add text to tag bodies. In the example above we say something like

html { 
  head { 
    title {+"XML encoding with Kotlin"} 
  } 
  // ... 
}

So basically, we just put a string inside a tag body, but there is this little "+" in front of it, do it is a function call that invokes a prefix "plus" operation. That operation is actually defined by an extension function plus that is a member of the TagWithText abstract class (a parent of Title):

fun String.plus() { 
  children.add(TextElement(this)) 
}

So, what the prefix "+" does here is it wraps a string into an instance of TextElement and adds it to the children collection, so that it becomes a proper part of the tag tree.

All this is defined in a package html that is imported at the top of the builder example above. In the next section you can read through the full definition of this namespace.

Full definition of the html namespace

This is how the namespace html is defined (only the elements used in the example above). It builds an HTML tree. It makes heavy use of Extension functions and Extension function literals.

package html 
 
import java.util.ArrayList 
import java.util.HashMap 
 
trait Element { 
    fun render(builder: StringBuilder, indent: String) 
 
    fun toString(): String? { 
        val builder = StringBuilder() 
        render(builder, "") 
        return builder.toString() 
    } 
} 
 
class TextElement(val text: String): Element { 
    override fun render(builder: StringBuilder, indent: String) { 
        builder.append("$indent$text\n") 
    } 
} 
 
abstract class Tag(val name: String): Element { 
    val children: ArrayList<Element> = ArrayList<Element>() 
    val attributes = HashMap<String, String>() 
 
    protected fun initTag<T: Element>(tag: T, init: T.() -> Unit): T { 
        tag.init() 
        children.add(tag) 
        return tag 
    } 
 
    override fun render(builder: StringBuilder, indent: String) { 
        builder.append("$indent<$name${renderAttributes()}>\n") 
        for (c in children) { 
            c.render(builder, indent + "  ") 
        } 
        builder.append("$indent</$name>\n") 
    } 
 
    private fun renderAttributes(): String? { 
        val builder = StringBuilder() 
        for (a in attributes.keySet()) { 
            builder.append(" $a=\"${attributes[a]}\"") 
        } 
        return builder.toString() 
    } 
} 
 
abstract class TagWithText(name: String): Tag(name) { 
    fun String.plus() { 
        children.add(TextElement(this)) 
    } 
} 
 
class HTML(): TagWithText("html") { 
    fun head(init: Head.() -> Unit) = initTag(Head(), init) 
 
    fun body(init: Body.() -> Unit) = initTag(Body(), init) 
} 
 
class Head(): TagWithText("head") { 
    fun title(init: Title.() -> Unit) = initTag(Title(), init) 
} 
 
class Title(): TagWithText("title") 
 
abstract class BodyTag(name: String): TagWithText(name) { 
    fun b(init: B.() -> Unit) = initTag(B(), init) 
    fun p(init: P.() -> Unit) = initTag(P(), init) 
    fun h1(init: H1.() -> Unit) = initTag(H1(), init) 
    fun a(href: String, init: A.() -> Unit) { 
        val a = initTag(A(), init) 
        a.href = href 
    } 
} 
 
class Body(): BodyTag("body") 
 
class B(): BodyTag("b") 
class P(): BodyTag("p") 
class H1(): BodyTag("h1") 
class A(): BodyTag("a") { 
    public var href: String 
        get() = attributes["href"]!! 
        set(value) { 
            attributes["href"] = value 
        } 
} 
 
fun html(init: HTML.() -> Unit): HTML { 
    val html = HTML() 
    html.init() 
    return html 
}

Appendix. Making Java classes nicer

In the code above there's something that looks very nice:

class A() : BodyTag("a") { 
    var href : String 
      get() = attributes["href"]!! 
      set(value) { attributes["href"] = value } 
  }

We access the attributes map as if it were an "associative array": just with the [] operation. By convention this compiles to a call to get(K) or set(K, V), all right. But we said that attributes was a Java Map, i.e. it does NOT have a set(K, V). This problem is easily fixable in Kotlin:

fun <K, V> Map<K, V>.set(key : K, value : V) = this.put(key, value)

So, we simply define an extension function set(K, V) that delegates to vanilla put and make a Kotlin operator available for a Java class.

What's next

Examples

Functions

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Jul 20, 2011

    Anonymous

    See how they all (groovy builders, kotlin builders) all want Lisp (such as Clojure). They just don’t know it yet it seems.

  2. Jul 28, 2011

    Type safe builders, this is really nice.
    The document structure definition, if we can call it that way, is still verbose however.
    I wonder what could be done with a little more sugar.
    But this is not common to design the structure of something like Html even if we use it so much.
    I have never done such a thing or see anybody do that.
    Inserting tags inside text, this is not common outside of html like data.
    Maybe with Svg, Vml, and the like.
    However for json like data, I see potential uses every day.

    Json syntax simplicity is hard not to like.
    Doing the same thing in java, not really, this is syntactically impossible.
    But in Kotlin, as far as I known the following code is valid syntax.
    The Country and Province class definition are left as an exercice of course.
    I havent seen the list literal syntax in the documentation yet, but I bet this is coming.

    This is not just a bunch of map of map.
    This is some type safe object notation.
    That's right, this is some tson.
    This is a really nice feature.
    Actually it is 3 small features working together: named params, removing the "new" keyword and list literals.

    That may still be improved.
    No comma or allowing a trailing coma would make it easier to edit properties.
    I always have to correct missing or extra commas in my jsons when I add, delete, shuffle and copy paste properties.
    Also, maybe the Province constructor here could be infered, when the type of the containing list is not abstract.

    1. Jul 27, 2011

      Thanks for your suggestion

  3. Aug 11, 2011

    Is it really necessary to specify type explicitly in initTag<B>(init) for example. It will be really nice if <B> can be infered

    1. Aug 12, 2011

      While we are still working on the inference subsystem, I think we will be able to infer the types in this case.

  4. Sep 25, 2011

    Anonymous

    The Unit fiction is one of the confusing things for people first learning Scala. I don't think it is necessary to create such an esoteric syntax. The html function (and child element functions) can take a variable argument list instead (or the last input parameter can be a variable argument list), then the braces get replaced with parenthesis and commas. Then one less thing to have to explain. I admire languages that have a consistent syntax with the least number of concepts to learn and memorize. What difference does it make:

    html {

       head {

          title { ... }

       }

       body {... }

    }

    Or:

    html (

       head (

          title ( ... )

       ),

       body( ... )

    )

    The latter is immediately understand by any programmer from any background.

    -Shelby Moore III

    1. Sep 25, 2011

      I don't see how Unit is essential for the example studied in this section.

      As of parameters vs function literal bodies, the key thing here is that which function literals you can intermix "markup" with code in the way you see in the last <p> element, and the context will be taken care of by the 'this' in the current function literal.

      1. Sep 27, 2011

        Anonymous

        Using variable argument length function parameters, seems to me the entire example can be accomplished with constructor functions. For example, body can input a variable argument of type htmlelement, and paragraph a variable argument of the disjunction type (htmlelement or string). No need to ever introduce the concept of Unit. I saw someone else refer to Unit as "fiction" and then I realized this is probably what they meant. Perhaps I am wrong.

        A disjunction type is very important: http://stackoverflow.com/questions/3508077/does-scala-have-type-disjunction-union-types/7460312#7460312

        1. Sep 27, 2011

          I still don't get how absence or presence of Unit can possibly influence the HTML builder example.

          As of the constructors story, please refer to the comment you were replying to.

  5. Oct 07, 2011

    Anonymous

    Is there a way to get rid of the "+"? If the body should return Unit, could one infer the "+"?

    1. Oct 07, 2011

      Anonymous

      The + was missing in my comment above in "...".

    2. Oct 07, 2011

      I don't think we could literally infer the "+", because this means implicitly calling a function, which, if generalized, leads to very cumbersome code.

      Note that "the '+' problem" only stands for HTML, and not for other builders that do not have "free" text in the built structure.

      For HTML, you can get rid of "+" at expense of sacrificing some type safety: use varargs functions instead of functions taking functions as parameters. And this is basically what Groovy does here.

  6. Oct 09, 2011

    Just to comment on the "groovy-ness" of builders and type-safety, we can make Groovy builders as type-safe as we want. We can create a builder that only recognizes certain tags and forbids others. With the help of a compilation customizer or an AST transformation, we can even let the compiler report compilation errors if a non-allowed tag is used. Furthermore, with GDSL or DSLD file (whether one is on IntelliJ IDEA or Eclipse), we can even provide rich type-completion from the IDE for authoring such markup.

    Also, the Groovy markup builder is used to create any markup (including namespaces), not just HTML. Your builder will have to be udpated should HTML 5, 6, 7, x, add new tags that are not recognized by the builder, whereas it's possible with Groovy's one.

    That said, the use of + for free text is a good idea -- that could be adopted within the Groovy markup builder as well.

  7. Apr 22, 2013

    in the following example,  you can see I have added a new "head" within body and also another "body" call within the main "body".

    Is there a way to restrict the calls and make sure only valid calls can happen ? 

    1. Apr 22, 2013

      You can define a deprecated method, say, "head" in the BodyTag class, so that the call will be highlighted for you. Currently there's no way to get a compiler error there, we are working on this.

      1. Jul 29, 2014

        Any update on this issue? Just discovered it today.

        UPD. Maybe some kind of compile-time annotations... 

        More complex cases like allowing only one head per html could be achieved by setting flags/variables in this annotations and checking them. This is hack of questionable cleanness that smells like C's #define, but why the hell not? :-)

        1. Jul 31, 2014

          No definite decision on this yet.

  8. May 07, 2013


    Why don't you add an optional string parameter to the initTag method, that will be treated as a first text node? So we can change


    with this one:

    In my experience mixed content in html is rarely used.

    1. May 07, 2013

      Yes, it's an option. The problem is not mixed content, but rather content generated by a few lines of code, though

      1. May 07, 2013

        Yeah, I see. Even so, imho, text nodes' values are often can be evaluated with a single expression.

  9. Oct 14, 2013

    Я правильно понимаю, что namespace html в настоящий момент не актуальный код? Может стоит его обновить? :)

    1. Oct 14, 2013

      Обновил, спасибо