From Swift to Kotlin and Back Again

This article is a reaction to the From Java to Kotlin and Back Again article, which I disagree with on pretty much every single point.

Kotlin is popular, Kotlin is familiar if you are coming from iOS development. Kotlin gives you compile-time null-safety and less boilerplate than Java. Naturally, it’s better than Java. If you are planning on cross platform development, or simply leveraging your existing Swift knowledge on Android or other JVM platforms, then you should definitely give it a try.

I peeked at Java 10, but now I am doing everything in Kotlin

I have my favourite set of languages for any given platform. Swift on iOS, Kotlin on Android. Typescript + Vue.js on web, and recently I have been testing the waters on Kotlin on the backend instead of Typescript + node.js. There is a large segment of Java proponents in the backend community. They tend to make everything extremely difficult.

The entire toolchain around Java seems to be set up as to take away all the hassles of the language instead of simply using a better language. Similarly, the Node + Typescript toolchain seems to involve double efforts in first handling all the quirks of javascript, and then tagging on an attempt at type safety which brings its own set of quirks in Typescript.

Coming from Swift, the switch to Kotlin was so graceful and easy, that Java didn’t even come close to making the cut.

Here are the reasons why:

  • Type inference
  • Compile time null safety
  • Similar type declaration
  • Functional language
  • Collection literals
  • Flat learning curve

A quick note about name shadowing, which the original article starts out with: Name shadowing is fully allowed in Javascript, and without a linter is still an issue in Typescript. It is still allowed in Swift and Kotlin but both languages emit a warning if you choose to use this feature. The original author makes a big deal out of it, but given that a warning is emitted, this should be a non-issue.

Type inference

In Kotlin (like Swift), when you declare a var or val, you usually let the compiler guess the variable type from the type of expression on the right. We call it local variable type inference, and it’s a great improvement for programmers. It allows us to simplify the code without compromising static type checking.

For example, this Kotlin code:

var a = "10"

would be translated by the Kotlin compiler into:

var a : String = "10"

Java 10 has adopted this, only partly. You can say

var a = "10";

but Kotlin is still slightly better in this field. You can use type inference also in other contexts, for example, one-line methods.

Compile time null-safety


Null-safe types are Kotlin’s killer feature (in Swift they are table stakes because it compares itself to Objective-C). The idea is great. In Kotlin, types are by default non-nullable. If you need a nullable type you need to add ? to it, for example:

val a: String? = null      // ok 
val b: String = null       // compilation error

Kotlin won’t compile if you use a nullable variable without the null check, for example:

println(a.length)          // compilation error
println(a?.length)         // fine, prints null
println(a?.length ?: 0)    // fine, prints 0

Once you have these this two kind of types, non-nullable T and nullable T?, you can forget about the most common exception in Java — NullPointerException.

At this point, the author goes on to complain about all the evils of nullable types, little does he realise that that he mentioned the correct approach (the elvis operator) in his original example, making the rest of his gripes a non-issue.

Similar type declaration

In functional programming languages, functions tend to be declared in a way which is closer to a mathematical function, with the function name on the left, and the result type on the right.

In Swift we write:

func a(b: Int) -> Int

similarly, in Kotlin, we write:

fun a(b: Int): Int

and in Typescript:

function a(b: number): number

The older c style of function declaration is left behind in favour of something which is well known and easily recognisable across modern languages.

Functional language

A functional language programmer comes to Kotlin.

“Hi Kotlin, since I’m writing code in a functional language, I don’t really need static variables.”
“Not really. If you want some static state maintained in the scope of a file, you can simply use a top level fileprivate var outside your class scope.”

There is a notion of a companion object if you really, really, really want something that behaves like a static variable, but I rarely find any need for it in real world scenarios.

Collection literals

In Java, initializing a list requires a lot of ceremony:

import java.util.Arrays;
...
List<String> strings = Arrays.asList("Saab", "Volvo");

Initializing a Map is so verbose, that lot of people use Guava:

import com.google.common.collect.ImmutableMap;
...
Map<String, String> string = ImmutableMap.of("firstName", "John", "lastName", "Doe");

In Java, they are still waiting for the new syntax to express collection and map literals. The syntax, which is so natural and handy in many languages.

Swift:

let list = ["Saab", "Volvo"]
let map = ["firstName": "John", "lastName": "Doe"]

Typescript:

const list = ['Saab', 'Volvo']
const map = {'firstName': 'John', 'lastName' : 'Doe'}

Kotlin:

val list = listOf("Saab", "Volvo")
val map = mapOf("firstName" to "John", "lastName" to "Doe")

Not really any surprise here. Having functions for this purpose makes this feel a little more functional, but overall it is exactly the same.

Flat learning curve

If you think that you can learn Kotlin quickly because you already know other modern languages like Swift or Typescript — you are completely right. If you are coming from Java you should not fall into the trap of thinking that any other language which can be compiled to run on a JVM is exactly like Java. Kotlin is indeed a completely different language, just like Typescript or Swift is.

Final thoughts

Learning a new technology is like an investment. We invest our time and then the technology should pay off.

I can definitely say that as investments go, the transition from Swift or Typescript into Kotlin was a small investment with a high return on investment. I’m not saying that Java is a bad language. I’m just saying that given the choice — which definitely is an available choice in a progressive workplace like Tradeshift — I would choose Kotlin over Java any day.