summaryrefslogtreecommitdiff
path: root/src/library/scala/runtime/Tuple2Zipped.scala
blob: 52dd1da09e8228cad7ad51718e68ccfc8a0a76ad (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2002-2016, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

package scala
package runtime


import scala.collection.{ TraversableLike, IterableLike }
import scala.collection.generic.{ CanBuildFrom => CBF }
import scala.language.{ higherKinds, implicitConversions }

/** This interface is intended as a minimal interface, not complicated
 *  by the requirement to resolve type constructors, for implicit search (which only
 *  needs to find an implicit conversion to Traversable for our purposes.)
 *  @define Coll `ZippedTraversable2`
 *  @define coll collection
 *  @define collectExample
 *  @define willNotTerminateInf
 */
trait ZippedTraversable2[+El1, +El2] extends Any {
  def foreach[U](f: (El1, El2) => U): Unit
}
object ZippedTraversable2 {
  implicit def zippedTraversable2ToTraversable[El1, El2](zz: ZippedTraversable2[El1, El2]): Traversable[(El1, El2)] = {
    new scala.collection.AbstractTraversable[(El1, El2)] {
      def foreach[U](f: ((El1, El2)) => U): Unit = zz foreach Function.untupled(f)
    }
  }
}

final class Tuple2Zipped[El1, Repr1, El2, Repr2](val colls: (TraversableLike[El1, Repr1], IterableLike[El2, Repr2])) extends AnyVal with ZippedTraversable2[El1, El2] {
  private def coll1 = colls._1
  private def coll2 = colls._2

  def map[B, To](f: (El1, El2) => B)(implicit cbf: CBF[Repr1, B, To]): To = {
    val b = cbf(coll1.repr)
    b.sizeHint(coll1)
    val elems2 = coll2.iterator

    for (el1 <- coll1) {
      if (elems2.hasNext)
        b += f(el1, elems2.next())
      else
        return b.result()
    }

    b.result()
  }

  def flatMap[B, To](f: (El1, El2) => TraversableOnce[B])(implicit cbf: CBF[Repr1, B, To]): To = {
    val b = cbf(coll1.repr)
    val elems2 = coll2.iterator

    for (el1 <- coll1) {
      if (elems2.hasNext)
        b ++= f(el1, elems2.next())
      else
        return b.result()
    }

    b.result()
  }

  def filter[To1, To2](f: (El1, El2) => Boolean)(implicit cbf1: CBF[Repr1, El1, To1], cbf2: CBF[Repr2, El2, To2]): (To1, To2) = {
    val b1 = cbf1(coll1.repr)
    val b2 = cbf2(coll2.repr)
    val elems2 = coll2.iterator

    for (el1 <- coll1) {
      if (elems2.hasNext) {
        val el2 = elems2.next()
        if (f(el1, el2)) {
          b1 += el1
          b2 += el2
        }
      }
      else return (b1.result(), b2.result())
    }

    (b1.result(), b2.result())
  }

  def exists(@deprecatedName('f) p: (El1, El2) => Boolean): Boolean = {
    val elems2 = coll2.iterator

    for (el1 <- coll1) {
      if (elems2.hasNext) {
        if (p(el1, elems2.next()))
          return true
      }
      else return false
    }
    false
  }

  def forall(@deprecatedName('f) p: (El1, El2) => Boolean): Boolean =
    !exists((x, y) => !p(x, y))

  def foreach[U](f: (El1, El2) => U): Unit = {
    val elems2 = coll2.iterator

    for (el1 <- coll1) {
      if (elems2.hasNext)
        f(el1, elems2.next())
      else
        return
    }
  }

  override def toString = s"($coll1, $coll2).zipped"
}

object Tuple2Zipped {
  final class Ops[T1, T2](private val x: (T1, T2)) extends AnyVal {
    def invert[El1, CC1[X] <: TraversableOnce[X], El2, CC2[X] <: TraversableOnce[X], That]
      (implicit w1: T1 <:< CC1[El1],
                w2: T2 <:< CC2[El2],
                bf: scala.collection.generic.CanBuildFrom[CC1[_], (El1, El2), That]
      ): That = {
        val buf = bf(x._1)
        val it1 = x._1.toIterator
        val it2 = x._2.toIterator
        while (it1.hasNext && it2.hasNext)
          buf += ((it1.next(), it2.next()))

        buf.result()
      }

    def zipped[El1, Repr1, El2, Repr2]
      (implicit w1: T1 => TraversableLike[El1, Repr1],
                w2: T2 => IterableLike[El2, Repr2]
      ): Tuple2Zipped[El1, Repr1, El2, Repr2] = new Tuple2Zipped((x._1, x._2))
  }
}