1. 4

  2. 14

    Having programmed Kotlin professionally (and at least at times, very much for fun) for a couple of years, I get where he’s coming from on some of this, but most of it’s…somewhere between wrong and weird.

    Starting at the beginning, I honestly just have no idea what the frak he’s trying to get at in the rant on for loops. He might have a point there that I’d agree with, but I can’t even tell what it’d be. Yeah, for loops are nominally syntactic sugar, except that special cases, such as for (x in start..finish) or for (x in aPrimitiveArray) are special-cased to compile down to optimized JVM bytecodes. (You can trivially verify this in IntelliJ by just asking the Kotlin plugin to show you the Kotlin bytecodes for a given function.) So it’s giving you a free abstraction. And that is bad because why exactly? Because I have the ability to extend for for my custom classes by implementing an iterator? Because they’re taking advantage of the fact that the compiler can optimize certain cases to actually do so? Good C++ compilers do this (thankfully!) with the STL, and so do even things like Common Lisp compilers if they’ve got enough type info to make the jump. I genuinely just don’t even get his point.

    In several places, he demonstrates a profound lack of familiarity with Kotlin or the JVM. His entire rant on nullable types in a threadable situation appear to be resolved by the .let function, as far as I can tell. His rants on generics are actually the thing I can get closest to agreeing with, but since Kotlin is very deliberately targeting frictionless interop with Java, you do at some point have to acknowledge that the JVM (unlike the CLR) implements generics with type erasure, which is gonna put limits on how generics work. (I genuinely believe Kotlin’s introduction of inlined generics, which function similar to C++ templates-in-practice, help a ton here, but I would agree that’s a wart.)

    The weirdest one to me was his data structure rant. Data structure functions include not just mapOf, arrayOf, and listOf, but also setOf, immutable<Foo>Of, and several other variants. And the mapOf is usually written mapOf(foo to bar, baz to quux, frob to plox), which is a lot more readable than what he proposes. (And also uses totally user-available Kotlin features, incidentally, to add a to operator applicable in the mapOf context, and in turn gets the above compiled down to optimized Java bytecodes–so while this is great for maps, it also means that you, the user, can do the same thing for your own data types, too!) To me, this is a feature, not a bug; I want lightweight syntax for those things, but I definitely do not need that lightweight syntax to be {} or [] specifically, and Kotlin, recognizing how common it is in Java to alternate between new HashSet<>(...) v. new ImmutableHashSet<>(...) and the like, opted to have a user-extensible mechanism for prims instead of blessing a few of these at the expense of others. We can argue about that particular design trade-off, but it doesn’t suck.

    Beyond that, though, a huge part of Kotlin was the introduction of typesafe DSLs that are stupidly easy to implement. So the actual thing you should do, if you find yourself writing 30 lines of mapOf crap, is…take a whole five minutes to write a little DSL for whatever the horrible hell you’re trying to do, because whether you’re writing YAML, JSON, Python bare arrays, Factor immediates, or whatever, I am going to hate you if you’re using a massive hash table to represent some concrete domain object that you totally could’ve statically typed.

    So, as a quick gloss: he’s both unfamiliar with basic parts of Kotlin, and unfamiliar with the JVM. And I’m most annoyed with that because it means he’s missing issues that would actually be really legitimate to bring up.

    You want some actual problems? Its compiler’s still quite slow. Not Scala-slow, but enough slower than Java that I occasionally think about how much I really need Kotlin for a given file. There’s a weird asymmetry between inlined generics and generics, and that’s confusing, even when you do grok how the JVM works under-the-hood, in part because you can’t trivially know while writing code whether any given function is inlined or not. The DSL syntax sugar was genuinely sugar until 1.1, meaning that there wasn’t any concept of hierarchy, which meant you could write syntactically valid but meaningless crud inside a DSL. (Think <td> outside a <tr> in an HTML DSL, for example.) Or to do the correct version of one of the author’s main points: the way that the dataThingieOf() inline functions are implemented means that while setOf(1), setOf(1, 2), setOf(1, 2, 3), etc., are all valid and optimized, setOf() is a compile-time error, requiring an emptySet() function to serve the same purpose. You thus have fooOf(), immutableFooOf(), and emptyFoo() for all the common data types. And to add insult to injury, emptyFoo() is inevitably empty[immutable]Foo(), which means they’re not suitable if you need to build up the object later.

    Kotlin has flaws. The flaws are real. I still drastically prefer it to Java whenever I can get away with it, and I think its flaws are, for the most part, symptoms of the JVM, rather than Kotlin itself. And that all said, I prefer C# and F# over the whole lot. But the concerns proposed in this particular post? I’m not convinced they make sense.

    1. 6

      I suppose the article is trying to point out flaws that are so rare or contrived that by doing so, he paints a positive picture of Kotlin, because all of its flaws are either rare or contrived.

      The problem is that half the time reading the article I can’t tell if it’s satire or not. The author’s flaws are contrived and based on ignorance of the finer details of JVM, e.g., ignorance of type erasure.

      Feels like a waste of time, really. Why do satire when one can’t do it well?

      1. 2

        that was my reaction too - it was clearly satire, but it was pretty heavy-handed satire that did not make it’s point very well

      2. 2

        I’d be interested to hear why you prefer C# over it. I’ve worked in C# a lot and just played with Kotlin a bit, but my impression was that it took Java from 3-4 steps behind C# to a step or 2 ahead of it in terms of language features.

        1. 4

          My preference for C# has (comparatively) little to do with C#, and a lot to do with the CLR, but things in that bucket include:

          • Value types
          • Reified generics
          • Unsigned values
          • The unsafe construct, and its making available of raw pointers
          • P/Invoke
          • Asynchronous libraries available in core

          While Kotlin does some things better than C# (inlined functions, for example, or the distinction between val and var, or (as of Kotlin 1.1) arguably coroutines/async-await at the language level), it also trails behind on all the above, plus either hasn’t kept up or can’t keep up in other areas where the JVM isn’t where the CLR is.