It doesn't matter how many languages you have learned, learning yet another one is always a wonderful experience. I have been working for a couple of months with Kotlin. Have got one app to ready for production state and another in the works.
To cut to the chase, I am really impressed by this language. As in really really impressed. And so I decided that I should write a few posts that can help readers get a better idea and learn about this language. So I started writing out the series and am already onto the third post now. But as I was writing it, I realized what I was writing was really about the mechanics of the language. Not so much about its spirit. Because when one gets into the tactical nitty-gritty details, one tends to miss the forest for the trees. So I decided to pen that here before I start that series (next week), and here are my few thoughts about why I really enjoy the language.
One of the reasons there is a lot of enthusiasm with the language is because it can be readily used for programming to the Android platform. That is how I ended up learning it. But very soon, my enthusiasm spread into the desktop/server space where I think Kotlin deserves a shout out for a very very credible effort.
At its core, programming is an expression of logic. And programming languages offer the core building blocks of logic. Languages such as assembly (and perhaps C) are very powerful in one particular way. They give the programmer extremely fine levels of control. But bog him down with very low-level tactical details. Thus, the programmer gets buried by too many likely situations where he can make mistakes, and too many detailed tasks for him to orchestrate together. These languages have given him the necessary abstractions, but these abstractions are still too low level for him to leverage effectively. C++ introduced Object Orientation into this space, but philosophically it still remained a very similar language in terms of the levels of abstraction it worked upon (except for the obvious OO change).
Then we have languages such as Java. It is undoubtedly a very successful language. Some of the strengths that made it so successful were platform neutrality, binary compatibility using a cross-platform JVM, and the fact that it was a much better C++ due to garbage collection. However, it never did achieve an improvement in the levels of abstraction. Plus the amount of boilerplate that is required for declaring even classes with little functionality is immense.
You then have languages like Python, Ruby, Groovy, etc., which help cut down boilerplate quite a bit. The same class in Java can be written with many fewer lines of code here. I have worked extensively with Python, so will talk a bit about it here. Apart from cutting down boilerplate, Python helps by at least attempting to introduce higher levels of abstractions. For example, what a list comprehension can do in Python in 1 line can sometimes take tens of lines in Java. If one chose to not use a list comprehension, one could still get equally good results using library functions such as map/reduce/filter/any/all ... etc. One of the greatest strengths of Python is it has attempted to (and IMO successfully managed to) retain much more closeness to English than any other programming language I am aware of. Which makes it a bit easier for programmers to deal with the constructs it offers. While it is OO, and also has many pre-OO characteristics, many contributors added capabilities to it that were certainly rooted in Functional Programming (FP). So here is a language which is dynamically typed, expressive, English-like, etc. What's there not to like?
You get the answer when you write code in a language like Erlang. It is also another beautifully simple programming language. You can be coding effectively in a matter of a couple of weeks. It has some superb characteristics such as pattern matching, which Python couldn't attempt to provide. It also has one other big difference. It is built around immutability. For all practical purposes you cannot change the value of a variable once initialized with a value. (It's not even correct to call it a variable, so it's called a binding.) And once you code using a language like this, you understand that, try hard as one might, the lack of immutable structures will always keep Python a poor competition in the functional space. But of course Erlang has many other languages, and then other aspects that are much more attractive in Python. So you are kind of in the sad situation of having to choose between one of two languages with very different characteristics and each being very attractive in its own way.
But I digress away from Java and so come back to it. It is clear that while Java was a superb introduction for the mid-1990s, it is a language that shows its age. Lots and lots of people are writing code with it, but not liking it. Mind you it is not JVM they are unhappy with. Like Erlang Beam, Java developers are in general very happy with the JVM. (That wasn't always the case, but it all changed in 2003.) So you have a write once run anywhere language that has automatic garbage collection, is statically typed, has decent OO support and that runs really really fast? What more would one want? Well for starters, it is very very verbose, the conventional paradigms are built around mutable data structures, and it still hasn't managed to elevate the essential programming abstractions from the tried and tested but old and dated for loop.
That brings us to the other languages on the JVM. There has been a large crop of languages on the JVM including languages that support Python; Ruby syntaxes; Groovy, which is a dynamically typed language with some really good abstraction constructs thrown in; Clojure, which is at least in terms of its primary differentiator a scheme on the JVM (some say Lisp, I wouldn't know since I don't know either of the languages particularly well); and there is Scala, which attempts to really take on a huge challenge of being interoperable with Java, and offering substantial levels of capabilities built around types.
So what does Kotlin bring to the table?
- Runs on the JVM.
- Is extremely good at interoperating with existing java code and libraries.
- Is statically typed (thus far far easier to refactor).
- Has a bit more evolved type system than Java.
- Is much safer than Java. Nullability is a first class compiler level construct—something that helps address a large number of likely defects (like the billion dollar bug). There is a lot to write home about here.
- Has a clear system of distinguishing between mutable and immutable structures. While it doesn't make an opinionated stand in favor of immutability, it gives you the programmer enough helpful constructs to chart your course down that path.
- Has support for type inference, which helps reduce your boilerplate and keeps code shorter.
- Has a wonderful story to tell in terms of it providing programmers an ability to write extension functions to existing classes (or for that matter even primitives).
- Has support for Higher Order Functions, Higher kinded types.
Does that make it the better language? I personally think it has achieved amongst the best set of tradeoffs that are attractive to me (obviously YMMV). And here's why I enjoy it so much.
- Its expressivity is comparable to or superior than Python for keeping your code short and sweet.
- It being a statically typed language helps enormously speed up refactoring exercises. Even though I have been using it for only two months, I went through at least two brutal refactoring cycles and found Kotlin code to be a pleasure to change.
- It is safer, a lot safer than Python/Java, and delegates one of the most frequent tasks of programming (null checking) to the compiler. That's a huge effort of the back along with reduction in number of probable defects. Surely nothing to complain about here. And believe me this is a big plus point.
- Uses the JVM, which is a fine and fast runtime engine.
- It is easy to learn. I actually went through the reference from start to end in 2 days and was a half decent programmer in about a week's time. Since then I have written functional libraries for Option, Either, Stack, List, HTTP Clients, XML parsing helper libraries, and rather complex X509 certificate trust chain verifiers. I have started playing around with more functional constructs such as currying, functors, etc. Look forward to working more with typeclasses. I just don't think I could have had such a pace of progress with any other language.
- It is non-opinionated. For XML parsing I wanted to ensure very low memory footprint because I wanted to use it on Android. I was able to write a library that heavily used mutation even as it maintained very low memory usage by keeping extra object allocation counts down. For another situation I wanted to use the immutable functional paradigm, and Kotlin happily let me create my own Option/Either/List classes and use that paradigm end to end. It doesn't get in your way. And focuses on getting work done.
- I have been interfacing with a large number of Java libraries. The interoperability has been an absolute breeze. It is actually refreshing to go through that experience. Doesn't matter if you are dealing with HTTP client APIs, integrating into a Slack HTTP service, interfacing with Java PKCS API—Kotlin does it easily and safely.
In a nutshell, I can write code that is safer, shorter, uses better building blocks, is easier to grok, gives me all the nice capabilities such as HOFs, lambdas, pretty competent type system that gives me all the feedback necessary when writing code and makes refactoring a breeze, and interoperates nicely and leverages the JVM universe.