Skip to content

Instantly share code, notes, and snippets.

@arturaz
Created January 28, 2020 10:45
Show Gist options
  • Save arturaz/36b60606558256efa466fc4ed09cd300 to your computer and use it in GitHub Desktop.
Save arturaz/36b60606558256efa466fc4ed09cd300 to your computer and use it in GitHub Desktop.
Interoperability between scala and kotlin persistent collections
package zowo_shared.lib.compat
import kotlinx.collections.immutable.ImmutableCollection
import kotlinx.collections.immutable.ImmutableSet
import kotlinx.collections.immutable.PersistentMap
import kotlinx.collections.immutable.persistentMapOf
import zowo_shared.lib.functional.ZOption
interface ICompatPersistentMap<K, V> {
val entries: ImmutableSet<Map.Entry<K, V>>
val keys: ImmutableSet<K>
val size: Int
val values: ImmutableCollection<V>
fun containsKey(key: K): Boolean
fun containsValue(value: V): Boolean
fun get(key: K): ZOption<V>
fun isEmpty(): Boolean
fun put(key: K, value: V): PersistentMap<K, V>
fun putAll(m: Map<out K, V>): PersistentMap<K, V>
fun remove(key: K): PersistentMap<K, V>
fun remove(key: K, value: V): PersistentMap<K, V>
fun builder(): PersistentMap.Builder<K, V>
}
@Suppress("unused")
class CompatPersistentMap<K, V>(val backing: ICompatPersistentMap<K, V>) : PersistentMap<K, V> {
companion object {
val empty = persistentMapOf<Nothing, Nothing>()
}
override val entries: ImmutableSet<Map.Entry<K, V>>
get() = backing.entries
override val keys: ImmutableSet<K>
get() = backing.keys
override val size: Int
get() = backing.size
override val values: ImmutableCollection<V>
get() = backing.values
override fun builder(): PersistentMap.Builder<K, V> = backing.builder()
@Suppress("UNCHECKED_CAST") override fun clear(): PersistentMap<K, V> = empty as PersistentMap<K, V>
override fun containsKey(key: K): Boolean = backing.containsKey(key)
override fun containsValue(value: V): Boolean = backing.containsValue(value)
override fun get(key: K): V? = backing.get(key).orNull
override fun isEmpty(): Boolean = backing.isEmpty()
override fun put(key: K, value: V): PersistentMap<K, V> = backing.put(key, value)
override fun putAll(m: Map<out K, V>): PersistentMap<K, V> = backing.putAll(m)
override fun remove(key: K): PersistentMap<K, V> = backing.remove(key)
override fun remove(key: K, value: V): PersistentMap<K, V> = backing.remove(key, value)
}
package compat.shared
import java.util
import kotlinx.collections.immutable.{ExtensionsKt, ImmutableCollection, ImmutableSet, PersistentMap}
import zowo_shared.lib.compat.{CompatPersistentMap, ICompatPersistentMap}
import zowo_shared.lib.functional.ZOption
import scala.jdk.CollectionConverters._
trait MapCompat { _: SetCompat with OptionCompat =>
implicit class KotlinPersistentMapExts[K, V](val m: PersistentMap[K, V]) {
def asScala: Map[K, V] = new Map[K, V] {
override def removed(key: K): Map[K, V] = m.remove(key)
override def updated[V1 >: V](key: K, value: V1): Map[K, V1] =
m.asInstanceOf[PersistentMap[K, V1]].put(key, value)
override def get(key: K): Option[V] = Option(m.get(key))
override def iterator: Iterator[(K, V)] = m.getEntries.iterator().asScala.map(e => (e.getKey, e.getValue))
}
}
implicit def kotlinPersistentMapAsScala[K, V](m: PersistentMap[K, V]): Map[K, V] = m.asScala
implicit class ScalaMapExts[K, V](val m: Map[K, V]) {
def asKotlin: PersistentMap[K, V] = {
new CompatPersistentMap[K, V](new ICompatPersistentMap[K, V] {
override def getEntries: ImmutableSet[util.Map.Entry[K, V]] = m.iterator.map(_.toMapEntry).toSet
override def getKeys: ImmutableSet[K] = m.keySet
override def getSize: Int = m.size
override def getValues: ImmutableCollection[V] = m.values.toVector
override def containsKey(k: K): Boolean = m.contains(k)
override def containsValue(v: V): Boolean = m.values.exists(_ == v)
override def get(k: K): ZOption[V] = m.get(k)
override def isEmpty: Boolean = m.isEmpty
override def put(k: K, v: V): PersistentMap[K, V] = m.updated(k, v)
override def putAll(map: util.Map[_ <: K, _ <: V]): PersistentMap[K, V] = m ++ map.asScala
override def remove(k: K): PersistentMap[K, V] = m - k
override def remove(k: K, v: V): PersistentMap[K, V] = m.get(k) match {
case Some(`v`) => m.removed(k)
case Some(_) | None => m
}
override def builder(): PersistentMap.Builder[K, V] = {
val b = ExtensionsKt.persistentHashMapOf[K, V]().builder()
m.foreach { case (k, v) => b.put(k, v) }
b
}
})
}
}
implicit def mapAsKotlinPersistentMap[K, V](m: Map[K, V]): PersistentMap[K, V] = m.asKotlin
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment