diff --git a/compat/src/main/scala-2.11/scala/collection/compat/package.scala b/compat/src/main/scala-2.11/scala/collection/compat/package.scala index 988a9fcf..efa2cf7f 100644 --- a/compat/src/main/scala-2.11/scala/collection/compat/package.scala +++ b/compat/src/main/scala-2.11/scala/collection/compat/package.scala @@ -13,6 +13,8 @@ package scala.collection import scala.collection.generic.{CanBuildFrom, GenericOrderedCompanion, IsTraversableLike} + +import scala.runtime.Tuple2Zipped import scala.collection.{immutable => i} import scala.{collection => c} @@ -41,7 +43,16 @@ package object compat extends compat.PackageShared { implicit def toSeqExtensionMethods[A](self: c.Seq[A]): SeqExtensionMethods[A] = new SeqExtensionMethods[A](self) + implicit def toTrulyTraversableLikeExtensionMethods[T1, El1, Repr1](self: T1)( + implicit w1: T1 => TraversableLike[El1, Repr1]) + : TrulyTraversableLikeExtensionMethods[T1, El1, Repr1] = + new TrulyTraversableLikeExtensionMethods[T1, El1, Repr1](self) + + implicit def toTuple2ZippedExtensionMethods[El1, Repr1, El2, Repr2](self: Tuple2Zipped[El1, Repr1, El2, Repr2]) + : Tuple2ZippedExtensionMethods[El1, Repr1, El2, Repr2] = + new Tuple2ZippedExtensionMethods[El1, Repr1, El2, Repr2](self) implicit def toImmutableQueueExtensionMethods[A]( self: i.Queue[A]): ImmutableQueueExtensionMethods[A] = new ImmutableQueueExtensionMethods[A](self) + } diff --git a/compat/src/main/scala-2.11_2.12/scala/collection/compat/PackageShared.scala b/compat/src/main/scala-2.11_2.12/scala/collection/compat/PackageShared.scala index c09682aa..fc3a05c2 100644 --- a/compat/src/main/scala-2.11_2.12/scala/collection/compat/PackageShared.scala +++ b/compat/src/main/scala-2.11_2.12/scala/collection/compat/PackageShared.scala @@ -14,8 +14,17 @@ package scala.collection.compat import scala.collection.generic._ import scala.reflect.ClassTag -import scala.collection.{MapLike, GenTraversable, BitSet, IterableView} -import scala.collection.{immutable => i, mutable => m} +import scala.collection.{ + BitSet, + GenTraversable, + IterableLike, + IterableView, + MapLike, + TraversableLike, + immutable => i, + mutable => m +} +import scala.runtime.{Tuple2Zipped, Tuple3Zipped} import scala.{collection => c} /** The collection compatibility API */ @@ -246,6 +255,7 @@ class TraversableExtensionMethods[A](private val self: c.Traversable[A]) extends def sizeCompare(otherSize: Int): Int = SizeCompareImpl.sizeCompareInt(self)(otherSize) def sizeIs: SizeCompareOps = new SizeCompareOps(self) def sizeCompare(that: c.Traversable[_]): Int = SizeCompareImpl.sizeCompareColl(self)(that) + } class SeqExtensionMethods[A](private val self: c.Seq[A]) extends AnyVal { @@ -361,6 +371,22 @@ class TraversableLikeExtensionMethods[A, Repr](private val self: c.GenTraversabl } } +class TrulyTraversableLikeExtensionMethods[T1, El1, Repr1](private val self: T1) extends AnyVal { + def lazyZip[El2, Repr2, T2](t2: T2)( + implicit w: T1 => TraversableLike[El1, Repr1], + w2: T2 => IterableLike[El2, Repr2]): Tuple2Zipped[El1, Repr1, El2, Repr2] = + new Tuple2Zipped((w(self), t2)) + +} + +class Tuple2ZippedExtensionMethods[El1, Repr1, El2, Repr2](private val self: Tuple2Zipped[El1, Repr1, El2, Repr2]) { + def lazyZip[El3, Repr3, T3](t3: T3)(implicit w3: T3 => IterableLike[El3, Repr3]) + : Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3] = { + + new Tuple3Zipped((self.colls._1, self.colls._2, t3)) + } +} + class MapViewExtensionMethods[K, V, C <: scala.collection.Map[K, V]]( private val self: IterableView[(K, V), C]) extends AnyVal { diff --git a/compat/src/main/scala-2.12/scala/collection/compat/package.scala b/compat/src/main/scala-2.12/scala/collection/compat/package.scala index 20d2d2f1..9596e5d8 100644 --- a/compat/src/main/scala-2.12/scala/collection/compat/package.scala +++ b/compat/src/main/scala-2.12/scala/collection/compat/package.scala @@ -14,8 +14,11 @@ package scala.collection import scala.collection.generic.{CanBuildFrom, GenericOrderedCompanion, IsTraversableLike} import scala.{collection => c} +import scala.collection.{mutable => m} +import scala.runtime.Tuple2Zipped import scala.collection.{immutable => i, mutable => m} + package object compat extends compat.PackageShared { implicit class MutableTreeMapExtensions2(private val fact: m.TreeMap.type) extends AnyVal { def from[K: Ordering, V](source: TraversableOnce[(K, V)]): m.TreeMap[K, V] = @@ -51,7 +54,17 @@ package object compat extends compat.PackageShared { implicit def toSeqExtensionMethods[A](self: c.Seq[A]): SeqExtensionMethods[A] = new SeqExtensionMethods[A](self) + implicit def toTrulyTraversableLikeExtensionMethods[T1, El1, Repr1](self: T1)( + implicit w1: T1 => TraversableLike[El1, Repr1]) + : TrulyTraversableLikeExtensionMethods[T1, El1, Repr1] = + new TrulyTraversableLikeExtensionMethods[T1, El1, Repr1](self) + + implicit def toTuple2ZippedExtensionMethods[El1, Repr1, El2, Repr2](self: Tuple2Zipped[El1, Repr1, El2, Repr2]) + : Tuple2ZippedExtensionMethods[El1, Repr1, El2, Repr2] = + new Tuple2ZippedExtensionMethods[El1, Repr1, El2, Repr2](self) + implicit def toImmutableQueueExtensionMethods[A]( self: i.Queue[A]): ImmutableQueueExtensionMethods[A] = new ImmutableQueueExtensionMethods[A](self) } + diff --git a/compat/src/test/scala/test/scala/collection/LazyZipTest.scala b/compat/src/test/scala/test/scala/collection/LazyZipTest.scala new file mode 100644 index 00000000..84fc1913 --- /dev/null +++ b/compat/src/test/scala/test/scala/collection/LazyZipTest.scala @@ -0,0 +1,43 @@ +package test.scala.collection + +import org.junit.Assert.assertEquals +import org.junit.Test + +import scala.collection.compat._ + +class LazyZipTest { + + private val ws = List(1, 2, 3) + private val xs = List(1, 2, 3, 4, 5, 6) + private val ys = List("a", "b", "c", "d", "e", "f") + private val zs = List(true, false, true, false, true, false) + private val zipped2 = ws lazyZip xs + private val zipped3 = ws lazyZip xs lazyZip ys + private val zipped4 = ws lazyZip xs lazyZip ys lazyZip zs + private val map = Map(1 -> "foo" , 2 -> "bar") + + @Test + def lazyZipTest(): Unit = { + val res: List[(Int, Int)] = zipped2.map((a, b) => (a, b)) + assertEquals(List((1, 1), (2, 2), (3, 3)), res) + } + + @Test + def lazyZip3_map(): Unit = { + val res: List[(Int, Int, String)] = zipped3.map((a: Int, b: Int, c: String) => (a, b, c)) + assertEquals(List((1, 1, "a"), (2, 2, "b"), (3, 3, "c")), res) + } + + @Test + def collectionValueIsNotEvaluated(): Unit = { + val st = Stream.cons(1, throw new AssertionError("should not be evaluated")) + ws.lazyZip(st) + } + + @Test + def zip3collectionValueIsNotEvaluated(): Unit = { + val st = Stream.cons(1, throw new AssertionError("should not be evaluated")) + ws.lazyZip(st).lazyZip(st) + } + +}