Skip to content
This repository was archived by the owner on Dec 22, 2021. It is now read-only.

Commit 853ac57

Browse files
committed
Add MapView and make View.MapValue a MapView.
1 parent 2f62c28 commit 853ac57

File tree

5 files changed

+61
-11
lines changed

5 files changed

+61
-11
lines changed

collections/src/main/scala/strawman/collection/Map.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,13 @@ trait Map[K, +V]
4747
* @define coll map
4848
* @define Coll `Map`
4949
*/
50-
trait MapOps[K, +V, +CC[X, Y] <: MapOps[X, Y, CC, _], +C]
50+
// Note: the upper bound constraint on CC is useful only to
51+
// erase CC to IterableOps instead of Object
52+
trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C]
5153
extends IterableOps[(K, V), Iterable, C]
52-
with PartialFunction[K, V]
53-
with Equals {
54+
with PartialFunction[K, V] {
55+
56+
override def view: MapView[K, V] = new MapView.Id(this)
5457

5558
/** Similar to fromIterable, but returns a Map collection type */
5659
protected[this] def mapFromIterable[K2, V2](it: Iterable[(K2, V2)]): CC[K2, V2]
@@ -164,7 +167,7 @@ trait MapOps[K, +V, +CC[X, Y] <: MapOps[X, Y, CC, _], +C]
164167
* @return a map view which maps every key of this map
165168
* to `f(this(key))`. The resulting map wraps the original map without copying any elements.
166169
*/
167-
def mapValues[W](f: V => W): View[(K, W)] = new View.MapValues(toIterable, f)
170+
def mapValues[W](f: V => W): MapView[K, W] = new MapView.MapValues(this, f)
168171

169172
/** Defines the default value computation for the map,
170173
* returned when a key is not found
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package strawman.collection
2+
3+
import scala.{Int, Option}
4+
5+
import strawman.collection.mutable.Builder
6+
7+
trait MapView[K, +V]
8+
extends MapOps[K, V, ({ type l[X, Y] = View[(X, Y)] })#l, View[(K, V)]]
9+
with View[(K, V)] {
10+
11+
override def view: MapView[K, V] = this
12+
13+
protected[this] def mapFromIterable[K2, V2](it: Iterable[(K2, V2)]): View[(K2, V2)] = fromIterable(it)
14+
15+
def mapFactory: MapFactory[({ type l[X, Y] = View[(X, Y)] })#l] =
16+
new MapFactory[({ type l[X, Y] = View[(X, Y)] })#l] {
17+
def newBuilder[X, Y](): Builder[(X, Y), View[(X, Y)]] = View.newBuilder[(X, Y)]()
18+
def empty[X, Y]: View[(X, Y)] = View.empty
19+
def from[X, Y](it: IterableOnce[(X, Y)]): View[(X, Y)] = View.from(it.asInstanceOf[Iterable[(X, Y)]]) // Waiting for https://github.com/scala/collection-strawman/pull/428
20+
}
21+
22+
def empty: View[(K, V)] = View.Empty
23+
24+
}
25+
26+
object MapView {
27+
28+
class Id[K, +V](underlying: MapOps[K, V, AnyConstr, _]) extends MapView[K, V] {
29+
def get(key: K): Option[V] = underlying.get(key)
30+
def iterator(): Iterator[(K, V)] = underlying.iterator()
31+
override def knownSize: Int = underlying.knownSize
32+
}
33+
34+
class MapValues[K, +V, +W](underlying: MapOps[K, V, AnyConstr, _], f: V => W) extends MapView[K, W] {
35+
def iterator(): Iterator[(K, W)] = underlying.iterator().map(kv => (kv._1, f(kv._2)))
36+
override def knownSize: Int = underlying.knownSize
37+
def get(key: K): Option[W] = underlying.get(key).map(f)
38+
}
39+
40+
}

collections/src/main/scala/strawman/collection/View.scala

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,6 @@ object View extends IterableFactoryLike[View] {
195195
override def knownSize = underlying.knownSize
196196
}
197197

198-
class MapValues[K, V, W](underlying: Iterable[(K, V)], f: V => W) extends View[(K, W)] {
199-
def iterator(): Iterator[(K, W)] = underlying.iterator().map(kv => (kv._1, f(kv._2)))
200-
override def knownSize: Int = underlying.knownSize
201-
}
202-
203198
/** A view that flatmaps elements of the underlying collection. */
204199
class FlatMap[A, B](underlying: Iterable[A], f: A => IterableOnce[B]) extends View[B] {
205200
def iterator() = underlying.iterator().flatMap(f)

collections/src/main/scala/strawman/collection/concurrent/TrieMap.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,7 @@ final class TrieMap[K, V] private (r: AnyRef, rtupd: AtomicReferenceFieldUpdater
962962
if (nonReadOnly) readOnlySnapshot().filterKeys(p)
963963
else super.filterKeys(p)
964964
}
965-
override def mapValues[W](f: V => W): collection.View[(K, W)] = {
965+
override def mapValues[W](f: V => W): collection.MapView[K, W] = {
966966
if (nonReadOnly) readOnlySnapshot().mapValues(f)
967967
else super.mapValues(f)
968968
}

test/junit/src/test/scala/strawman/collection/ViewTest.scala

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,22 @@ class ViewTest {
2323
}
2424

2525
@Test
26-
def seqViewReverse(): Unit = {
26+
def seqView(): Unit = {
2727
val xs = List(1, 2, 3).view
2828
assertEquals(List(3, 2, 1), xs.reverse.to(List))
29+
assertEquals(2, xs(1))
2930
// assertEquals(xs, xs.reverse.reverse.to(List)) doesn’t compile
3031
}
3132

33+
@Test
34+
def mapView(): Unit = {
35+
val xs = immutable.Map(1 -> "a", 2 -> "b")
36+
assertEquals("a", xs.view(1))
37+
val ys = xs.mapValues(s => s.toUpperCase)
38+
assertTrue(ys.contains(1))
39+
assertEquals("B", ys(2))
40+
}
41+
3242
@Test
3343
def viewsViewIsNoOp(): Unit = {
3444
def check[A](it: Iterable[A]): Unit = {
@@ -38,5 +48,7 @@ class ViewTest {
3848
check(immutable.Set(1, 2, 3)) // View
3949
check(List(1, 2, 3)) // SeqView
4050
check(immutable.Vector(1, 2, 3)) // IndexedView
51+
check(immutable.Map(1 -> "a", 2 -> "b")) // MapView
4152
}
53+
4254
}

0 commit comments

Comments
 (0)