Skip to content

Commit a7f803d

Browse files
committed
Add generic/IsSeq to stdlib
1 parent 6a690bf commit a7f803d

File tree

1 file changed

+117
-0
lines changed

1 file changed

+117
-0
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Scala (https://www.scala-lang.org)
3+
*
4+
* Copyright EPFL and Lightbend, Inc.
5+
*
6+
* Licensed under Apache License 2.0
7+
* (http://www.apache.org/licenses/LICENSE-2.0).
8+
*
9+
* See the NOTICE file distributed with this work for
10+
* additional information regarding copyright ownership.
11+
*/
12+
13+
package scala.collection
14+
package generic
15+
16+
import scala.reflect.ClassTag
17+
18+
/** Type class witnessing that a collection representation type `Repr` has
19+
* elements of type `A` and has a conversion to `SeqOps[A, Iterable, C]`, for
20+
* some types `A` and `C`.
21+
*
22+
* This type enables simple enrichment of `Seq`s with extension methods which
23+
* can make full use of the mechanics of the Scala collections framework in
24+
* their implementation.
25+
*
26+
* @see [[scala.collection.generic.IsIterable]]
27+
*/
28+
trait IsSeq[Repr] extends IsIterable[Repr] {
29+
30+
@deprecated("'conversion' is now a method named 'apply'", "2.13.0")
31+
override val conversion: Repr => SeqOps[A, Iterable, C] = apply(_)
32+
33+
/** A conversion from the type `Repr` to `SeqOps[A, Iterable, C]`
34+
*
35+
* @note The second type parameter of the returned `SeqOps` value is
36+
* still `Iterable` (and not `Seq`) because `SeqView[A]` only
37+
* extends `SeqOps[A, View, View[A]]`.
38+
*/
39+
def apply(coll: Repr): SeqOps[A, Iterable, C]
40+
}
41+
42+
object IsSeq {
43+
44+
private val seqOpsIsSeqVal: IsSeq[Seq[Any]] =
45+
new IsSeq[Seq[Any]] {
46+
type A = Any
47+
type C = Any
48+
def apply(coll: Seq[Any]): SeqOps[Any, Iterable, Any] = coll
49+
}
50+
51+
implicit def seqOpsIsSeq[CC0[X] <: SeqOps[X, Iterable, CC0[X]], A0]: IsSeq[CC0[A0]] { type A = A0; type C = CC0[A0] } =
52+
seqOpsIsSeqVal.asInstanceOf[IsSeq[CC0[A0]] { type A = A0; type C = CC0[A0] }]
53+
54+
/* Under cc, views are not Seqs and can't use SeqOps.
55+
56+
implicit def seqViewIsSeq[CC0[X] <: SeqView[X], A0]: IsSeq[CC0[A0]] { type A = A0; type C = View[A0] } =
57+
new IsSeq[CC0[A0]] {
58+
type A = A0
59+
type C = View[A]
60+
def apply(coll: CC0[A0]): SeqOps[A0, View, View[A0]] = coll
61+
}
62+
63+
implicit val stringViewIsSeq: IsSeq[StringView] { type A = Char; type C = View[Char] } =
64+
new IsSeq[StringView] {
65+
type A = Char
66+
type C = View[Char]
67+
def apply(coll: StringView): SeqOps[Char, View, View[Char]] = coll
68+
}
69+
70+
*/
71+
implicit val stringIsSeq: IsSeq[String] { type A = Char; type C = String } =
72+
new IsSeq[String] {
73+
type A = Char
74+
type C = String
75+
def apply(s: String): SeqOps[Char, immutable.IndexedSeq, String] =
76+
new SeqOps[Char, immutable.ArraySeq, String] {
77+
def length: Int = s.length
78+
def apply(i: Int): Char = s.charAt(i)
79+
def toIterable: Iterable[Char] = new immutable.WrappedString(s)
80+
protected[this] def coll: String = s
81+
protected[this] def fromSpecific(coll: IterableOnce[Char]): String = coll.iterator.mkString
82+
def iterableFactory: FreeSeqFactory[immutable.ArraySeq] = immutable.ArraySeq.untagged
83+
override def empty: String = ""
84+
protected[this] def newSpecificBuilder: mutable.Builder[Char, String] = new StringBuilder
85+
def iterator: Iterator[Char] = s.iterator
86+
}
87+
}
88+
89+
implicit def arrayIsSeq[A0 : ClassTag]: IsSeq[Array[A0]] { type A = A0; type C = Array[A0] } =
90+
new IsSeq[Array[A0]] {
91+
type A = A0
92+
type C = Array[A0]
93+
def apply(a: Array[A0]): SeqOps[A0, Seq, Array[A0]] =
94+
new SeqOps[A, mutable.ArraySeq, Array[A]] {
95+
def apply(i: Int): A = a(i)
96+
def length: Int = a.length
97+
def toIterable: Iterable[A] = mutable.ArraySeq.make(a)
98+
protected def coll: Array[A] = a
99+
protected def fromSpecific(coll: IterableOnce[A]): Array[A] = Array.from(coll)
100+
def iterableFactory: FreeSeqFactory[mutable.ArraySeq] = mutable.ArraySeq.untagged
101+
override def empty: Array[A] = Array.empty[A]
102+
protected def newSpecificBuilder: mutable.Builder[A, Array[A]] = Array.newBuilder
103+
def iterator: Iterator[A] = a.iterator
104+
}
105+
}
106+
107+
// `Range` can not be unified with the `CC0` parameter of the
108+
// `seqOpsIsSeq` definition because it does not take a type parameter.
109+
// Hence the need for a separate case:
110+
implicit def rangeIsSeq[C0 <: Range]: IsSeq[C0] { type A = Int; type C = immutable.IndexedSeq[Int] } =
111+
new IsSeq[C0] {
112+
type A = Int
113+
type C = immutable.IndexedSeq[Int]
114+
def apply(coll: C0): SeqOps[Int, Seq, immutable.IndexedSeq[Int]] = coll
115+
}
116+
117+
}

0 commit comments

Comments
 (0)