@@ -5,7 +5,7 @@ import compiletime.*
5
5
import compiletime .ops .int .*
6
6
7
7
/** Tuple of arbitrary arity */
8
- sealed trait Tuple extends Product {
8
+ sealed trait Tuple extends Product :
9
9
import Tuple .*
10
10
11
11
/** Create a copy of this tuple as an Array */
@@ -83,9 +83,23 @@ sealed trait Tuple extends Product {
83
83
*/
84
84
inline def reverse [This >: this .type <: Tuple ]: Reverse [This ] =
85
85
runtime.Tuples .reverse(this ).asInstanceOf [Reverse [This ]]
86
- }
87
86
88
- object Tuple {
87
+ /** A tuple with the elements of this tuple in reversed order added in front of `acc` */
88
+ inline def reverseOnto [This >: this .type <: Tuple , Acc <: Tuple ](acc : Acc ): ReverseOnto [This , Acc ] =
89
+ (this .reverse ++ acc).asInstanceOf [ReverseOnto [This , Acc ]]
90
+
91
+ /** A tuple consisting of all elements of this tuple that have types
92
+ * for which the given type level predicate `P` reduces to the literal
93
+ * constant `true`.
94
+ */
95
+ inline def filter [This >: this .type <: Tuple , P [_] <: Boolean ]: Filter [This , P ] =
96
+ val toInclude = constValueTuple[IndicesWhere [This , P ]].toArray
97
+ val arr = new Array [Object ](toInclude.length)
98
+ for i <- 0 until toInclude.length do
99
+ arr(i) = this .productElement(toInclude(i).asInstanceOf [Int ]).asInstanceOf [Object ]
100
+ Tuple .fromArray(arr).asInstanceOf [Filter [This , P ]]
101
+
102
+ object Tuple :
89
103
90
104
/** Type of a tuple with an element appended */
91
105
type Append [X <: Tuple , Y ] <: NonEmptyTuple = X match {
@@ -165,25 +179,38 @@ object Tuple {
165
179
* ```
166
180
* @syntax markdown
167
181
*/
168
- type Filter [Tup <: Tuple , P [_] <: Boolean ] <: Tuple = Tup match {
182
+ type Filter [X <: Tuple , P [_] <: Boolean ] <: Tuple = X match
169
183
case EmptyTuple => EmptyTuple
170
- case h *: t => P [h] match {
184
+ case h *: t => P [h] match
171
185
case true => h *: Filter [t, P ]
172
186
case false => Filter [t, P ]
173
- }
174
- }
175
187
176
- /** Given two tuples, `A1 *: ... *: An * At` and `B1 *: ... *: Bn *: Bt`
177
- * where at least one of `At` or `Bt` is `EmptyTuple` or `Tuple`,
178
- * returns the tuple type `(A1, B1) *: ... *: (An, Bn) *: Ct`
179
- * where `Ct` is `EmptyTuple` if `At` or `Bt` is `EmptyTuple`, otherwise `Ct` is `Tuple`.
188
+ /** A tuple consisting of those indices `N` of tuple `X` where the predicate `P`
189
+ * is true for `Elem[X, N]`. Indices are type level values <: Int.
180
190
*/
181
- type Zip [T1 <: Tuple , T2 <: Tuple ] <: Tuple = (T1 , T2 ) match {
191
+ type IndicesWhere [X <: Tuple , P [_] <: Boolean ] =
192
+ helpers.IndicesWhereHelper [X , P , 0 ]
193
+
194
+ /** The type of the tuple consisting of all element values of
195
+ * tuple `X` zipped with corresponding elements of tuple `Y`.
196
+ * If the two tuples have different sizes,
197
+ * the extra elements of the larger tuple will be disregarded.
198
+ * For example, if
199
+ * ```
200
+ * X = (S1, ..., Si)
201
+ * Y = (T1, ..., Tj) where j >= i
202
+ * ```
203
+ * then
204
+ * ```
205
+ * Zip[X, Y] = ((S1, T1), ..., (Si, Ti))
206
+ * ```
207
+ * @syntax markdown
208
+ */
209
+ type Zip [T1 <: Tuple , T2 <: Tuple ] <: Tuple = (T1 , T2 ) match
182
210
case (h1 *: t1, h2 *: t2) => (h1, h2) *: Zip [t1, t2]
183
211
case (EmptyTuple , _) => EmptyTuple
184
212
case (_, EmptyTuple ) => EmptyTuple
185
213
case _ => Tuple
186
- }
187
214
188
215
/** Converts a tuple `(F[T1], ..., F[Tn])` to `(T1, ... Tn)` */
189
216
type InverseMap [X <: Tuple , F [_]] <: Tuple = X match {
@@ -198,15 +225,13 @@ object Tuple {
198
225
*/
199
226
type IsMappedBy [F [_]] = [X <: Tuple ] =>> X =:= Map [InverseMap [X , F ], F ]
200
227
201
- /** Type of the reversed tuple */
202
- type Reverse [X <: Tuple ] = Helpers .ReverseImpl [EmptyTuple , X ]
203
-
204
- object Helpers :
228
+ /** A tuple with the elements of tuple `X` in reversed order */
229
+ type Reverse [X <: Tuple ] = ReverseOnto [X , EmptyTuple ]
205
230
206
- /** Type of the reversed tuple */
207
- type ReverseImpl [ Acc <: Tuple , X <: Tuple ] <: Tuple = X match
208
- case x *: xs => ReverseImpl [ x *: Acc , xs ]
209
- case EmptyTuple => Acc
231
+ /** A tuple with the elements of tuple `X` in reversed order added in front of `Acc` */
232
+ type ReverseOnto [ X <: Tuple , Acc <: Tuple ] <: Tuple = X match
233
+ case x *: xs => ReverseOnto [xs, x *: Acc ]
234
+ case EmptyTuple => Acc
210
235
211
236
/** Transforms a tuple `(T1, ..., Tn)` into `(T1, ..., Ti)`. */
212
237
type Take [T <: Tuple , N <: Int ] <: Tuple = N match {
@@ -275,7 +300,18 @@ object Tuple {
275
300
given canEqualTuple [H1 , T1 <: Tuple , H2 , T2 <: Tuple ](
276
301
using eqHead : CanEqual [H1 , H2 ], eqTail : CanEqual [T1 , T2 ]
277
302
): CanEqual [H1 *: T1 , H2 *: T2 ] = CanEqual .derived
278
- }
303
+
304
+ object helpers :
305
+
306
+ /** Used to implement IndicesWhere */
307
+ type IndicesWhereHelper [X <: Tuple , P [_] <: Boolean , N <: Int ] <: Tuple = X match
308
+ case EmptyTuple => EmptyTuple
309
+ case h *: t => P [h] match
310
+ case true => N *: IndicesWhereHelper [t, P , S [N ]]
311
+ case false => IndicesWhereHelper [t, P , S [N ]]
312
+
313
+ end helpers
314
+ end Tuple
279
315
280
316
/** A tuple of 0 elements */
281
317
type EmptyTuple = EmptyTuple .type
0 commit comments