Skip to content

Commit 1dda4b3

Browse files
committed
Introduce Tuple.ReverseOnto and use it in Tuple.reverse
1 parent d96e9e4 commit 1dda4b3

File tree

4 files changed

+40
-14
lines changed

4 files changed

+40
-14
lines changed

library/src/scala/Tuple.scala

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -202,16 +202,13 @@ object Tuple {
202202

203203
/** Type of the reversed tuple */
204204
@experimental
205-
type Reverse[X <: Tuple] = Helpers.ReverseImpl[EmptyTuple, X]
205+
type Reverse[X <: Tuple] = ReverseOnto[X, EmptyTuple]
206206

207+
/** Prepends all elements of a tuple in reverse order onto the other tuple */
207208
@experimental
208-
object Helpers:
209-
210-
/** Type of the reversed tuple */
211-
@experimental
212-
type ReverseImpl[Acc <: Tuple, X <: Tuple] <: Tuple = X match
213-
case x *: xs => ReverseImpl[x *: Acc, xs]
214-
case EmptyTuple => Acc
209+
type ReverseOnto[From <: Tuple, To <: Tuple] <: Tuple = From match
210+
case x *: xs => ReverseOnto[xs, x *: To]
211+
case EmptyTuple => To
215212

216213
/** Transforms a tuple `(T1, ..., Tn)` into `(T1, ..., Ti)`. */
217214
type Take[T <: Tuple, N <: Int] <: Tuple = N match {

tests/pos/TupleReverse.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import scala.Tuple.*
2+
def test[T1, T2, T3, T4] =
3+
summon[Reverse[EmptyTuple] =:= EmptyTuple]
4+
summon[Reverse[T1 *: EmptyTuple] =:= T1 *: EmptyTuple]
5+
summon[Reverse[(T1, T2)] =:= (T2, T1)]
6+
summon[Reverse[(T1, T2, T3)] =:= (T3, T2, T1)]
7+
summon[Reverse[(T1, T2, T3, T4)] =:= (T4, T3, T2, T1)]
8+
9+
summon[Reverse[(T1, T2, T3, T4)] =:= Reverse[(T1, T2, T3, T4)]]
10+
summon[Reverse[(T1, T2, T3, T4)] <:< Reverse[(Any, Any, Any, Any)]]
11+
12+
def test2[Tup <: Tuple] =
13+
summon[Reverse[Tup] =:= Reverse[Tup]]
14+
15+
def test3[T1, T2, T3, T4](tup1: (T1, T2, T3, T4)) =
16+
summon[Reverse[tup1.type] =:= (T4, T3, T2, T1)]

tests/pos/TupleReverseOnto.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import scala.Tuple.*
2+
def test[T1, T2, T3, T4] =
3+
summon[ReverseOnto[(T1, T2), (T3, T4)] =:= ReverseOnto[(T1, T2), (T3, T4)]]
4+
summon[ReverseOnto[(T1, T2), (T3, T4)] =:= (T2, T1, T3, T4)]
5+
summon[ReverseOnto[(T1, T2), (T3, T4)] <:< (Any, Any, Any, Any)]
6+
summon[ReverseOnto[(T1, T2), (T3, T4)] <:< ReverseOnto[(Any, Any), (Any, Any)]]
7+
summon[ReverseOnto[(T1, T2), (T3, T4)] =:= Concat[Reverse[(T1, T2)], (T3, T4)]]
8+
9+
def test2[Tup1 <: Tuple, Tup2 <: Tuple] =
10+
summon[ReverseOnto[EmptyTuple, Tup1] =:= Tup1]
11+
summon[ReverseOnto[Tup1, EmptyTuple] =:= Reverse[Tup1]]
12+
13+
def test3[T1, T2, T3, T4](tup1: (T1, T2), tup2: (T3, T4)) =
14+
summon[ReverseOnto[tup1.type, tup2.type] <:< (T2, T1, T3, T4)]
15+
summon[ReverseOnto[tup1.type, tup2.type] =:= T2 *: T1 *: tup2.type]

tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,10 @@ val experimentalDefinitionInLibrary = Set(
9292
"scala.quoted.Quotes.reflectModule.TermParamClauseMethods.hasErasedArgs",
9393

9494
// New feature: reverse method on Tuple
95-
"scala.Tuple.reverse",
96-
"scala.Tuple$.Helpers",
97-
"scala.Tuple$.Helpers$",
98-
"scala.Tuple$.Helpers$.ReverseImpl",
99-
"scala.Tuple$.Reverse",
100-
"scala.runtime.Tuples$.reverse"
95+
"scala.Tuple.reverse", // can be stabilized in 3.4
96+
"scala.Tuple$.Reverse", // can be stabilized in 3.4
97+
"scala.Tuple$.ReverseOnto", // can be stabilized in 3.4
98+
"scala.runtime.Tuples$.reverse", // can be stabilized in 3.4
10199
)
102100

103101

0 commit comments

Comments
 (0)