Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin, targeting Java interop: Idiomatic type for lazy collection?

When targeting Java interop, what type should one use for a lazy collection?

  • Sequence<T> makes the most sense for Kotlin callers due to extension functions on it being lazy by default, but forces Java callers to deal with a Kotlin stdlib type and convert the sequence iterator manually (sequence does not extend iterable!)
  • Iterable<T> makes sense for Java callers due to implicit usage in for loops, but will cause unsuspecting Kotlin callers to accidentally drop laziness due to non-lazy extension functions
  • Stream<T> is optimal for both Java and Kotlin callers but may have overhead and is Java 8+ (Kotlin targets 6+)
like image 813
F. George Avatar asked Aug 01 '17 10:08

F. George


1 Answers

You can make everyone happy by implementing all three. e.g.:

data class User(val name: String)

fun userSequence(): Sequence<User> = TODO()
fun usersLazily(): Iterable<User> = userSequence().asIterable()
fun userStream(): Stream<User> = userSequence().asStream()

By not using a simple name like users for any of these functions you make the caller think just a little extra on which one they really want:

  • Kotlin users will use userSequence.
  • Java 1.6 and 1.7 users will use usersLazily.
  • Java 1.8 users will use userStream.

userStream will have to be defined in a separate JAR adding JDK 1.8 support to your 1.6/1.7 JAR (similar to how org.jetbrains.kotlin:kotlin-stdlib-jre8 does for org.jetbrains.kotlin:kotlin-stdlib).

With that said, I would question whether you really need to maintain Java 1.6 or 1.7 support. If you find you don't then you can put userSequence and userStream into the same JAR and not even define usersLazily.

like image 78
mfulton26 Avatar answered Sep 28 '22 03:09

mfulton26