top | item 15649082

(no title)

danneu | 8 years ago

I'm really rusty, but if I can recall the simplest example correctly, you can't just naively go from this Kotlin code:

    Server { req -> Response().html("<h1>Hello world</h1>") }
to this Java code:

    new Server(req -> new Response().html("<h1>Hello world</h1>") 
Because Server is implemented in Kotlin and the Java lambda certainly isn't a kotlin.Function.

If that's a bad example (foggy memory), another one would be the use of @DslMarker or reflection to build my type-safe router: https://github.com/danneu/kog#type-safe-routing. Or how about inline functions with reified generics.

Kotlin does have Kotlin->Jvm interop annotations, but my take-away was that you would have to put some thought into your API and possibly make concessions so that you could sufficiently annotate it to the point that it's pleasant to use from Java. Not everything maps.

For example, you can see that OP went the route of using Java at the interface edges yet Kotlin internally to solve interop for their project.

I admit that "effectively one-way interop" is too heavy-handed of a statement, but there's definitely asymmetry that I ran into on my own project. For example, I would not recommend building something in Kotlin in the hopes that, once you're done, you can just sprinkle on some @Jvm annotations and end up with an API that's compelling to use from Java.

discuss

order

nostrademons|8 years ago

That's because the concept of a typed lambda function doesn't really exist in Java; in Java 8 lambdas are syntactic sugar for SAM-type object creation. (There are other interface warts too: @DslMarker and parameterized receivers, as you mention; treatment of void vs. Unit; different default collection types; destructuring data types, and the need to clutter your code with 'new' if you use them a lot; etc.)

It's similar to any interop problem: if you want your library to be accessible from lots of languages, its interface better be the lowest common denominator of the features they support.

There's nothing stopping you, though, from defining your interfaces in Java and then implementing those interfaces in Kotlin. The Kotlin interop code even will do a good job letting you use Kotlin's syntactic sugar for this, eg. you can pass Kotlin lambdas to functions that expect a SAM-type, or use 'with()' to treat a conventional builder pattern as a DSL.