Hacker News new | comments | ask | show | jobs | submit login

We built Roll for Android ( http://tryroll.com ) in Kotlin -- we currently have ~17k lines and have been working on it since this Spring.

We wanted to iterate on a lot of the software structure we came up with for our Swift iOS app, and for a bunch of pieces we needed a powerful type system. So rather than just stick with Java -- as others have said, it's way too verbose, we started looking at alternatives. We wanted a strong type system. Scala has too much overhead for Android. Kotlin really stood out for us. This document by Jake Wharton at Square https://docs.google.com/document/d/1ReS3ep-hjxWA8kZi0YqDbEhC... made the decision easier. So we took the risk.

And we love it!

The best features:

Null type safety!

Lambdas can be inlined! No need to be afraid of anonymous inner class overhead on the map/filter/fold of iterables.

Reified generics!

Extension functions!

Single-method interfaces/classes can be represented as lambdas! aka

  view.setOnClickListener(new View.OnClickListener() {
     @Override public void onClick(View v) { /* do something */ }

  view.setOnClickListener { /* do something */ }
This is great for things like RxJava.

Speaking of which, the Java interoperability is fantastic. Any Android libraries we've tried work great from Kotlin.

Using these tools, we've built a simple dependency injection framework, a handful of really useful extensions on things like T? (for example monadic bind), a hack for algebraic data types and pattern matching, and of course a fairly complex app.

Android Studio's Kotlin support is fantastic (good job JetBrains!) -- it's a pleasure to use.

I think Kotlin is totally worth using. The biggest issue for us is the build time. Our build takes anywhere from 1.5 to 6 minutes depending on how much you've changed, but I've found that the type system is strong enough that you don't have to do too many build-change a line-rebuild cycles.

We'll be starting a blog soon to talk about some of the stuff we've been doing, but if you can't wait send me a message bkase at highlig.ht if you're interested in hearing more (I love talking about this stuff)

Lambda inlining only works for very narrow scenarios. Passing a lambda to any Java API, such as event handlers in Android, will always have to resort to an anonymous class translation strategy, which generates a static or instance method in the outer class and a lambda class implementing the functional interface, forwarding to the outer class method. Non-capturing lambdas can be instantiated once and cached statically, forwarding to an outer class static method. Capturing lambdas can not be cached but still forward to an outer class static method. Lambdas capturing fields of the outer class can also not be cached and need to forward to an instance method of the outer class. Many lambdas passed to Android APIs will result in the last translation scheme.

Thanks for the info! I did know that passing lambdas to Java API calls still has to instantiate an anonymous inner class, but the details about what happens in each situation are new to me (and really interesting).

I'm sorry that I didn't make it clearer in my post (I'll edit it), but the thing I really appreciate is that I can use functional methods on objects (like map, fold, filter on iterables or our monadic bind method on optionals) and pass lambdas because I know it will be inlined. The inlining -- which should always happen this particular scenario (please correct me if I'm wrong) -- makes using these methods super cheap!

Only a look at the resulting bytecode will tell you what happens in your scenarios :)

No need for bytecode when a stacktrace will do :-)

    public static void main(String... args) {
        Runnable r = () -> {
            ((Object)null).toString(); // kaboom

Kotlin is great, but I would like to point out a few things:

> Lambdas can be inlined!

Kotlin's inline functions are meant to serve as a poor man's macro system (to implement simple control structures) and/or for argument type specialization -- not to save the "inner class overhead" because, guess what? There isn't one! While HotSpot's JIT will certainly not inline lambdas in every circumstance (though it's getting better), it will inline them in all cases where Kotlin's inline functions can be used (and many others where they can't). It is possible, however, that inner classes do have some overhead on Android.

> Reified generics!

Kotlin does not reify generics, and like in Java, that's a good thing! Java's erased generics are precisely what makes polyglot interop easy.

I haven't looked into it much in the past few years so it is possible the inner class overhead on Android is not significant anymore, but a few years ago it was definitely something to watch out for on Dalvik.

Again I wasn't being very clear, sorry about that: Kotlin doesn't always reify generics, but it can for functions you mark as inline if you want (it's useful!). Check out the inline function docs!

Inlining is also about performance. Classes impose significant memory and code size overhead even if HotSpot does inline the code eventually .... but much code is still interpreted. And Kotlin also targets Android. Finding documentation about what optimisations ART does is difficult, but I imagine it's got a weaker compiler than HotSpot if only because it's newer.

Not directly related, but for completeness sake: Java 8 lambdas only generate classes for capturing lambdas, and even then, only at runtime (a class file isn't generated). Kotlin can't quite do that because it relies on method handles and invokedynamic, which are missing from Android.

Also, there are few compilers anywhere with optimizations as powerful as HotSpot :) And HotSpot compilation is only getting better and better. Java 9 will even let us use Graal as the optimizing compiler (i.e. instead of C2), which can do this: https://twitter.com/ChrisGSeaton/status/619885182104043520

Your comment on build speed is interesting. Do you have a ballpark figure for Kotlin compile speed in lines per minute?

Kotlin is not actually slow to compile. The problem is that incremental compilation and gradle/android don't mix. So it ends up recompiling the whole thing each time.

I use Kotlin for non-Android projects with Maven, so incremental compilation works. Build times are not a significant issue, though the Kotlin compiler is still not as fast as the Java compiler is. I noticed from doing hotswaps when debugging processes that Kotlin seems to still compile too much, even when in incremental model. So I hope once JetBrains get stability under control they can spend some time optimising.

Unfortunately, not. We had a bad gradle config for a while so when we fixed that our build time jumped down from 6min incremental to 2min. However, I can tell you that I haven't noticed an increase in build time since we fixed our gradle settings which happened a few months ago and we have added code. Maybe it's a function of gradle modules (we have around 25)? If we ever spend a bunch more time trying to optimize our build time we'll write about it somewhere.

That single-method lambda thing I'd really good to hear. Most of my java code is just gluing together APIs, so lambdas don't do much for me unless I can use them with naive java APIs.

Mail to bkase at highlig.ht bounced back. Are you sure the mail address is correct?

Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact