DEV Community

Cover image for Cocktail of Kotlin
Brian Orwe
Brian Orwe

Posted on

Cocktail of Kotlin

This is An Article about the possibilities and syntax of Kotlin from a Java devs.

Basically, recently joined the Android Hutsy Group in Kenya, where we started to have a look at Kotlin language from scratch, I knew Kotlin but, I had never really gone deep, and was mostly relying on previous Java experience, I was amazed at what Kotlin could actually do, especially syntax wise, though at some point I must admit it started feeling like I was just using Lombok without the annotations, that was till I discovered the crazy syntax abilities it offers by the way which Kotlin handles Lambdas.

Let's start from basics. A class.
In Kotlin all classes a closed, aka final as we would call them in Java world by default, hence they can't be extended, unless opened using the open key word. An example of such a class is bellow.

open class Element(val tagName: String,
    var elements: MutableList<Element> = mutableListOf(),
    var attributes: MutableMap<String, String> = mutableMapOf()){
    override fun toString(): String{
        var result = "<$tagName"
        if(elements.size == 0){
            result += "/>"
        }else{
            result+=">"
            for(element in elements){
                result += element.toString()
            }
            result+="</$tagName>"
        }
        return result
    }
}
Enter fullscreen mode Exit fullscreen mode

So another difference in classes in Kotlin is variables that would normally have been declared inside the class body are put inside the () after the class name, this is Kotlins constructor way of initializing variables, there is other ways eg the init{} method inside a class, but that one is often rarely used when the variables can just be set via the constructor.
For example val tagName: String, is a variable inside the class, notice the declaration resemble that of typescript where the type comes after colons, and like typescript the type can be infered, the val keyword means const, and var would be the equivalent of a non const version.

In the above class we override the toString method, very similar to how Java does it too. The class above is a base class that we will use to create a simple HTML DSL language which we can call toString on the final object to get the full html syntax. Next we extend the open Element class

class H1(val title: String): Element("h1"){
    override fun toString(): String{
        return "<h1>$title</h1>"
    }
}
Enter fullscreen mode Exit fullscreen mode

This will be our <h1> equivalent tag, but in Kotlin, not that the toString method basically returns a string of <h1>$title</h1> which title being a variable inside the class H1, also not how we extend the class, unlike Java, the extends keyword has been replaced with a colon, but you still can't have multiple extends, only 1, and none or many interfaces just like in Java. Next we declare the body tag, for the body element.

class Body(): Element("body")
Enter fullscreen mode Exit fullscreen mode

Not that we don't need a body block when the class is empty when declaring a class in Kotlin, as we would have needed in Java. Next lets define a function can produces the body element.

fun body(vararg funcs: (Element)->Element): Element{
    var body = Body()
    for(func in funcs){
        val element = func(body)
        body.elements.add(element)
    }
    return body
}
Enter fullscreen mode Exit fullscreen mode

Functions in Kotlin don't need to be in classes, Java 21 had recently added this feature too. Notice the vararg, that is a variadic function, meaning, it takes zero or more arguments of the said type (Element)->Element, this is a lambda that takes in an Element and returns an Element type.
We then create a body object, and to go through the variadic arguments passed we use a for in loop in kotlin, this would be similar to the foreach loop in Java, we call each element in the variadic passed, since it is a function, and pass it the body object, we then add the elements returned from calling the function into the body object, lastly we return the body object. Next we define the html function, this one would look quite similar to the body function.

fun html(vararg funcs: (Element)->Element): Element{
    var html = Element("html")
    for(func in funcs){
        val element = func(html)
        html.elements.add(element)
    }
    return html
}
Enter fullscreen mode Exit fullscreen mode

The reason we pass a varargs you will see later is it helps in creating composition of elements, giving a smilar look to jetpack Compose and android framework for drawing Views onto the screen. Next we define the h1 function.

fun h1(heading: String) = H1(heading)
Enter fullscreen mode Exit fullscreen mode

Note that this has no body, just an equal sign, yes. With Kotlin we can shorten the function body by just using = sign when returning a single object, the object can be composed, but eventually only one thing is returned, it can be a list, an int, etc... but one object. We now define the main function.

fun main() {
    var html = html(
    {
        body(
            {h1("HELLO WORLD")},
            {h1("FROM BRIAN")}
        )
    })
    print(html)
}
Enter fullscreen mode Exit fullscreen mode

Finally we reach the meat. Notice it is all looking very simple, and composed, html takes in multiple elements, we pass it a body, which also can take in multiple elements, which we pass it as mutlple h1s, remember the html and body had variadic arguments? yes this was the reason, it allowed for simple composability. Finally we get the finally html object and store it in the html variable, we then call the print function on the object which now unwraps the html elements, in a nice way, remember we didn't write much in terms of the toString, and only h1 had a custom design. Eventually the output would be as shown bellow:

<html><body><h1>HELLO WORLD</h1><h1>FROM BRIAN</h1></body></html>
Enter fullscreen mode Exit fullscreen mode

Pretty neat huh? Kotlin is pretty composable if you ask me, you could build your own basic backend serverside rendering HTML DSL pretty easily with all this if one wished to extend it further, reminded be of the old Java Server Pages days, but in a very more composable easy to read way.

That's all for now, here is the full sourcecode all together, enjoy, 😄

open class Element(val tagName: String, 
   var elements: MutableList<Element> = mutableListOf(),
   var attributes: MutableMap<String, String> = mutableMapOf()){
    override fun toString(): String{
        var result = "<$tagName"
        if(elements.size == 0){
            result += "/>"
        }else{
            result+=">"
            for(element in elements){
                result += element.toString()
            }
            result+="</$tagName>"
        }
        return result
    }
}

class H1(val title: String): Element("h1"){
    override fun toString(): String{
        return "<h1>$title</h1>"
    }
}

class Body(): Element("body")

fun body(vararg funcs: (Element)->Element): Element{
    var body = Body()
    for(func in funcs){
        val element = func(body)
        body.elements.add(element)
    }
    return body
}

fun html(vararg funcs: (Element)->Element): Element{
    var html = Element("html")
    for(func in funcs){
        val element = func(html)
        html.elements.add(element)
    }
    return html
}

fun h1(heading: String) = H1(heading)

fun main() {
    var html = html(
    {
        body(
            {h1("HELLO WORLD")},
            {h1("FROM BRIAN")}
        )
    })
    print(html)
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)