Why Kotlin is my next programming language

An ode to the language you’ve never heard of

Mike Hearn
Mike’s blog
Published in
12 min readJul 6, 2015

--

Kotlin is a new programming language from JetBrains, the maker of the world’s best IDEs. After much searching, I have settled on it as the programming language I will probably use for the next 5–10 years or so.

I like Kotlin a lot and think it will be a very successful project. Someone who saw me using it in my open source work asked me to write about it, so in this article I’ll explain why I think Kotlin is good. Then I will discuss some of the problems and hiccups you may encounter if you start using it today. Finally, I’ll argue that now Kotlin is on the scene you should consider using the JVM if you aren’t already (e.g. because you use Go or Node).

Why Kotlin is good

At first this article may seem strange: normally language advocacy articles start by listing all the cool features the new language has. This article does not; we will get to them later.

I am going to start by telling you about other things, because a 2013 study showed that language features matter little compared to ecosystem issues when developers evaluate programming languages. That tallies with my own experience, so, here we go:

Kotlin compiles to JVM bytecode or JavaScript. It is not a language you will write a kernel in. It is of greatest interest to people who work with Java today, although it could appeal to all programmers who use a garbage collected runtime, including people who currently use Scala, Go, Python, Ruby and JavaScript.

Kotlin comes from industry, not academia. It solves problems faced by working programmers today. As an example, the type system helps you avoid null pointer exceptions. Research languages tend to just not have null at all, but this is of no use to people working with large codebases and APIs which do.

Kotlin costs nothing to adopt! It’s open source, but that’s not what I mean here. What I mean is there’s a high quality, one-click Java to Kotlin converter tool, and a strong focus on Java binary compatibility. You can convert an existing Java project one file at a time and everything will still compile, even for complex programs that run to millions of lines of code. This is how I am adopting Kotlin and I expect it to be how most developers do.

As an obvious implication of the above, Kotlin programs can use all existing Java frameworks and libraries, even advanced frameworks that rely on annotation processing. The interop is seamless and does not require wrappers or adapter layers. It integrates with Maven, Gradle and other build systems.

It is approachable and it can be learned in a few hours by simply reading the language reference. The syntax is lean and intuitive. Kotlin looks a lot like Scala, but is simpler. The language balances terseness and readability well.

It enforces no particular philosophy of programming, such as overly functional or OOP styling.

It imposes no runtime overhead. The standard library is small and tight: it consists mostly of focused extensions to the Java standard library. Heavy use of compile-time inlining means functional constructs like pipelines of map/filter/reduce compile similarly to an imperative version of the same code.

Combined with the appearance of frameworks like Anko and Kovenant, this resource lightness means Kotlin is starting to become popular with Android developers. If you’re working on Android, you will soon be in good company. You can read a report written by a developer at Square on their experience with Kotlin and Android.

Kotlin allows you to keep using your productivity enhancing tools. If you use IntelliJ, IDE interop is entirely seamless: code can be refactored, searched, navigated and auto completed as if the Kotlin code was Java and vice-versa. There is full support for debugging, unit testing, profiling and so on.

Beyond Android, I think Kotlin is highly suitable for enterprise Java shops. If you spend all day working on big Java codebases at even bigger companies, you should investigate Kotlin because:

  • It has strong commercial support from an established company. JetBrains is committed to the project, has a large and highly competent team working on it, has a stable business model and is even converting parts of their own flagship product to use it. Kotlin is unlikely to be abandoned any time soon.
  • Adopting Kotlin is low risk: it can be trialled in a small part of your code base by one or two enthusiastic team members without disrupting the rest of your project: Kotlin classes export a Java API that looks identical to that of regular Java code.
  • Because Kotlin focuses on readable syntax, code reviews are not a problem: they can still be done by team members who aren’t familiar with the language.
  • It targets Java 6, so you can use it even if your deployment makes upgrading to a newer JVM difficult.

Earlier this year I presented Kotlin to a team of Java and .NET architects at Swiss Re, a large reinsurance company. I started by defining a simple Java class with a few fields, toString, equals, hashCode etc. It was about 50 lines of code. By the time we had finished converting it to Kotlin (mostly automatically), it had shrunk to just one line of code. I then demoed other time saving features. They were enthusiastic and saw it as a potentially strong competitor to C# for their own projects.

I think Kotlin hits the sweet spot for enterprise Java devs, so even though Kotlin is free I expect JetBrains to make a killing from increased sales of the commercial version of their IDE. This will incentivise them to keep improving it according to the wishes of their customers.

Contrast this with many other language developers who are subsidised by unrelated products, meaning they have little reason to respond to the demands of their users when those demands conflict with pre-held ideologies.

Features

Kotlin stands out in a sea of new programming languages because of its focus on the ecosystem: JetBrains understand that productivity comes from more than convenient syntax.

Despite that, Kotlin has many useful features that make writing code in it pleasant:

  • We already mentioned null safety (optionality), that lets the compiler systematically flag potential null pointer dereferences. Unlike some languages, this does not involve an option type and is therefore zero-overhead. Other language features ensure it’s not inconvenient.
  • Lean syntax: type inference works everywhere, one liner functions take one line, simple structs/JavaBeans can also be declared in one line. Real properties generate getFoo/setFoo methods behind the scenes for Java interop. Functions can exist outside of classes.
  • Exceptions are unchecked.
  • Adding the data annotation to a class triggers autogeneration of boilerplate like equals, hashCode, toString, a copy method and variable spreading support (destructuring). This gives you convenient immutable classes without the need for builders.
  • But if you do need to construct complex structures, a clever intersection of language features makes builders clean and type safe (read: auto-completable). If you use Google Protocol Buffers to store structured data, that gets easier too.
  • Functional programming support with zero-overhead lambdas and ability to do mapping, folding etc over standard Java collections. The Kotlin type system distinguishes between mutable and immutable views over collections.
  • Extension functions let you add methods to classes without modifying their source code. This looks at first like a superficial bit of syntax sugar to avoid FooUtils style classes. Then you realise that doing it this way enables you to easily discover the new methods via auto-completion, lets you build powerful language extensions and lets you integrate existing Java APIs with other Kotlin features. Features like …
  • Operator overloading. But the good kind: no Scala / Perl style line noise here. Operators map to special method names, so can override the behaviour of the existing operators (including function invocation), but you cannot define entirely new ones. This strikes a balance between power and readability.
  • Kotlin does not have macros or other ways to redefine the language, but a collection of carefully designed features allow for libraries that act like language extensions far more than they act like collections of objects. A good example: would you like to use fibers, actors, and Go-style channels? A library called Quasar has you covered.
  • Markdown instead of HTML for your API docs. This makes writing JavaDocs much more pleasant. The “Dokka” tool, which is the equivalent of JavaDoc, can read both Kotlin and Java source code and generate combined doc websites, both with its own style and also in the standard JavaDoc HTML style.
  • Better generics. If you never fully got to grips with what exactly super and extends mean when put inside a type variable, don’t worry: it’s not you. Java’s generics really are just confusing. Kotlin fixes it.
  • Delegation (forwarding methods) can be done automatically.
  • The == operator does what you actually expect.
  • Would you like fast and convenient async programming? Of course you would.
  • String interpolation “works like ${this.example}!”
  • Function arguments can be named, optional and variadic.
  • Many, many other tweaks and improvements. If something annoyed you about Java, I give it 50/50 that it’s fixed in Kotlin.

Try it now!

Like many modern languages, Kotlin has a way to try it out via your web browser. Unlike those other languages, Kotlin’s tryout site is practically a full blown IDE that features fast autocompletion, real time background compilation and even online static analysis!

TRY IT NOW

Go on. I’ll wait for you to come back.

What’s the catch?

NOTE: This article was originally written in July 2015. By now this section has become inaccurate as various issues were fixed by JetBrains. I have marked the resolved issues below in bold, but left the text as-is.

Nothing in life is perfect, and alas, neither is Kotlin. Here are some of the issues I encountered whilst using the language.

  1. The data class feature is a very useful way to auto-generate JavaBean boilerplate, but it imposes severe limitations: such classes cannot inherit from anything, nor be inherited from. This in turn makes the “sealed class” feature rather less useful, as you can’t have a sealed hierarchy of data classes. JetBrains say they want to relax the constraints on data classes in a future version, when they figured out exactly what the behaviours involved should be. (Kotlin 1.1: data classes may inherit from other classes)
  2. There are no type aliases yet. So, function types have to be written out redundantly each and every time. (1.1 added type aliases)
  3. The IDE plugin still throws exceptions more often than it should. These don’t ever seem to break anything so are a minor nuisance compared to what a crash in a native-code IDE would be. But the “Internal IDE error” bubble can still be an irritant.
  4. By default, classes are final. You have to mark them as “open” if you want the standard Java behaviour. Some Java frameworks that rely on bytecode synthesis assume classes won’t be final and can fail or silently do the wrong thing when encountering Kotlin code. This isn’t Kotlin’s fault, but I’ve still had a non-trivial amount of time wasted by having to debug this. As Kotlin gets more widespread I expect such frameworks to improve. (1.1 adds some compiler plugins for popular frameworks that auto-open classes at the right time)
  5. Kotlin supports compile-time function inlining. This makes the use of higher order functions like map/filter/reduce very cheap at runtime, and so it’s common to use it a lot. Inlining also allows you to work around the JVM’s lack of reified generics in some cases and do non-local returns, like exiting a function from inside a lambda. These are good things! But they come at a cost: because the JVM doesn’t understand what’s happened, stack traces can sometimes get messed up. IntelliJ attempts to “un-scramble” stack traces that have been made confusing thanks to function inlining, but it’s still common to encounter exception stacks that refer to non-existent line numbers and other bizarre oddities. Ideally, Kotlin wouldn’t have to do this because JVMs would have all the features needed. But they don’t, so, we’re probably stuck with this unless the JVM learns how to handle functions that were inlined by the language frontend.
  6. Kotlin targets Java 6 bytecode. It does not use some of the improvements in Java 8. One minor issue is that the Kotlin standard library sometimes duplicates things that Java 8’s standard library also provides. Also, the compiler doesn’t use the “invokedynamic” bytecode to reduce the number of class files generated by lambdas, so Kotlin JARs that use a lot of non-inlineable lambdas can get a bit bloaty compared to Java 8. Fixing this is high up on JetBrain’s agenda so hopefully it’ll get done soon.
  7. Compilation inside IntelliJ is incremental and extremely fast (as fast as Java). Compilation through Gradle is slow because it’s not incremental at all. Avoid compiling through Gradle if you can. Again, this is high up on their list of things to fix. (fixed in 1.1)
  8. There’s no equivalent of macros or compiler plugins, so if you like macros from Scala or things like the Checker Framework from Java, sorry, you’ll have to do without.

Other issues to consider:

  • The community is small. Whilst the excellent Java interop means you don’t really need Kotlin libraries, they’re still nice to have and currently there aren’t many.
  • FP purists may feel the type system is lacking some of the more advanced features that can be found in Scala or Haskell. If you’re the sort of person who cares about this more than average, Kotlin may not be for you. The funKTionale library adds some constructs known from Haskell to the language like partial application, function currying, memoization etc.
  • Whilst it can compile down to JavaScript, this mode is experimental and a lot buggier/unfinished compared to the Java backend. (done in 1.1)
  • There is no standard style guide, and at points Kotlin gives you several alternative syntaxes to choose from. Kotlin written by different people may look different. This is in contrast to Go, which enforces style rigidly. (there is now a simple conventions document)
  • There is an Eclipse plugin for Kotlin, but it is naturally much less sophisticated than the IntelliJ support. Kotlin will work best if your team standardises on IntelliJ.
  • Kotlin is pickier about some things than Java. It will not autoconvert integers to longs and such, you are required to specify you want the conversion explicitly. This is because the language has a focus on correctness and attempts to fix the issues found in the famous “Java Puzzlers” book. JetBrains claim they nailed about half of them.
  • Because Kotlin targets Java 6 it is restricted to the features that runtime has. Whilst it can match or exceed C# in many areas, it lacks features like value types which aren’t yet a part of the Java platform.

Why you should now consider the JVM

In recent times I have encountered many startups using either a dynamic scripting language like JavaScript, or Go.

As I work in the Bitcoin space the use of dynamic languages is especially distressing; the lack of type safety in such tools has already led to serious monetary losses. Go is less error-prone but still suffers badly from lack of basic things, like a good debugger, fast GC, solid dependency management and reliable profiling tools.

In the last 15 years or so Java became strongly associated with verbosity and over engineering — and to a large extent that reputation was deserved. Enterprise Java became famous for classes with names like PathVariableMapMethodArgumentResolver. For the longest time I stayed away from the JVM, as I was sure the surrounding culture was not for me.

Eventually I was forced to return to Java by Android. It turned out that things had been changing. Whilst XML still popped up more frequently than fashion would dictate, the capabilities of the infrastructure had become very impressive. IntelliJ turned out to be much faster and more intuitive than Eclipse. Maven, though at first rather overwhelming, turned out to have a ton of features I’d often wished for in other build/dependency management systems. Newer web frameworks like Ninja and Play learned lightness from projects like Ruby on Rails. There were tons of libraries. Hardware had got better and the JVM had got more efficient. And so on.

The one big thing that hadn’t really changed was the language itself. Java was still annoyingly verbose and painful to write.

Now there is Kotlin, and with it the last traditional pain associated with the Java ecosystem is gone. You can write code that’s more expressive and more concise than even a scripting language, but with way fewer bugs and with way better performance. You can use all the great tools: just try the bundled VisualVM program for a taste of what’s available for free in this ecosystem, or check out the Chronon time travelling debugger to see what you can get if you’re willing to pay some money.

If JavaScript is your thing, try Kotlin’s JS backend. Or, run your existing code inside the Nashorn JS engine.

And finally, if you like Go because it generates self contained programs, check out the javapackager tool. It creates native, bundled packages for each platform, meaning on Linux you can get DEBs or tarballs that are entirely self contained with no JRE dependency. Sure, it’s not a single file once unpacked, but a single directory isn’t much harder to work with from a deployment perspective.

In short: if you have previously ignored the JVM ecosystem because it was terminally uncool, you should grab Kotlin and take another look.

--

--