Kotlin logo

Kotlin

A concise multiplatform language developed by JetBrains

Language design

The Dot Operator

Warning: this is an April Fools’ post

Point-free style is a big trend in modern functional programming: it allows to manipulate functions without mentioning their arguments which makes the code concise and compositional. Here is an example from Wikipedia:

mf = (. map) . (.) . filter

This function, written in Haskell, composes a map() function with a filter() function. As you can see, point-free style largely relies on dots.

Kotlin is not a functional language per se, but we are happy to borrow useful features from other languages. So, today I’ll write about dots.

The Dot

We introduce the dot operator in Kotlin. As usual, it works by convention. If there’s a function like this

fun Foo.dot() {
    println("a dot!")
}

it will be called whenever there’s a dot (“.”) after an expression of type Foo:

fun test(f: Foo) {
    f.foo()
    Foo().bar().baz()
}

This function prints “a dot!” twice: once for each dot after a Foo. The bar() function doesn’t return a Foo, so the dot after it doesn’t count.

Dot Chaining

What if my dot() function returned something, for example, another Foo?

class Foo(val count: Int)

fun Foo.dot(): Foo {
    return Foo(count + 1)
}

then, of course, it’s result is used to call whatever comes after the dot:

println(Foo(1).count)

This prints 2, because the dot() function returned a new Foo with an increased counter.

As you can see, the dot operator gives us a lot of power and addresses most of the issues previously tackled only by aspect-oriented programming.

Flavors of the Dot

The real power of the dot operator comes in when you declare it with a parameter:

fun Any.dot(p: Dot) {
   ...
}

The parameter must be of the Dot type, of which there are a few interesting predefined values:

LEFT
RIGHT
TOP
BOTTOM

These values correspond, obviously, to the position of the dot:

fun test() {
    println(a.b[1..2])
}

One might think that in this example dot() is called three times: one for “a.b”, with the argument BOTTOM, then twice for “1..2”: first with LEFT, and then with RIGHT (these are not two BOTTOMs, because “..” is a single token in Kotlin), but in fact it gets called four times, and the fourth time (in fact it comes first) with TOP as an argument.

I’m sure you already see why: in Kotlin, we never forget to dot out i’s, and that dot counts as well; its position is clearly TOP (we could introduce a separate tittle() function, but we found it too inconvenient). Tittles above j’s count just as well, same for dots in ; ! ? etc.

The Depth of the Dot

You may be wondering what happens if dot() is defined like this:

fun Foo.dot() {
    println(this.count)
}

There is a dot after this, which has type Foo, in the body of Foo.dot() function itself, so dot() should be called recursively at that point and, seemingly, never terminate. This is called a higher-order dot, and is executed only if there’s a function dot1() defined on Foo. If dot1(), in turn, contains a higher-order dot, then dot2() is called and so on:

fun Foo.dot1() {
    println(this.count) // a call to dot2() if that is defined
}

This corresponds to Russel’s approach to set theory called type theory (with its notion of a class), which lies the solid foundation for statically-typed object-oriented programming.

Conclusion

We are planning to support the dot operator very soon. The first version will be restricted to basic ASCII characters such as . : ; ! ? and, of course i, but in the future we plan to expand it to other characters like ё.

Have a nice Dot!

image description