Skip to content

Commit 1ea6692

Browse files
Merge pull request #13786 from danicheg/tuple-append-operator
Add `append` operator to `Tuple`
2 parents afaac17 + ff20e8b commit 1ea6692

File tree

5 files changed

+231
-1
lines changed

5 files changed

+231
-1
lines changed

library/src/scala/Tuple.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ sealed trait Tuple extends Product {
2121
inline def toIArray: IArray[Object] =
2222
runtime.Tuples.toIArray(this)
2323

24+
/** Return a copy of `this` tuple with an element appended */
25+
@experimental
26+
inline def :* [This >: this.type <: Tuple, L] (x: L): Append[This, L] =
27+
runtime.Tuples.append(x, this).asInstanceOf[Append[This, L]]
28+
2429
/** Return a new tuple by prepending the element to `this` tuple.
2530
* This operation is O(this.size)
2631
*/
@@ -78,6 +83,13 @@ sealed trait Tuple extends Product {
7883

7984
object Tuple {
8085

86+
/** Type of a tuple with an element appended */
87+
@experimental
88+
type Append[X <: Tuple, Y] <: Tuple = X match {
89+
case EmptyTuple => Y *: EmptyTuple
90+
case x *: xs => x *: Append[xs, Y]
91+
}
92+
8193
/** Type of the head of a tuple */
8294
type Head[X <: NonEmptyTuple] = X match {
8395
case x *: _ => x

library/src/scala/runtime/Tuples.scala

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,82 @@ object Tuples {
357357
case _ => specialCaseTail(self)
358358
}
359359

360+
// Append for TupleXXL
361+
private def xxlAppend(x: Any, xxl: TupleXXL): TupleXXL = {
362+
val arr = new Array[Object](xxl.productArity + 1)
363+
arr(xxl.productArity) = x.asInstanceOf[Object]
364+
System.arraycopy(xxl.elems, 0, arr, 0, xxl.productArity)
365+
TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]])
366+
}
367+
368+
// Append for Tuple1 to Tuple22
369+
private def specialCaseAppend(x: Any, self: Tuple): Tuple = {
370+
(self: Any) match {
371+
case EmptyTuple =>
372+
Tuple1(x)
373+
case self: Tuple1[_] =>
374+
Tuple2(self._1, x)
375+
case self: Tuple2[_, _] =>
376+
Tuple3(self._1, self._2, x)
377+
case self: Tuple3[_, _, _] =>
378+
Tuple4(self._1, self._2, self._3, x)
379+
case self: Tuple4[_, _, _, _] =>
380+
Tuple5(self._1, self._2, self._3, self._4, x)
381+
case self: Tuple5[_, _, _, _, _] =>
382+
Tuple6(self._1, self._2, self._3, self._4, self._5, x)
383+
case self: Tuple6[_, _, _, _, _, _] =>
384+
Tuple7(self._1, self._2, self._3, self._4, self._5, self._6, x)
385+
case self: Tuple7[_, _, _, _, _, _, _] =>
386+
Tuple8(self._1, self._2, self._3, self._4, self._5, self._6, self._7, x)
387+
case self: Tuple8[_, _, _, _, _, _, _, _] =>
388+
Tuple9(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, x)
389+
case self: Tuple9[_, _, _, _, _, _, _, _, _] =>
390+
Tuple10(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, x)
391+
case self: Tuple10[_, _, _, _, _, _, _, _, _, _] =>
392+
Tuple11(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, x)
393+
case self: Tuple11[_, _, _, _, _, _, _, _, _, _, _] =>
394+
Tuple12(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, x)
395+
case self: Tuple12[_, _, _, _, _, _, _, _, _, _, _, _] =>
396+
Tuple13(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, x)
397+
case self: Tuple13[_, _, _, _, _, _, _, _, _, _, _, _, _] =>
398+
Tuple14(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, x)
399+
case self: Tuple14[_, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
400+
Tuple15(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, x)
401+
case self: Tuple15[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
402+
Tuple16(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, x)
403+
case self: Tuple16[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
404+
Tuple17(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, x)
405+
case self: Tuple17[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
406+
Tuple18(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, x)
407+
case self: Tuple18[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
408+
Tuple19(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, x)
409+
case self: Tuple19[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
410+
Tuple20(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, x)
411+
case self: Tuple20[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
412+
Tuple21(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, x)
413+
case self: Tuple21[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
414+
Tuple22(self._1, self._2, self._3, self._4, self._5, self._6, self._7, self._8, self._9, self._10, self._11, self._12, self._13, self._14, self._15, self._16, self._17, self._18, self._19, self._20, self._21, x)
415+
case self: Tuple22[_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] =>
416+
val arr: Array[Object] = Array(
417+
self._1.asInstanceOf[Object], self._2.asInstanceOf[Object],
418+
self._3.asInstanceOf[Object], self._4.asInstanceOf[Object], self._5.asInstanceOf[Object],
419+
self._6.asInstanceOf[Object], self._7.asInstanceOf[Object], self._8.asInstanceOf[Object],
420+
self._9.asInstanceOf[Object], self._10.asInstanceOf[Object], self._11.asInstanceOf[Object],
421+
self._12.asInstanceOf[Object], self._13.asInstanceOf[Object], self._14.asInstanceOf[Object],
422+
self._15.asInstanceOf[Object], self._16.asInstanceOf[Object], self._17.asInstanceOf[Object],
423+
self._18.asInstanceOf[Object], self._19.asInstanceOf[Object], self._20.asInstanceOf[Object],
424+
self._21.asInstanceOf[Object], self._22.asInstanceOf[Object], x.asInstanceOf[Object]
425+
)
426+
TupleXXL.fromIArray(arr.asInstanceOf[IArray[Object]]).asInstanceOf[Tuple]
427+
}
428+
}
429+
430+
@experimental
431+
def append(x: Any, self: Tuple): Tuple = (self: Any) match {
432+
case xxl: TupleXXL => xxlAppend(x, xxl).asInstanceOf[Tuple]
433+
case _ => specialCaseAppend(x, self)
434+
}
435+
360436
// Init for TupleXXL
361437
private def xxlInit(xxl: TupleXXL): Tuple = {
362438
if (xxl.productArity == 23) {

project/MiMaFilters.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ object MiMaFilters {
66
val Library: Seq[ProblemFilter] = Seq(
77
// Experimental APIs that can be added in 3.2.0
88
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuples.init"),
9-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuples.last")
9+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuples.last"),
10+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuples.append")
1011
)
1112
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
(0)
2+
(0,1)
3+
(0,1,2)
4+
(0,1,2,3)
5+
(0,1,2,3,4)
6+
(0,1,2,3,4,5)
7+
(0,1,2,3,4,5,6)
8+
(0,1,2,3,4,5,6,7)
9+
(0,1,2,3,4,5,6,7,8)
10+
(0,1,2,3,4,5,6,7,8,9)
11+
(0,1,2,3,4,5,6,7,8,9,10)
12+
(0,1,2,3,4,5,6,7,8,9,10,11)
13+
(0,1,2,3,4,5,6,7,8,9,10,11,12)
14+
(0,1,2,3,4,5,6,7,8,9,10,11,12,13)
15+
(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14)
16+
(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
17+
(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)
18+
(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17)
19+
(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18)
20+
(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19)
21+
(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
22+
(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)
23+
(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)
24+
(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23)
25+
(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24)
26+
(0,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)
27+
(1)
28+
(1,2)
29+
(1,2,3)
30+
(1,2,3,4)
31+
(1,2,3,4,5)
32+
(1,2,3,4,5,6)
33+
(1,2,3,4,5,6,7)
34+
(1,2,3,4,5,6,7,8)
35+
(1,2,3,4,5,6,7,8,9)
36+
(1,2,3,4,5,6,7,8,9,10)
37+
(1,2,3,4,5,6,7,8,9,10,11)
38+
(1,2,3,4,5,6,7,8,9,10,11,12)
39+
(1,2,3,4,5,6,7,8,9,10,11,12,13)
40+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14)
41+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
42+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)
43+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17)
44+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18)
45+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19)
46+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
47+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)
48+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)
49+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23)
50+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24)
51+
(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)
52+
(1)
53+
(1,2)
54+
(1,2,3)
55+
(1,2,3,4)
56+
(1,2,3,4,5)
57+
(1,2,3,4,5,6)
58+
(1,2,3,4,5,6,7)
59+
(1,2,3,4,5,6,7,8)
60+
(1,2,3,4,5,6,7,8,9)
61+
(1,2,3,4,5,6,7,8,9,10)
62+
(1,2,3,4,5,6,7,8,9,10,11)
63+
(1,2,3,4,5,6,7,8,9,10,11,12)
64+
(1,2,3,4,5,6,7,8,9,10,11,12,13)
65+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14)
66+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
67+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)
68+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17)
69+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18)
70+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19)
71+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
72+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)
73+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)
74+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23)
75+
(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24)
76+
(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)
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import scala.reflect.ClassTag
2+
3+
object Test {
4+
def main(args: Array[String]): Unit = {
5+
def testArray[T: ClassTag](n: Int, elem: Int => T): Unit = {
6+
val t: Tuple = Tuple.fromArray(Array.tabulate(n)(elem))
7+
println(t :* n)
8+
}
9+
10+
for (i <- 0 to 25)
11+
testArray(i, j => j)
12+
13+
println(Tuple() :* 1)
14+
println(Tuple1(1) :* 2)
15+
println((1, 2) :* 3)
16+
println((1, 2, 3) :* 4)
17+
println((1, 2, 3, 4) :* 5)
18+
println((1, 2, 3, 4, 5) :* 6)
19+
println((1, 2, 3, 4, 5, 6) :* 7)
20+
println((1, 2, 3, 4, 5, 6, 7) :* 8)
21+
println((1, 2, 3, 4, 5, 6, 7, 8) :* 9)
22+
println((1, 2, 3, 4, 5, 6, 7, 8, 9) :* 10)
23+
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10) :* 11)
24+
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) :* 12)
25+
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) :* 13)
26+
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13) :* 14)
27+
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14) :* 15)
28+
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) :* 16)
29+
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) :* 17)
30+
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17) :* 18)
31+
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18) :* 19)
32+
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19) :* 20)
33+
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20) :* 21)
34+
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21) :* 22)
35+
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22) :* 23)
36+
println((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23) :* 24)
37+
println((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)
38+
39+
println(EmptyTuple :* 1)
40+
println((1 *: Tuple()) :* 2)
41+
println((1 *: 2 *: Tuple()) :* 3)
42+
println((1 *: 2 *: 3 *: Tuple()) :* 4)
43+
println((1 *: 2 *: 3 *: 4 *: Tuple()) :* 5)
44+
println((1 *: 2 *: 3 *: 4 *: 5 *: Tuple()) :* 6)
45+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: Tuple()) :* 7)
46+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: Tuple()) :* 8)
47+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: Tuple()) :* 9)
48+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: Tuple()) :* 10)
49+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: Tuple()) :* 11)
50+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: Tuple()) :* 12)
51+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: Tuple()) :* 13)
52+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: Tuple()) :* 14)
53+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: Tuple()) :* 15)
54+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: Tuple()) :* 16)
55+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: Tuple()) :* 17)
56+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: Tuple()) :* 18)
57+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: Tuple()) :* 19)
58+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: Tuple()) :* 20)
59+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: Tuple()) :* 21)
60+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: 21 *: Tuple()) :* 22)
61+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: 21 *: 22 *: Tuple()) :* 23)
62+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: 21 *: 22 *: 23 *: Tuple()) :* 24)
63+
println((1 *: 2 *: 3 *: 4 *: 5 *: 6 *: 7 *: 8 *: 9 *: 10 *: 11 *: 12 *: 13 *: 14 *: 15 *: 16 *: 17 *: 18 *: 19 *: 20 *: 21 *: 22 *: 23 *: 24 *: Tuple()) :* 25)
64+
}
65+
}

0 commit comments

Comments
 (0)