Using Kotlin Duration with Java Time fluently - kotlin

What is purpose of Kotlin Duration when it isn't fluently compatible with java.time clasees?
When I need always use converter... Why aren't implements extenstion function over java classes which should intercept Kotlin Duration? Are there some fluent ways to use Kotlin Duration with java.time?
OffsetDateTime.now().plus(1.days) // not working
OffsetDateTime.now().plus(1.days.toJavaDuration()) // working
NOTE: example not so good, in this case I can use plusDays... but I hope that ilustrate inflating of expresion

The purpose of kotlin.time.Duration to represent the duration between two instances in time - the same as java.time.Duration.
Note that some parts of Kotlin Time are still experimental, and require an opt-in for any Kotlin projects that aim to support Kotlin v1.5 or lower.
One benefit of kotlin.time.Duration is that it is multiplatform, and can be used in Java, JavaScript, Native, and (soon) WASM Kotlin projects. java.time.Duration can only be used in Java projects.
There are at least two ways to improve compatibility:
Use kotlinx-datetime, a JetBrains library that can be used to completely replace Java Time.
This would make working with temporals in Kotlin easier, but it might be a large amount of effort for not much gain. It might also not be possible if the existing codebase is very dependent on Java Time.
Create a custom extension functions, that make temporal operations more convenient. Using the plus() operator is a natural improvement.
import java.time.OffsetDateTime
import kotlin.time.Duration.Companion.seconds
import kotlin.time.Duration.*
import kotlin.time.*
fun main() {
val now = OffsetDateTime.now()
println("now : $now")
println("now.plus(1s): ${now.plus(1.seconds.toJavaDuration())}")
println("now + 1s : ${now + 1.seconds}")
}
/** Adds [amountToAdd] to an [OffsetDateTime] */
operator fun OffsetDateTime.plus(amountToAdd: Duration): OffsetDateTime =
plus(amountToAdd.toJavaDuration())
Run in Kotlin Playground

Related

Is sequence referred to internal DSL in Kotlin?

In book 'Kotlin in Action', it says Kotlin DSL structure is most commonly created through chained method calls. Also, a typical library consists of many methods and no context is maintained btw one call and the next.
I'm confused of which side sequence is close to. Before I read this, I've thought sequence is just API of library, but it really fits with feature of DSL.
I'm not 100% sure this answers your question, but I would not think of Sequence pipelines as a "DSL" per se, in particular because it is quite general, which is the opposite of "domain-specific" - the heart of the definition of a DSL.
If you build your own builder API based on chained method calls for a specific domain, you could consider that as a DSL, but I would say Kotlin DSLs are mostly made of nested lambdas with declarative property assignments, rather than chained method calls.
This is because lambdas in Kotlin give the illusion of blocks and structure more than actual functions and function calls, which is why nested structures like this look like their own "language" (the L of DSL). Chained method calls don't look like another "language" - they just look like function calls, but of course that's my subjective take.
For example, here is a Gradle build script using the Gradle Kotlin DSL:
plugins {
`java-library`
}
dependencies {
api("junit:junit:4.13")
implementation("junit:junit:4.13")
testImplementation("junit:junit:4.13")
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
It does look like its own language, you don't immediately think of Kotlin when reading such code.

Concurrent Hash Map in Kotlin

Is it possible to implement a concurrent hash map purely in Kotlin (without Java dependency)? I am new to Kotlin and it looks like there is no obvious API available in kotlin.collections.
You can probably convert the source without too many issues. It's freely available, here for example. The concurrency model of Kotlin multiplatform (which I'm guessing is your goal, there's no point in reimplementing it if you only target the JVM) is a bit different than the one Java uses, there are no locks for example. But there's no reason why that would prevent it.
The following resources might also help you with the implementation:
Concurrency in Kotlin/Native
kotlin.native.concurrent package
Replacement for synchronized
Official Kotlin/Native Concurrency tutorial
You can try:
val emitters: ConcurrentMap<String, Any> = ConcurrentHashMap()
// get
val obj: Any = emitters[email]
// put:
emitters[email] = this
// delete
emitters.remove(email)
Such way, u don't need to add any library to your project

Multi-platform InputStream Alternative in Kotlin?

I’m looking for a multi-platform alternative to input streams. My concrete task is to fetch an encrypted file from a remote server via https and decrypt it on demand.
In Java land I would an implement InputStream which proxies the reads to the input stream from the https library. How can I do the same in kotlin targeting multiple platforms.
I see ktor returns an ByteReadChannel, but I don’t know which functions.
I’m lost and don’t know where to start. Thanks for your help in advance.
If the framework you are using does not provide you with a full-fledged InputStream implementation, the only chance left is to write your own. Much like what the ktor developers did: ByteReadChannel is just an abstraction of "reading bytes from a channel".
This abstraction lives in the common part and allows to write application and business logic around it.
The key to make this work in the context of a Kotlin Multiplatform project is, the actual implementation needs to be provided in the platform specific parts. The JVM specific code of the ktor project actually has an implementation that uses InputStream: InputStream.toByteReadChannel.
You certainly don't have to do it like your example from the ktor project and model everything down from byte channels up to file representations. If you want to leverage Kotlin framework classes, Sequences might be handy. This could look something like this:
// in common
interface FileFetcher {
fun fetch(): Sequence<Byte>
}
expect fun fileFetcher(source: String): FileFetcher
// in jvm
class JvmFileFetcher(val input: java.io.InputStream): FileFetcher {
override fun fetch(): Sequence<Byte> = input.readBytes().asSequence()
}
actual fun fileFetcher(source: String): FileFetcher {
val input = java.net.URL(source).openStream()
return JvmFileFetcher(input)
}
You would define an interface FileFetcher along with a factory function fileFetcher in the common part. By using the expect keyword on the fileFetcher function you need to provide platform-specific implementations for all target platforms you define. Use the FileFetcher interface in the common part to implement your logic (decrypting file contents etc.). See the documentation for Sequence for how to work with it.
Then implement the factory function for all platforms and use the actual keyword on them. You will then need to write platform-specific implementations of FileFetcher. My example shows how a JVM version of the FileFetcher interface.
The example is of course very basic and you probably would not want to do it exactly like this (at least some buffering would be needed, I guess). Also, within the JVM part you could also leverage your favorite networking/HTTP library easily.

Can anyone here explain the Kotlin/Native spinner app project structure in detail? Also the specifics on how different modules work

I would like to specifically know how the common module is used by the individual client modules. Which are the truly common parts that is shared by all the clients and the server.
Thank you.
This is easy. I suspect you're talking about Kotlin multiplatform modules.
Consider print and println.
In the common module we can expect a print function:
expect fun print(a: String)
But we don't know how was it implemented, because the common module doesn't know anything about Java's System.out, as well as JavaScript's console.
But the common module can expect such function that prints a String on screen, without providing an implementation.
Since we have print, we can implement println:
fun println(a: String) = print("$a\n")
All codes above are inside the common module.
And all you have to do is to to implement print for JVM/JS spererately.
For JVM:
actual fun print(a: String) = System.out.println(a)
For JS:
actual fun print(a: String) = console.log(a)
(Maybe) For Native:
actual fun print(a: String) = printf(a)
The three code blocks above are inside client modules.
Consider you've designed a data format, you have encoding and decoding code. Those codes are used in your Android device (JVM), your backend server (JVM), your frontend webpage (JS), your native app (Native).
You use Kotlin in all those sub projects but you want to write the encoder/decoder only once. Kotlin multiplatform module solves this probelm.
About the spinner app
It's not using the standard kotlin approach for creating multiplatform project. It's a trick on gradle.
There's a readResources (and randomInit as well, for osx/linux) function that implements differently on platforms but of the same signature, and gradle will decide which Kommon.kt should be compiled with the client projects.
readResources and randomInit should be marked as actual, and there should be a "common module" that has "expect"ed those two functions.
They didn't do this probably because Kotlin 1.2 (which brings stable multiplatform support) isn't out when KotlinConf holds.

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+)
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.