back
38 comments
Multiplatform docs here: https://kotlinlang.org/docs/reference/multiplatform.html

Example from the docs:

  // Common module
  
  package org.jetbrains.foo
  
  expect class Foo(bar: String) {
      fun frob()
  }
  
  fun main(args: Array<String>) {
      Foo("Hello").frob()
  }

  // JVM module
  
  package org.jetbrains.foo
  
  actual class Foo actual constructor(val bar: String) {
      actual fun frob() {
          println("Frobbing the $bar")
      }
  }
I brought up how I thought the `expect` and `actual` keywords (but primarily the latter) added unneeded verbosity in the Kotlin Slack awhile back and was pretty much shrugged off, despite folks on the Kotlin team admitting that they exist in part to make the IDE's job easier, but weren't actually necessary.

It leaves a sour taste in my mouth, but I suppose it might be because I'm familiar with projects in C/C++ where, if a symbol goes undefined, the compiler/linker is smart enough to tell you that without being hand-held.

You are not alone.

I also believe they could have manage it without polluting the code with expect and actual.

Probably the compiler would need some extra work to do the matching.

True, but on a scale of 1 to 10, with 10 being amazing, Kotlin is quite high, maybe an 8, and your point is only a minor nit.
You seem very fond of Kotlin.

I hear a quite a bit about it lately, but as I haven't had the chance to play with it yet, I was wondering why would one choose it over Scala.

I find it to be more pragmatic and easier on the eyes. It's easier to learn and also being adopted by more mainstream ecosystems like Spring, Android, Gradle, etc. IDE support is obviously top-notch as well.
When doing Android development.

Kotlin has gotten official support from Google, including documentation as part of Android SDK.

It's not really "to make the IDE's job easier", it's to make it explicit that the given class needs to match a certain contract, and to make the validation errors more clear.
So expected is import and actual is export in unit module parlance?
It's a bit different from a regular export/import relationship. An exported declaration is usually made visible to an unlimited number of clients, and an actual declaration matches a single specific expect declaration.
That’s why I said units, as in program units (Flatt, Findler, etc...). I added a module system to java that did the same thing using light bytecode rewriting in the linking step (kotlin seems to do structural matching, but doesn’t have a reconfigurable linker I guess); https://dl.acm.org/citation.cfm?id=504311.504298.
I know precisely why they did this. They did it because IntelliJ cannot cope with a file being part of two different modules.

Scala/JVM + Scala.js has been sharing code for almost three years now, and it works perfectly out-of-the-box in Eclipse. However, in IntelliJ they barely made it kind-of work by creating an artificial `shared` module (in addition to the normal `jvm` and `js` modules) that `jvm` and `js` depend on. But `shared` cannot see the definitions from `jvm` and `js` with that model. [1]

So because IntelliJ cannot deal with shared source files, they bastardized the language to work around that limitation.

They really should have fixed the IDE instead.

[1] https://youtrack.jetbrains.com/issue/SCL-7859

That's silly. I guess devs got lazy and decided to go with a convenient wart instead of conceptual purity. I was thinking about using Kotlin for multiplatform stuff but now I'll likely look elsewhere...
>I guess devs got lazy and decided to go with a convenient wart instead of conceptual purity

Aka pragmatic.

But it can all be fixed -- you can do a hostile fork and improve upon their code together with other non-lazy developers. You'd get much more done than the Kotlin team, being non-lazy and all...

Hostile fork has a low chance of survival; for one you should wait until Google cuts all vital pieces off JetBrains as they are trying for the past few years anyway, yet making JetBrains people somehow flattered about it... MS is at least openly trying to kill them.
requirement outjection vs. dependency injection
that is so verbose I still can't believe it's true. sorry actually true
I really like some of Kotlin's decisions, but I prefer Haxe's approach to this.

For single target code, you can prefix the class module with the platform tag (e.g. "js" or "java"). These module names are reserved within the compiler and any code therein is restricted to their respective targets.

Another way is to use conditional compilation markers to indicate specific target-compatible boundaries. E.g.

  #if java
     public function print(s : String) java.lang.System.out.println(v);
  #end
That method only exists on the java target, and the compiler will complain otherwise.

Conditional compilation also allows for more fine-grained support of multiple targets:

  #if java
     public function print(s : String) java.lang.System.out.println(v);
  #elseif js
     public function print(s : String) console.log(v);  // as a simple example
  #end
This makes a cleaner organizational distinction between extern code that must remain target specific, and true cross platform code that can be called on any of the supported targets. Editors can pick up on this very easily and provide early warnings as you are typing, and doc generators can also inspect these directives and show api availability between targets in the rendered docs.

(self-disclosure: Haxe compiler contributor)

In Kotlin, every module contains either common code or platform-specific code. I'm not sure why you consider the module-level distinction to be less clean than being able to mix common and platform-specific code randomly within a single file.

And your example shows that there is no way to verify that each module provides a consistent API.

> In Kotlin, every module contains either common code or platform-specific code. I'm not sure why you consider the module-level distinction to be less clean than being able to mix common and platform-specific code randomly within a single file.

Module-level distinctions are per-target. It doesn't get any more clean and clear than that, does it? The trade off is that it's a bit limiting. Conditional compilation is where you can start to pick and choose targets/features and handle more sophisticated cases.

> And your example shows that there is no way to verify that each module provides a consistent API.

This is easy to do by providing a common interface definition and a simple build class that targets each language you're interested in. It's a good idea in a formal testing suite for a complex library.

I only do that in a handful of projects though, most of the time cross-target code is just a few special exceptions. In that case, you'd call out the special case, and then use the #else directive for the rest:

  #if java
     public inline function print(s : String) java.lang.System.out.println(v);
  #else
     public inline function print(s : String) Sys.println(s); // most of the time basic ops are covered by std lib.     
  #end
FWIW I've "inlined" things here with the keyword. This lets you alias cross-platform methods like this without extra function call overhead.
How good is Haxe? What are its issues, pros/cons? I am looking for something similar; Kotlin was one choice though after today I am not sure about it anymore, so what do other frameworks offer?
Eclipse plugin is stuck on 1.1.1, 20 March 2017.

I understand JetBrains would like everyone to use InteliJ and they aren't required to support other IDEs, but it prevents adoption on many IT departments that only allow for Eclipse on their dev images.

We're now resuming the development of the Eclipse plugin, and you'll see new updates very soon.
Thanks for the update.
I really hope this release means https://github.com/JetBrains/kotlin-native will get brought onto the express lane! It's either Kotlin or Swift that will go full cross platform for end user applications (JS/Android/iOS) and Kotlin right now has the advantage! (Swift doesn't officially support the Web story.)
> "Working with the Command Line Compiler"

https://kotlinlang.org/docs/tutorials/command-line.html

> "We can download it from GitHub Releases."

https://github.com/JetBrains/kotlin/releases/tag/v1.2

404

We've fixed this already; the fix is being deployed. The correct URL is https://github.com/JetBrains/kotlin/releases/tag/v1.2.0

    $ which kotlinc
    /opt/src/kotlin-1.2.0/bin/kotlinc

    $ kotlinc
    /usr/bin/env: ‘bash\r’: No such file or directory
Seems to have been saved with MS Win line ends, which causes a problem with bash on Ubuntu.
Do you have to use bash to run it? Seems like that should have used sh to get the biggest install base (Groovy does this).
Yes, we have an issue in our issue tracker for that already; will fix in the next update. Sorry!
How does Kotlin multiplatform compare to React? In React I can:

- server side render a page to HTML and send it to browser, or

- send down the React code as JS and render in browser, or

- use React Native to write sorta native Android/iOS apps and reuse some of my JS codebase

Does Kotlin cover the same use cases of server-side render & browser render & native mobile apps?

You can do isomorphic (server-side and client-side) rendering in Kotlin. For mobile UI, you can build native UIs in Kotlin for Android and for iOS, but the UI code will be different for each platform, built on the native API of the corresponding platform. At this time we have no plans to build a solution for reusing UI code between mobile platforms.
If I can't reuse code between iOS & Android then what is the benefit of using Kotlin over just building mobile apps in Java & Swift?
IMO, It's just a different approach to the idea than the React world. I would assume the idea here is that you always want to write your UI layer "natively" in order to take full advantage of platform-specific performance accelerations/hardware APIs, but the entire stack underneath what's actually rendering visual components would be shared.

It forces you to start out more modular between your UI code and domain logic code, whereas React (& React Native) leaves the door open right at the start for tight coupling between UI code & domain logic, unless you expressly build this separation into your initial architecture.

They said UI code. You shouldn't be reusing that anyway. You should be writing stuff to take advantage of the native platform.
You can't reuse UI code between iOS and Android. You do have the ability to reuse the business logic code (domain models and so on).
Great idea , but for many react apps (both native and JS) domain models doesn’t exists. Redux + graphql apps let me eliminate even more logic. So what we actually share between react native and react JS apps are : graphql queries, reducers, saga middleware. The rest is just UI. In my usecases there is nothing to share using Kotlin.
Why do you compare Kotlin against React? They can work together: https://blog.jetbrains.com/kotlin/2017/04/use-kotlin-with-np...

Write your React code in Kotlin, compile to JS and use it everywhere where React is supported.

I will still bet for scala, at least it makes more sense for me considering the usage of Apache Spark / Flink