Skip to content

Commit 471fce0

Browse files
authored
Merge pull request #295 from NthPortal/topic/filterKeys-fix/PR
Allow chaining of filterKeys and mapValues
2 parents 1c1572c + cc47fe2 commit 471fce0

File tree

4 files changed

+40
-3
lines changed

4 files changed

+40
-3
lines changed

compat/src/main/scala-2.11/scala/collection/compat/package.scala

+11
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@ package object compat extends compat.PackageShared {
2121
implicit ordering: Ordering[A]): CanBuildFrom[Any, A, CC[A]] =
2222
CompatImpl.simpleCBF(fact.newBuilder[A])
2323

24+
// CanBuildFrom instances for `IterableView[(K, V), Map[K, V]]` that preserve
25+
// the strict type of the view to be `Map` instead of `Iterable`
26+
// Instances produced by this method are used to chain `filterKeys` after `mapValues`
27+
implicit def canBuildFromIterableViewMapLike[K, V, L, W, CC[X, Y] <: Map[X, Y]]: CanBuildFrom[IterableView[(K, V), CC[K, V]], (L, W), IterableView[(L, W), CC[L, W]]] =
28+
new CanBuildFrom[IterableView[(K, V), CC[K, V]], (L, W), IterableView[(L, W), CC[L, W]]] {
29+
// `CanBuildFrom` parameters are used as type constraints, they are not used
30+
// at run-time, hence the dummy builder implementations
31+
def apply(from: IterableView[(K, V), CC[K, V]]) = new TraversableView.NoBuilder
32+
def apply() = new TraversableView.NoBuilder
33+
}
34+
2435
implicit def toTraversableLikeExtensionMethods[Repr](self: Repr)(
2536
implicit traversable: IsTraversableLike[Repr])
2637
: TraversableLikeExtensionMethods[traversable.A, Repr] =

compat/src/main/scala-2.11_2.12/scala/collection/compat/PackageShared.scala

+11-3
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,15 @@ class MapViewExtensionMethods[K, V, C <: scala.collection.Map[K, V]](
354354
implicit bf: CanBuildFrom[IterableView[(K, V), C], (K, W), That]): That =
355355
self.map[(K, W), That] { case (k, v) => (k, f(v)) }
356356

357-
def filterKeys[That](p: K => Boolean)(
358-
implicit bf: CanBuildFrom[IterableView[(K, V), C], (K, V), That]): That =
359-
self.collect[(K, V), That] { case (k, v) if p(k) => (k, v) }
357+
// TODO: Replace the current implementation of `mapValues` with this
358+
// after major version bump when bincompat can be broken.
359+
// At the same time, remove `canBuildFromIterableViewMapLike`
360+
/*
361+
def mapValues[W](f: V => W): IterableView[(K, W), C] =
362+
// the implementation of `self.map` also casts the result
363+
self.map({ case (k, v) => (k, f(v)) }).asInstanceOf[IterableView[(K, W), C]]
364+
*/
365+
366+
def filterKeys(p: K => Boolean): IterableView[(K, V), C] =
367+
self.filter { case (k, _) => p(k) }
360368
}

compat/src/main/scala-2.12/scala/collection/compat/package.scala

+11
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@ package object compat extends compat.PackageShared {
3232
implicit ordering: Ordering[A]): CanBuildFrom[Any, A, CC[A]] =
3333
CompatImpl.simpleCBF(fact.newBuilder[A])
3434

35+
// CanBuildFrom instances for `IterableView[(K, V), Map[K, V]]` that preserve
36+
// the strict type of the view to be `Map` instead of `Iterable`
37+
// Instances produced by this method are used to chain `filterKeys` after `mapValues`
38+
implicit def canBuildFromIterableViewMapLike[K, V, L, W, CC[X, Y] <: Map[X, Y]]: CanBuildFrom[IterableView[(K, V), CC[K, V]], (L, W), IterableView[(L, W), CC[L, W]]] =
39+
new CanBuildFrom[IterableView[(K, V), CC[K, V]], (L, W), IterableView[(L, W), CC[L, W]]] {
40+
// `CanBuildFrom` parameters are used as type constraints, they are not used
41+
// at run-time, hence the dummy builder implementations
42+
def apply(from: IterableView[(K, V), CC[K, V]]) = new TraversableView.NoBuilder
43+
def apply() = new TraversableView.NoBuilder
44+
}
45+
3546
implicit def toTraversableLikeExtensionMethods[Repr](self: Repr)(
3647
implicit traversable: IsTraversableLike[Repr])
3748
: TraversableLikeExtensionMethods[traversable.A, Repr] =

compat/src/test/scala/test/scala/collection/ViewTest.scala

+7
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,11 @@ class ViewTest {
3535
assertEquals(oldStyle.toMap, newStyle.toMap)
3636
}
3737

38+
@Test
39+
def filterKeysMapValues(): Unit = {
40+
val m = Map("a" -> 1, "b" -> 2, "c" -> 3)
41+
assertEquals(Map(), m.view.filterKeys(_.length > 1).mapValues(_ + 1).toMap)
42+
assertEquals(Map(), m.view.mapValues(_ + 1).filterKeys(_.length > 1).toMap)
43+
}
44+
3845
}

0 commit comments

Comments
 (0)