diff --git a/core/api/kotlinx-collections-immutable.api b/core/api/kotlinx-collections-immutable.api index 09231a36..cfc60020 100644 --- a/core/api/kotlinx-collections-immutable.api +++ b/core/api/kotlinx-collections-immutable.api @@ -1,4 +1,9 @@ public final class kotlinx/collections/immutable/ExtensionsKt { + public static final fun buildPersistentHashMap (Lkotlin/jvm/functions/Function1;)Lkotlinx/collections/immutable/PersistentMap; + public static final fun buildPersistentHashSet (Lkotlin/jvm/functions/Function1;)Lkotlinx/collections/immutable/PersistentSet; + public static final fun buildPersistentList (Lkotlin/jvm/functions/Function1;)Lkotlinx/collections/immutable/PersistentList; + public static final fun buildPersistentMap (Lkotlin/jvm/functions/Function1;)Lkotlinx/collections/immutable/PersistentMap; + public static final fun buildPersistentSet (Lkotlin/jvm/functions/Function1;)Lkotlinx/collections/immutable/PersistentSet; public static final fun immutableHashMapOf ([Lkotlin/Pair;)Lkotlinx/collections/immutable/PersistentMap; public static final fun immutableHashSetOf ([Ljava/lang/Object;)Lkotlinx/collections/immutable/PersistentSet; public static final fun immutableListOf ()Lkotlinx/collections/immutable/PersistentList; diff --git a/core/api/kotlinx-collections-immutable.klib.api b/core/api/kotlinx-collections-immutable.klib.api index 4bd7b493..23a58dc1 100644 --- a/core/api/kotlinx-collections-immutable.klib.api +++ b/core/api/kotlinx-collections-immutable.klib.api @@ -242,6 +242,8 @@ final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlinx.collections.immutab final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlinx.collections.immutable/PersistentMap).kotlinx.collections.immutable/plus(kotlin.sequences/Sequence>): kotlinx.collections.immutable/PersistentMap<#A, #B> // kotlinx.collections.immutable/plus|plus@kotlinx.collections.immutable.PersistentMap(kotlin.sequences.Sequence>){0§;1§}[0] final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlinx.collections.immutable/PersistentMap).kotlinx.collections.immutable/plus(kotlin/Array>): kotlinx.collections.immutable/PersistentMap<#A, #B> // kotlinx.collections.immutable/plus|plus@kotlinx.collections.immutable.PersistentMap(kotlin.Array>){0§;1§}[0] final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlinx.collections.immutable/PersistentMap).kotlinx.collections.immutable/plus(kotlin/Pair<#A, #B>): kotlinx.collections.immutable/PersistentMap<#A, #B> // kotlinx.collections.immutable/plus|plus@kotlinx.collections.immutable.PersistentMap(kotlin.Pair<0:0,0:1>){0§;1§}[0] +final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> kotlinx.collections.immutable/buildPersistentHashMap(kotlin/Function1, kotlin/Unit>): kotlinx.collections.immutable/PersistentMap<#A, #B> // kotlinx.collections.immutable/buildPersistentHashMap|buildPersistentHashMap(kotlin.Function1,kotlin.Unit>){0§;1§}[0] +final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> kotlinx.collections.immutable/buildPersistentMap(kotlin/Function1, kotlin/Unit>): kotlinx.collections.immutable/PersistentMap<#A, #B> // kotlinx.collections.immutable/buildPersistentMap|buildPersistentMap(kotlin.Function1,kotlin.Unit>){0§;1§}[0] final inline fun <#A: kotlin/Any?> (kotlinx.collections.immutable/PersistentCollection<#A>).kotlinx.collections.immutable/minus(#A): kotlinx.collections.immutable/PersistentCollection<#A> // kotlinx.collections.immutable/minus|minus@kotlinx.collections.immutable.PersistentCollection<0:0>(0:0){0§}[0] final inline fun <#A: kotlin/Any?> (kotlinx.collections.immutable/PersistentCollection<#A>).kotlinx.collections.immutable/plus(#A): kotlinx.collections.immutable/PersistentCollection<#A> // kotlinx.collections.immutable/plus|plus@kotlinx.collections.immutable.PersistentCollection<0:0>(0:0){0§}[0] final inline fun <#A: kotlin/Any?> (kotlinx.collections.immutable/PersistentList<#A>).kotlinx.collections.immutable/minus(#A): kotlinx.collections.immutable/PersistentList<#A> // kotlinx.collections.immutable/minus|minus@kotlinx.collections.immutable.PersistentList<0:0>(0:0){0§}[0] @@ -250,3 +252,6 @@ final inline fun <#A: kotlin/Any?> (kotlinx.collections.immutable/PersistentList final inline fun <#A: kotlin/Any?> (kotlinx.collections.immutable/PersistentSet<#A>).kotlinx.collections.immutable/minus(#A): kotlinx.collections.immutable/PersistentSet<#A> // kotlinx.collections.immutable/minus|minus@kotlinx.collections.immutable.PersistentSet<0:0>(0:0){0§}[0] final inline fun <#A: kotlin/Any?> (kotlinx.collections.immutable/PersistentSet<#A>).kotlinx.collections.immutable/mutate(kotlin/Function1, kotlin/Unit>): kotlinx.collections.immutable/PersistentSet<#A> // kotlinx.collections.immutable/mutate|mutate@kotlinx.collections.immutable.PersistentSet<0:0>(kotlin.Function1,kotlin.Unit>){0§}[0] final inline fun <#A: kotlin/Any?> (kotlinx.collections.immutable/PersistentSet<#A>).kotlinx.collections.immutable/plus(#A): kotlinx.collections.immutable/PersistentSet<#A> // kotlinx.collections.immutable/plus|plus@kotlinx.collections.immutable.PersistentSet<0:0>(0:0){0§}[0] +final inline fun <#A: kotlin/Any?> kotlinx.collections.immutable/buildPersistentHashSet(kotlin/Function1, kotlin/Unit>): kotlinx.collections.immutable/PersistentSet<#A> // kotlinx.collections.immutable/buildPersistentHashSet|buildPersistentHashSet(kotlin.Function1,kotlin.Unit>){0§}[0] +final inline fun <#A: kotlin/Any?> kotlinx.collections.immutable/buildPersistentList(kotlin/Function1, kotlin/Unit>): kotlinx.collections.immutable/PersistentList<#A> // kotlinx.collections.immutable/buildPersistentList|buildPersistentList(kotlin.Function1,kotlin.Unit>){0§}[0] +final inline fun <#A: kotlin/Any?> kotlinx.collections.immutable/buildPersistentSet(kotlin/Function1, kotlin/Unit>): kotlinx.collections.immutable/PersistentSet<#A> // kotlinx.collections.immutable/buildPersistentSet|buildPersistentSet(kotlin.Function1,kotlin.Unit>){0§}[0] diff --git a/core/commonMain/src/extensions.kt b/core/commonMain/src/extensions.kt index 57d289fa..e060714a 100644 --- a/core/commonMain/src/extensions.kt +++ b/core/commonMain/src/extensions.kt @@ -766,3 +766,66 @@ public fun Map.toPersistentHashMap(): PersistentMap = this as? PersistentHashMap ?: (this as? PersistentHashMapBuilder)?.build() ?: PersistentHashMap.emptyOf().putAll(this) + +/** + * Builds a new [PersistentList] by populating a [MutableList] using the given [builderAction] + * and returning an immutable list with the same elements. + * + * The list passed as a receiver to the [builderAction] is valid only inside that function. + * Using it outside the function produces an unspecified behavior. + */ +public inline fun buildPersistentList(builderAction: MutableList.() -> Unit): PersistentList { + return persistentListOf().mutate(builderAction) +} + +/** + * Builds a new [PersistentSet] by populating a [MutableSet] using the given [builderAction] + * and returning an immutable set with the same elements. + * + * The set passed as a receiver to the [builderAction] is valid only inside that function. + * Using it outside the function produces an unspecified behavior. + * + * Elements of the set are iterated in the order they were added by the [builderAction]. + */ +public inline fun buildPersistentSet(builderAction: MutableSet.() -> Unit): PersistentSet { + return persistentSetOf().mutate(builderAction) +} + +/** + * Builds a new [PersistentSet] by populating a [MutableSet] using the given [builderAction] + * and returning an immutable set with the same elements. + * + * The set passed as a receiver to the [builderAction] is valid only inside that function. + * Using it outside the function produces an unspecified behavior. + * + * Order of the elements in the returned set is unspecified. + */ +public inline fun buildPersistentHashSet(builderAction: MutableSet.() -> Unit): PersistentSet { + return persistentHashSetOf().mutate(builderAction) +} + +/** + * Builds a new [PersistentMap] by populating a [MutableMap] using the given [builderAction] + * and returning an immutable map with the same key-value pairs. + * + * The map passed as a receiver to the [builderAction] is valid only inside that function. + * Using it outside the function produces an unspecified behavior. + * + * Entries of the map are iterated in the order they were added by the [builderAction]. + */ +public inline fun buildPersistentMap(builderAction: MutableMap.() -> Unit): PersistentMap { + return persistentMapOf().mutate(builderAction) +} + +/** + * Builds a new [PersistentMap] by populating a [MutableMap] using the given [builderAction] + * and returning an immutable map with the same key-value pairs. + * + * The map passed as a receiver to the [builderAction] is valid only inside that function. + * Using it outside the function produces an unspecified behavior. + * + * Order of the entries in the returned map is unspecified. + */ +public inline fun buildPersistentHashMap(builderAction: MutableMap.() -> Unit): PersistentMap { + return persistentHashMapOf().mutate(builderAction) +} diff --git a/core/commonTest/src/contract/list/ImmutableListTest.kt b/core/commonTest/src/contract/list/ImmutableListTest.kt index 76883a04..859a8764 100644 --- a/core/commonTest/src/contract/list/ImmutableListTest.kt +++ b/core/commonTest/src/contract/list/ImmutableListTest.kt @@ -159,6 +159,16 @@ class ImmutableListTest { } } + @Test fun buildPersistentList() { + val expected = persistentListOf(1, 2, 3, 4, 5, 6) + val actual = buildPersistentList { + for (i in 1..6) { + add(i) + } + } + assertEquals(expected, actual) + } + @Test fun subListOfBuilder() { val list = "abcxaxyz12".toImmutableList().toPersistentList() val builder = list.builder() diff --git a/core/commonTest/src/contract/map/ImmutableMapTest.kt b/core/commonTest/src/contract/map/ImmutableMapTest.kt index d204d443..0f7c6a7d 100644 --- a/core/commonTest/src/contract/map/ImmutableMapTest.kt +++ b/core/commonTest/src/contract/map/ImmutableMapTest.kt @@ -78,6 +78,21 @@ class ImmutableHashMapTest : ImmutableMapTest() { compareMaps(expected, builder1.build()) } + @Test fun buildPersistentHashMap() { + val expected = mutableMapOf() + val actual = buildPersistentHashMap { + for (i in 300..400) { + put("$i", i) + expected["$i"] = i + } + for (i in 0..200) { + put("$i", i) + expected["$i"] = i + } + } + compareMapsUnordered(expected, actual) + } + @Test fun regressionGithubIssue109() { // https://github.com/Kotlin/kotlinx.collections.immutable/issues/109 val map0 = immutableMapOf().put(0, 0).put(1, 1).put(32, 32) @@ -139,6 +154,21 @@ class ImmutableOrderedMapTest : ImmutableMapTest() { changing.add("break iteration") assertFailsWith { builder.filter { it.key === changing } } } + + @Test fun buildPersistentMap() { + val expected = mutableMapOf() + val actual = buildPersistentMap { + for (i in 300..400) { + put("$i", i) + expected["$i"] = i + } + for (i in 0..200) { + put("$i", i) + expected["$i"] = i + } + } + compareMaps(expected, actual) + } } abstract class ImmutableMapTest { diff --git a/core/commonTest/src/contract/set/ImmutableSetTest.kt b/core/commonTest/src/contract/set/ImmutableSetTest.kt index 1339ebcf..e25d3540 100644 --- a/core/commonTest/src/contract/set/ImmutableSetTest.kt +++ b/core/commonTest/src/contract/set/ImmutableSetTest.kt @@ -195,6 +195,17 @@ class ImmutableHashSetTest : ImmutableSetTestBase() { compareSets(immutableSetOf(), left - right) } } + + @Test fun buildPersistentHashSet() { + val expected = mutableSetOf() + val actual = buildPersistentHashSet { + for (i in 0..2000) { + add(i) + expected.add(i) + } + } + compareSetsUnordered(expected, actual) + } } class ImmutableOrderedSetTest : ImmutableSetTestBase() { @@ -221,6 +232,17 @@ class ImmutableOrderedSetTest : ImmutableSetTestBase() { changing.add("break iteration") assertFailsWith { builder.filter { it === changing } } } + + @Test fun buildPersistentSet() { + val expected = mutableSetOf() + val actual = buildPersistentSet { + for (i in 0..2000) { + add(i) + expected.add(i) + } + } + compareSets(expected, actual) + } } abstract class ImmutableSetTestBase {