Victor Kropp

DSLs in Kotlin: The Good, the Bad and the Ugly

DSLs are a very hot topic among Kotlin developers. No surprise, language designers take it seriously and are adding specific features directly into the language to improve DSL behavior. In this post, I’d like to share and discuss 3 examples of DSLs written in Kotlin.

The Good, the Bad and the Ugly (1966)

The Good, the Bad and the Ugly (1966)

The Good

Anko is a great DSL for building Android views. Here is an example from official documentation:

verticalLayout {
    val name = editText()
    button("Say Hello") {
        onClick { toast("Hello, ${name.text}!") }
    }
}

Anko uses Kotlin’s builder functions not only to create nested views but also to add listeners. Still, it is absolutely clear in both cases what is meant to be here. This language is extensible and covers all use cases.

kotlinx.html is very similar language to build HTML. It would be the perfect example as well if only it doesn’t use + operator to append raw text. Why? I’ll explain it in the next section.

The Bad

Here is the whole DSL in just one line of code:

operator fun String.div(path: String) = this + "/" + path
val logFile = home / "logs" / "log.txt"

It allows using / operator on strings for file system path concatenation. I’ve seen it many times before (for example, in C# and C++ where operator overloading is possible too).

On the first sight, it looks like a smart and clever idea. However you soon discover its limits:

Don’t abuse operator overloading, it is usually unclear and can lead to unpredictable errors. Still not convinced? Read further.

The Ugly

Just don’t do this. Never.

It is a very quirky way to add missing ternary operator. Reasons, why it is not implemented in Kotlin, are explained in the documentation. One of them is the lack of extensibility, nested ternary operators look ugly and it might be very difficult to find out what’s going on there. Use when instead.

This DSL does not resolve the aforementioned problem but adds another one: without looking in the source code, it is absolutely unclear what does these % and / symbols mean in this context. I bet, even the author of this snippet will forget their meaning in a year.

If only it was not enough already, this particular code adds an object instantiation on every call, which may lead to performance problems if it is on a critical path.

So let me repeat it once again: don’t do this.

Conclusion

Kotlin is very flexible general purpose language. It offers great extensibility and power of type-safe builders and extension functions to library creators. Please, don’t abuse it. With great power comes great responsibility.

Do you know other DSLs written in Kotlin? Share and discuss in comments!

kotlindslprogramming

Subscribe to all blog posts via RSS