Skip to content

Commit

Permalink
Introduce Tuple.ReverseOnto and use it in Tuple.reverse
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolasstucki committed Dec 12, 2023
1 parent d96e9e4 commit 12e7c9e
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 14 deletions.
13 changes: 5 additions & 8 deletions library/src/scala/Tuple.scala
Original file line number Diff line number Diff line change
Expand Up @@ -202,16 +202,13 @@ object Tuple {

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

/** Prepends all elements of a tuple in reverse order onto the other tuple */
@experimental
object Helpers:

/** Type of the reversed tuple */
@experimental
type ReverseImpl[Acc <: Tuple, X <: Tuple] <: Tuple = X match
case x *: xs => ReverseImpl[x *: Acc, xs]
case EmptyTuple => Acc
type ReverseOnto[From <: Tuple, +To <: Tuple] <: Tuple = From match
case x *: xs => ReverseOnto[xs, x *: To]
case EmptyTuple => To

/** Transforms a tuple `(T1, ..., Tn)` into `(T1, ..., Ti)`. */
type Take[T <: Tuple, N <: Int] <: Tuple = N match {
Expand Down
16 changes: 16 additions & 0 deletions tests/pos/TupleReverse.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import scala.Tuple.*
def test[T1, T2, T3, T4] =
summon[Reverse[EmptyTuple] =:= EmptyTuple]
summon[Reverse[T1 *: EmptyTuple] =:= T1 *: EmptyTuple]
summon[Reverse[(T1, T2)] =:= (T2, T1)]
summon[Reverse[(T1, T2, T3)] =:= (T3, T2, T1)]
summon[Reverse[(T1, T2, T3, T4)] =:= (T4, T3, T2, T1)]

summon[Reverse[(T1, T2, T3, T4)] =:= Reverse[(T1, T2, T3, T4)]]
summon[Reverse[(T1, T2, T3, T4)] <:< Reverse[(Any, Any, Any, Any)]]

def test2[Tup <: Tuple] =
summon[Reverse[Tup] =:= Reverse[Tup]]

def test3[T1, T2, T3, T4](tup1: (T1, T2, T3, T4)) =
summon[Reverse[tup1.type] =:= (T4, T3, T2, T1)]
15 changes: 15 additions & 0 deletions tests/pos/TupleReverseOnto.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import scala.Tuple.*
def test[T1, T2, T3, T4] =
summon[ReverseOnto[(T1, T2), (T3, T4)] =:= ReverseOnto[(T1, T2), (T3, T4)]]
summon[ReverseOnto[(T1, T2), (T3, T4)] =:= (T2, T1, T3, T4)]
summon[ReverseOnto[(T1, T2), (T3, T4)] <:< (Any, Any, Any, Any)]
summon[ReverseOnto[(T1, T2), (T3, T4)] <:< ReverseOnto[(Any, Any), (Any, Any)]]
summon[ReverseOnto[(T1, T2), (T3, T4)] =:= Concat[Reverse[(T1, T2)], (T3, T4)]]

def test2[Tup1 <: Tuple, Tup2 <: Tuple] =
summon[ReverseOnto[EmptyTuple, Tup1] =:= Tup1]
summon[ReverseOnto[Tup1, EmptyTuple] =:= Reverse[Tup1]]

def test3[T1, T2, T3, T4](tup1: (T1, T2), tup2: (T3, T4)) =
summon[ReverseOnto[tup1.type, tup2.type] <:< (T2, T1, T3, T4)]
summon[ReverseOnto[tup1.type, tup2.type] =:= T2 *: T1 *: tup2.type]
10 changes: 4 additions & 6 deletions tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,10 @@ val experimentalDefinitionInLibrary = Set(
"scala.quoted.Quotes.reflectModule.TermParamClauseMethods.hasErasedArgs",

// New feature: reverse method on Tuple
"scala.Tuple.reverse",
"scala.Tuple$.Helpers",
"scala.Tuple$.Helpers$",
"scala.Tuple$.Helpers$.ReverseImpl",
"scala.Tuple$.Reverse",
"scala.runtime.Tuples$.reverse"
"scala.Tuple.reverse", // can be stabilized in 3.4
"scala.Tuple$.Reverse", // can be stabilized in 3.4
"scala.Tuple$.ReverseOnto", // can be stabilized in 3.4
"scala.runtime.Tuples$.reverse", // can be stabilized in 3.4
)


Expand Down

0 comments on commit 12e7c9e

Please sign in to comment.