kotlin


Kotlin to Javascript

In my opinion, one of the most interesting Kotlin features is the ability to transpile into Javascript. I’m a huge fan of GWT (Java -> Javascript), a lot of my projects are working in the web with GWT (like http://chess.mobialia.com or http://12chess.com), and I need to know if Kotlin is going to be able to replace Java+GWT in the near future.

So I tried to compile the Carballo Kotlin code to JS (as a NodeJS app) in the “js” branch: https://github.com/albertoruibal/karballo/tree/js, and I couldn’t make it work yet. I found some problems that I will detail in this post.

GWT includes a reduced version of the JRE, without some classes and methods, but Kotlin is much more radical: To compile a Kotlin code to JS, it cannot reference any java.* class, so forget about java.lang.*, java.util.* or java.io.*.

No basic java types

Integer, Character, Boolean… are a Java classes and they cannot be used, so a lot of common operations must be done the “Kotlin way”, i.e.:

Integer.parseInt(myString) -> myString.toInt()
Character.toLowerCase(myChar) -> myChar.toLowerCase()
Integer.MAX_VALUE -> Int.MAX_VALUE

Emulating Java classes: System, Math, Random, Arrays, Date

These classes are not available when building to JS. To avoid changing the original code and migrate seamless from JVM to JS, I created auxiliar classes with the methods used in the code:

  • System: I implemented currentTimeMillis() (calling the JS Date object), exit(), arraycopy(), and an empty gc()
  • Math: When building for JS, the java.lang.Math class must be replaced by kotlin.js.Math, using this class avoids to change a lot of code
  • Random: Using kotlin.js.Math.random()
  • Arrays: Implementing some variants of the fill() method
  • Date: partial implementation to get the current date

Other problems

  • IntelliJ does not allow to mix the Java and the JS Kotlin stdlib in the same project, so I hat to create a different branch “js”
  • No Threads nor Coroutines support in JS jet
  • Kotlin’s readLine() (to read lines from stdin) is only available in the JVM stdlib
  • String.toBoolean() is only available in the JVM stdlib, I fixed it defining a extension function in the same package: 
    inline fun String.toBoolean(): Boolean = "true".equals(this.toLowerCase())
  • No support for asserts in the JS compiler
  • Some annotations aren’t available @JvmOverloads, @Throws…
  • No LinkedList
  • No StringBuffer, but in this case it’s better to use Kotlin’s StringBuilder
  • Missing StringBuilder.setLength() method (I sent a pull request to Kotlin implementing setLength() and substring())
  • It does not allow returns into synchronized blocks
  • No printStackTrace() on exceptions
  • No JUnit tests in JS, so I removed the tests in the “js” branch

Overall conclusion

After solving all these problems, the Kotlin2JS compiler is introducing bugs that don’t allow the karballo engine to work.

Kotlin2JS isn’t production ready, and years behind GWT.


Converting Carballo to Kotlin

Kotlin is a JVM language developed by JetBrains: http://kotlinlang.org gaining momentum among Android developers. Kotlin has interesting features like:

  • It can be compiled to bytecode compatible with Java >=6, allowing to use a lot of Java 7-8 features (lambdas…)  in Java 6 bytecode (=Android)
  • It can be transpiled to Javascript (like Java with GWT)

So I decided to migrate the Carballo Chess Engine code to Kotlin (and his name is Karballo) to make some experiments and having some “fun” :)… but it became a non-trivial task, the converted code is at: https://github.com/albertoruibal/karballo.

Converting the code

To start working with Kotlin I installed the Kotlin plugin for Android Studio (=IntelliJ) from:

File->Settings->Plugins->Install JetBrains Plugin

Once the Kotlin plugin is installed, it’s quite easy to convert java source files to Kotlin with: CTRL + SHIFT + ALT + K

Conversion problems

The Java to Kotlin code conversion does not work perfectly, the Carballo conversion arose these errors:

  • Kotlin is strong typed, you cannot compare a long against the literal ‘0’, you must use ‘0L’… I had hundreds of this comparisons
  • A Long cannot be initialized with an unsigned hex literal if the value does not fit in the signed type, it gives a “Value out of range” compilation error ,  so you cannot do:
    var variable = 0xffffffffffffffffL

    The solution is to convert the literals to a signed decimal:

    var variable = -1
  • Error “Property must be initialized or be abstract” with attributes not initialized in the constructor, solved adding the “lateinit” modifier to the declaration of the attributes (yes, Kotlin knows if you are initializing the attribute in the constructor)
  • Strange toInt() insertions:
    pieceNames.indexOf(pieceChar.toInt())

    should be:

    pieceNames.indexOf(pieceChar)
  • Variables of type Byte cannot be used as array indices, I had to manually change many vars from Byte to Int
  • Kotlin does not allow assignments in expressions, so it’s impossible to do:
    while ((node.move = node.moveIterator.next()) != Move.NONE) { 

    I manually had to change some cases to the more verbose:

    while (true) {
        node.move = node.moveIterator.next()
        if (node.move == Move.NONE) {
           break
        }
  • The binary operators do not work in multi line if they are placed at the beginning of the second line, only if they are at the end of the first, so:
    var myLong : Long = long1
        or long2

    does not compile, it must be:

    var myLong : Long = long1 or
        long2
  • It didn’t recognize some custom getters and I had to merge them manually, I like a lot how they look in Kotlin (notice the use of the special word “field” to avoid calling the getter recursively):
    var lastMoveSee: Int = SEE_NOT_CALCULATED
        get() {
            if (field == SEE_NOT_CALCULATED) {
                field = board.see(move, ai)
            }
            return field
        }
  • The conversion process got hung with two complex classes: CompleteEvaluator and ExperimentalEvaluator… I had to kill IntelliJ. I converted the CompleteEvaluator class copying to a new class small chunks of code.
  • Kotlin’s when() statement do not work like the Java’s switch->case, as it hasn’t breaks, you cannot jump from one option to the next excluding the break: the conversion duplicated a lot of the MoveIterator code and I fixed it manually.
  • Some other strange errors like wrong expressions and missing parenthesis…

Some things of Kotlin that I don’t like (yet)

Some are part of the claimed Kotlin “features”:

  • Kotlin does not has primitive types, but it seems to not affect the performance…
  • There is no ternary operator in Kotlin, it’s replaced with “if (…) … else …” expressions: This increases a lot the verbosity, al least in my code
  • Kotlin’s crusade against NullPointerExcepcions: It a type allows null, it must be explicitly indicated appending a question mark to the type:
    var myString : String? = null

    To convert a nullable var/val to a non-nullable, you should use the !! operator, this forces a NullPointerException if the value is null (and it seems that you are shouting to the IDE…):

    var myString : String? = "hello"
    var myStringNotNull : String = myString!!
  • Static fields and methods are grouped in a “Companion Object”
  • Compilation is slower than pure Java
  • Many bugs running from Android Studio non-android projects (IntelliJ worked better for me)
  • Couldn’t get the JS compilation working yet

And other things that I like

  • The full interoperability with Java
  • Type inference, normally I continue to specify the types, but in some cases it saves a bit of code
  • Data classes, they will save you hundreds of lines of boilerplate code https://kotlinlang.org/docs/reference/data-classes.html
  • Array initialization with lambdas
    nodes = Array(MAX_DEPTH, {i->Node(this, i)})
  • The singleton pattern is embedded in the language: using “object” instead “class” assumes that the class is a singleton
  • Visibility is “public” by default, with the access modifier “internal” it can be accessed only from the same module
  • Implicit getters / setters
  • No need for “new” to call constructors
  • And much more…

Performance

I’m my first tests, I’m not noticing any performance downgrade (or upgrade) over the Carballo Java version.