From ce5f7e9d615e38c1fa21f5be6e208864e9e57d7c Mon Sep 17 00:00:00 2001 From: Ilya Ryzhenkov Date: Mon, 9 Jun 2014 23:27:42 +0400 Subject: [PATCH] Breaking change. Map operations revisited. --- .../cfg/PseudocodeVariableDataCollector.kt | 2 +- .../org/jetbrains/jet/utils/addToStdlib.kt | 3 +- libraries/stdlib/src/generated/_Filtering.kt | 36 ---- .../stdlib/src/kotlin/collections/Maps.kt | 177 +++++++++++++----- .../stdlib/src/kotlin/collections/MapsJVM.kt | 11 +- .../src/templates/Filtering.kt | 19 -- 6 files changed, 140 insertions(+), 108 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.kt index 5846edffed5..20721dc34b6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.kt @@ -61,7 +61,7 @@ public class PseudocodeVariableDataCollector( // Variables declared in an inner (deeper) scope can't be accessed from an outer scope. // Thus they can be filtered out upon leaving the inner scope. - return data.filterKeys { variable -> + return data.filterKeys_tmp { variable -> val lexicalScope = lexicalScopeVariableInfo.declaredIn[variable] // '-1' for variables declared outside this pseudocode val depth = lexicalScope?.depth ?: -1 diff --git a/compiler/util/src/org/jetbrains/jet/utils/addToStdlib.kt b/compiler/util/src/org/jetbrains/jet/utils/addToStdlib.kt index 1fd917fda61..129706280c6 100644 --- a/compiler/util/src/org/jetbrains/jet/utils/addToStdlib.kt +++ b/compiler/util/src/org/jetbrains/jet/utils/addToStdlib.kt @@ -19,7 +19,8 @@ package org.jetbrains.jet.utils.addToStdlib import java.util.HashMap import java.util.Collections -fun Map.filterKeys(predicate: (K)->Boolean): Map { +deprecated("Replace with filterKeys when bootstrapped") +fun Map.filterKeys_tmp(predicate: (K)->Boolean): Map { val result = HashMap() for ((k, v) in this) { if (predicate(k)) { diff --git a/libraries/stdlib/src/generated/_Filtering.kt b/libraries/stdlib/src/generated/_Filtering.kt index fdc46e28a27..c90b3373d98 100644 --- a/libraries/stdlib/src/generated/_Filtering.kt +++ b/libraries/stdlib/src/generated/_Filtering.kt @@ -431,19 +431,6 @@ public inline fun Iterable.filter(predicate: (T) -> Boolean): List { return filterTo(ArrayList(), predicate) } -/** - * Returns a map containing all key-value pairs matching the given *predicate* - */ -public inline fun Map.filter(predicate: (Map.Entry) -> Boolean): Map { - val result = HashMap() - for (entry in this) { - if (predicate(entry)) { - result.put(entry.key, entry.value) - } - } - return result -} - /** * Returns a stream containing all elements matching the given *predicate* */ @@ -528,13 +515,6 @@ public inline fun Iterable.filterNot(predicate: (T) -> Boolean): List return filterNotTo(ArrayList(), predicate) } -/** - * Returns a list containing all elements not matching the given *predicate* - */ -public inline fun Map.filterNot(predicate: (Map.Entry) -> Boolean): List> { - return filterNotTo(ArrayList>(), predicate) -} - /** * Returns a stream containing all elements not matching the given *predicate* */ @@ -674,14 +654,6 @@ public inline fun > Iterable.filterNotTo(desti return destination } -/** - * Appends all elements not matching the given *predicate* to the given *destination* - */ -public inline fun >> Map.filterNotTo(destination: C, predicate: (Map.Entry) -> Boolean): C { - for (element in this) if (!predicate(element)) destination.add(element) - return destination -} - /** * Appends all elements not matching the given *predicate* to the given *destination* */ @@ -778,14 +750,6 @@ public inline fun > Iterable.filterTo(destinat return destination } -/** - * Appends all elements matching the given *predicate* into the given *destination* - */ -public inline fun >> Map.filterTo(destination: C, predicate: (Map.Entry) -> Boolean): C { - for (element in this) if (predicate(element)) destination.add(element) - return destination -} - /** * Appends all elements matching the given *predicate* into the given *destination* */ diff --git a/libraries/stdlib/src/kotlin/collections/Maps.kt b/libraries/stdlib/src/kotlin/collections/Maps.kt index 75d99d79b77..0f21a570f35 100644 --- a/libraries/stdlib/src/kotlin/collections/Maps.kt +++ b/libraries/stdlib/src/kotlin/collections/Maps.kt @@ -6,37 +6,37 @@ import java.util.HashMap // Map APIs /** Returns the size of the map */ -public val Map<*,*>.size : Int -get() = size() +public val Map<*, *>.size: Int + get() = size() /** Returns true if this map is empty */ -public val Map<*,*>.empty : Boolean -get() = isEmpty() +public val Map<*, *>.empty: Boolean + get() = isEmpty() /** Provides [] access to maps */ -public fun MutableMap.set(key : K, value : V) : V? = this.put(key, value) +public fun MutableMap.set(key: K, value: V): V? = this.put(key, value) /** Returns the [[Map]] if its not null otherwise it returns the empty [[Map]] */ public fun Map?.orEmpty() : Map -= if (this != null) this else stdlib_emptyMap() + = if (this != null) this else stdlib_emptyMap() public fun Map.contains(key : K) : Boolean = containsKey(key) /** Returns the key of the entry */ -public val Map.Entry.key : K +public val Map.Entry.key: K get() = getKey() /** Returns the value of the entry */ -public val Map.Entry.value : V +public val Map.Entry.value: V get() = getValue() /** Returns the key of the entry */ -fun Map.Entry.component1() : K { +fun Map.Entry.component1(): K { return getKey() } /** Returns the value of the entry */ -fun Map.Entry.component2() : V { +fun Map.Entry.component2(): V { return getValue() } @@ -45,7 +45,7 @@ fun Map.Entry.component2() : V { * * @includeFunctionBody ../../test/collections/MapTest.kt getOrElse */ -public inline fun Map.getOrElse(key: K, defaultValue: ()-> V) : V { +public inline fun Map.getOrElse(key: K, defaultValue: () -> V): V { if (this.containsKey(key)) { return this.get(key) as V } else { @@ -58,7 +58,7 @@ public inline fun Map.getOrElse(key: K, defaultValue: ()-> V) : V { * * @includeFunctionBody ../../test/collections/MapTest.kt getOrPut */ -public inline fun MutableMap.getOrPut(key: K, defaultValue: ()-> V) : V { +public inline fun MutableMap.getOrPut(key: K, defaultValue: () -> V): V { if (this.containsKey(key)) { return this.get(key) as V } else { @@ -68,63 +68,54 @@ public inline fun MutableMap.getOrPut(key: K, defaultValue: ()-> V) : } } - /** * Returns an [[Iterator]] over the entries in the [[Map]] * * @includeFunctionBody ../../test/collections/MapTest.kt iterateWithProperties */ -public fun Map.iterator(): Iterator> { +public fun Map.iterator(): Iterator> { val entrySet = this.entrySet() return entrySet.iterator() } /** - * Populates the given *result* [[Map]] with the value returned by applying the *transform* function on each [[Map.Entry]] in this [[Map]] + * Populates the given *destination* [[Map]] with the value returned by applying the *transform* function on each [[Map.Entry]] in this [[Map]] */ -public inline fun > Map.mapValuesTo(result: C, transform : (Map.Entry) -> R) : C { - for (e in this) { - val newValue = transform(e) - result.put(e.key, newValue) - } - return result +public inline fun > Map.mapValuesTo(destination: C, transform: (Map.Entry) -> R): C { + for (e in this) { + val newValue = transform(e) + destination.put(e.key, newValue) + } + return destination +} + +/** + * Populates the given *destination* [[Map]] with the value returned by applying the *transform* function on each [[Map.Entry]] in this [[Map]] + */ +public inline fun > Map.mapKeysTo(destination: C, transform: (Map.Entry) -> R): C { + for (e in this) { + val newKey = transform(e) + destination.put(newKey, e.value) + } + return destination } /** * Puts all the entries into this [[MutableMap]] with the first value in the pair being the key and the second the value */ -public fun MutableMap.putAll(vararg values: Pair): Unit { +public fun MutableMap.putAll(vararg values: Pair): Unit { for ((key, value) in values) { put(key, value) } } /** - * Copies the entries in this [[Map]] to the given mutable *map* + * Puts all the entries into this [[MutableMap]] with the first value in the pair being the key and the second the value */ -public fun > Map.toMap(map: C): C { - map.putAll(this) - return map -} - -/** - * Copies the entries from given iterable of pairs to the given mutable *map* - */ -public fun > Iterable>.toMap(map: C): C { - for((key,value) in this) { - if (map.containsKey(key)) { - throw DuplicateKeyException() - } - map.put(key,value) +public fun MutableMap.putAll(values: Iterable>): Unit { + for ((key, value) in values) { + put(key, value) } - return map -} - -/** - * Creates map from given iterable of pairs - */ -public fun Iterable>.toMap() : Map { - return toMap(HashMap()) } /** @@ -132,6 +123,98 @@ public fun Iterable>.toMap() : Map { * * @includeFunctionBody ../../test/collections/MapTest.kt mapValues */ -public inline fun Map.mapValues(transform : (Map.Entry) -> R): Map { - return mapValuesTo(java.util.HashMap(this.size), transform) +public inline fun Map.mapValues(transform: (Map.Entry) -> R): Map { + return mapValuesTo(HashMap(this.size), transform) +} + +/** + * Returns a new Map containing the results of applying the given *transform* function to each [[Map.Entry]] in this [[Map]] + * + * @includeFunctionBody ../../test/collections/MapTest.kt mapKeys + */ +public inline fun Map.mapKeys(transform: (Map.Entry) -> R): Map { + return mapKeysTo(HashMap(this.size), transform) +} + +/** + * Returns a map containing all key-value pairs matching keys with the given *predicate* + */ +public inline fun Map.filterKeys(predicate: (K) -> Boolean): Map { + val result = HashMap() + for (entry in this) { + if (predicate(entry.key)) { + result.put(entry.key, entry.value) + } + } + return result +} + +/** + * Returns a map containing all key-value pairs matching values with the given *predicate* + */ +public inline fun Map.filterValues(predicate: (V) -> Boolean): Map { + val result = HashMap() + for (entry in this) { + if (predicate(entry.value)) { + result.put(entry.key, entry.value) + } + } + return result +} + + +/** + * Appends all elements matching the given *predicate* into the given *destination* + */ +public inline fun > Map.filterTo(destination: C, predicate: (Map.Entry) -> Boolean): C { + for (element in this) { + if (predicate(element)) { + destination.put(element.key, element.value) + } + } + return destination +} + +/** + * Returns a map containing all key-value pairs matching the given *predicate* + */ +public inline fun Map.filter(predicate: (Map.Entry) -> Boolean): Map { + return filterTo(HashMap(), predicate) +} + +/** + * Appends all elements matching the given *predicate* into the given *destination* + */ +public inline fun > Map.filterNotTo(destination: C, predicate: (Map.Entry) -> Boolean): C { + for (element in this) { + if (!predicate(element)) { + destination.put(element.key, element.value) + } + } + return destination +} + +/** + * Returns a map containing all key-value pairs matching the given *predicate* + */ +public inline fun Map.filterNot(predicate: (Map.Entry) -> Boolean): Map { + return filterNotTo(HashMap(), predicate) +} + +/** + * Appends given [pair] to the mutable map. + */ +public fun MutableMap.plusAssign(pair: Pair) { + put(pair.first, pair.second) +} + +/** + * Returns a map containing all key-value pairs from the given collection + */ +public fun Iterable>.toMap(): Map { + val result = HashMap() + for (element in this) { + result.put(element.first, element.second) + } + return result } diff --git a/libraries/stdlib/src/kotlin/collections/MapsJVM.kt b/libraries/stdlib/src/kotlin/collections/MapsJVM.kt index 00aa9607741..1fa2f781125 100644 --- a/libraries/stdlib/src/kotlin/collections/MapsJVM.kt +++ b/libraries/stdlib/src/kotlin/collections/MapsJVM.kt @@ -11,14 +11,14 @@ import java.util.Properties /** * Converts this [[Map]] to a [[LinkedHashMap]] so future insertion orders are maintained */ -public fun Map.toLinkedMap(): LinkedHashMap = toMap(LinkedHashMap(size)) +public fun Map.toLinkedMap(): LinkedHashMap = LinkedHashMap(this) /** * Converts this [[Map]] to a [[SortedMap]] so iteration order will be in key order * * @includeFunctionBody ../../test/collections/MapTest.kt toSortedMap */ -public fun Map.toSortedMap(): SortedMap = toMap(TreeMap()) +public fun Map.toSortedMap(): SortedMap = TreeMap(this) /** * Converts this [[Map]] to a [[SortedMap]] using the given *comparator* so that iteration order will be in the order @@ -26,8 +26,11 @@ public fun Map.toSortedMap(): SortedMap = toMap(TreeMap()) * * @includeFunctionBody ../../test/collections/MapTest.kt toSortedMapWithComparator */ -public fun Map.toSortedMap(comparator: Comparator): SortedMap = toMap(TreeMap(comparator)) - +public fun Map.toSortedMap(comparator: Comparator): SortedMap { + val result = TreeMap(comparator) + result.putAll(this) + return result +} /** * Converts this [[Map]] to a [[Properties]] object diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Filtering.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Filtering.kt index 9547e89cb00..4e041edd93c 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Filtering.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Filtering.kt @@ -205,21 +205,6 @@ fun filtering(): List { return FilteringStream(this, true, predicate) """ } - - include(Maps) - doc(Maps) { "Returns a map containing all key-value pairs matching the given *predicate*" } - returns(Maps) { "Map" } - body(Maps) { - """ - val result = HashMap() - for (entry in this) { - if (predicate(entry)) { - result.put(entry.key, entry.value) - } - } - return result - """ - } } templates add f("filterTo(destination: C, predicate: (T) -> Boolean)") { @@ -246,8 +231,6 @@ fun filtering(): List { return destination """ } - - include(Maps) } templates add f("filterNot(predicate: (T) -> Boolean)") { @@ -276,7 +259,6 @@ fun filtering(): List { return FilteringStream(this, false, predicate) """ } - include(Maps) } templates add f("filterNotTo(destination: C, predicate: (T) -> Boolean)") { @@ -300,7 +282,6 @@ fun filtering(): List { return destination """ } - include(Maps) } templates add f("filterNotNull()") {