@@ -28,100 +28,27 @@ object NamedTuple:
28
28
extension [V <: Tuple ](x : V )
29
29
inline def withNames [N <: Tuple ]: NamedTuple [N , V ] = x
30
30
31
- export NamedTupleDecomposition .{Names , DropNames }
31
+ export NamedTupleDecomposition .{
32
+ Names , DropNames ,
33
+ apply , size , init , last , tail , take , drop , splitAt , ++ , map , reverse , zip , toList , toArray , toIArray
34
+ }
32
35
33
36
extension [N <: Tuple , V <: Tuple ](x : NamedTuple [N , V ])
34
37
38
+ // ALL METHODS DEPENDING ON `toTuple` MUST BE EXPORTED FROM `NamedTupleDecomposition`
35
39
/** The underlying tuple without the names */
36
40
inline def toTuple : V = x
37
41
38
- /** The number of elements in this tuple */
39
- inline def size : Tuple .Size [V ] = toTuple.size
40
-
41
42
// This intentionally works for empty named tuples as well. I think NonEmptyTuple is a dead end
42
43
// and should be reverted, just like NonEmptyList is also appealing at first, but a bad idea
43
44
// in the end.
44
45
45
- /** The value (without the name) at index `n` of this tuple */
46
- inline def apply (n : Int ): Tuple .Elem [V , n.type ] =
47
- inline toTuple match
48
- case tup : NonEmptyTuple => tup(n).asInstanceOf [Tuple .Elem [V , n.type ]]
49
- case tup => tup.productElement(n).asInstanceOf [Tuple .Elem [V , n.type ]]
50
-
51
46
/** The first element value of this tuple */
52
- inline def head : Tuple .Elem [V , 0 ] = apply(0 )
53
-
54
- /** The tuple consisting of all elements of this tuple except the first one */
55
- inline def tail : NamedTuple [Tuple .Tail [N ], Tuple .Tail [V ]] =
56
- toTuple.drop(1 ).asInstanceOf [NamedTuple [Tuple .Tail [N ], Tuple .Tail [V ]]]
57
-
58
- /** The last element value of this tuple */
59
- inline def last : Tuple .Last [V ] = apply(size - 1 ).asInstanceOf [Tuple .Last [V ]]
60
-
61
- /** The tuple consisting of all elements of this tuple except the last one */
62
- inline def init : NamedTuple [Tuple .Init [N ], Tuple .Init [V ]] =
63
- toTuple.take(size - 1 ).asInstanceOf [NamedTuple [Tuple .Init [N ], Tuple .Init [V ]]]
64
-
65
- /** The tuple consisting of the first `n` elements of this tuple, or all
66
- * elements if `n` exceeds `size`.
67
- */
68
- inline def take (n : Int ): NamedTuple [Tuple .Take [N , n.type ], Tuple .Take [V , n.type ]] =
69
- toTuple.take(n)
70
-
71
- /** The tuple consisting of all elements of this tuple except the first `n` ones,
72
- * or no elements if `n` exceeds `size`.
73
- */
74
- inline def drop (n : Int ): NamedTuple [Tuple .Drop [N , n.type ], Tuple .Drop [V , n.type ]] =
75
- toTuple.drop(n)
76
-
77
- /** The tuple `(x.take(n), x.drop(n))` */
78
- inline def splitAt (n : Int ):
79
- (NamedTuple [Tuple .Take [N , n.type ], Tuple .Take [V , n.type ]],
80
- NamedTuple [Tuple .Drop [N , n.type ], Tuple .Drop [V , n.type ]]) =
81
- // would be nice if this could have type `Split[NamedTuple[N, V]]` instead, but
82
- // we get a type error then. Similar for other methods here.
83
- toTuple.splitAt(n)
84
-
85
- /** The tuple consisting of all elements of this tuple followed by all elements
86
- * of tuple `that`. The names of the two tuples must be disjoint.
87
- */
88
- inline def ++ [N2 <: Tuple , V2 <: Tuple ](that : NamedTuple [N2 , V2 ])(using Tuple .Disjoint [N , N2 ] =:= true )
89
- : NamedTuple [Tuple .Concat [N , N2 ], Tuple .Concat [V , V2 ]]
90
- = toTuple ++ that.toTuple
47
+ inline def head : Tuple .Elem [V , 0 ] = x.apply(0 )
91
48
92
49
// inline def :* [L] (x: L): NamedTuple[Append[N, ???], Append[V, L] = ???
93
50
// inline def *: [H] (x: H): NamedTuple[??? *: N], H *: V] = ???
94
51
95
- /** The named tuple consisting of all element values of this tuple mapped by
96
- * the polymorphic mapping function `f`. The names of elements are preserved.
97
- * If `x = (n1 = v1, ..., ni = vi)` then `x.map(f) = `(n1 = f(v1), ..., ni = f(vi))`.
98
- */
99
- inline def map [F [_]](f : [t] => t => F [t]): NamedTuple [N , Tuple .Map [V , F ]] =
100
- toTuple.map(f).asInstanceOf [NamedTuple [N , Tuple .Map [V , F ]]]
101
-
102
- /** The named tuple consisting of all elements of this tuple in reverse */
103
- inline def reverse : NamedTuple [Tuple .Reverse [N ], Tuple .Reverse [V ]] =
104
- toTuple.reverse
105
-
106
- /** The named tuple consisting of all elements values of this tuple zipped
107
- * with corresponding element values in named tuple `that`.
108
- * If the two tuples have different sizes,
109
- * the extra elements of the larger tuple will be disregarded.
110
- * The names of `x` and `that` at the same index must be the same.
111
- * The result tuple keeps the same names as the operand tuples.
112
- */
113
- inline def zip [V2 <: Tuple ](that : NamedTuple [N , V2 ]): NamedTuple [N , Tuple .Zip [V , V2 ]] =
114
- toTuple.zip(that.toTuple)
115
-
116
- /** A list consisting of all element values */
117
- inline def toList : List [Tuple .Union [V ]] = toTuple.toList.asInstanceOf [List [Tuple .Union [V ]]]
118
-
119
- /** An array consisting of all element values */
120
- inline def toArray : Array [Object ] = toTuple.toArray
121
-
122
- /** An immutable array consisting of all element values */
123
- inline def toIArray : IArray [Object ] = toTuple.toIArray
124
-
125
52
end extension
126
53
127
54
/** The size of a named tuple, represented as a literal constant subtype of Int */
@@ -212,6 +139,85 @@ end NamedTuple
212
139
@ experimental
213
140
object NamedTupleDecomposition :
214
141
import NamedTuple .*
142
+ extension [N <: Tuple , V <: Tuple ](x : NamedTuple [N , V ])
143
+ /** The value (without the name) at index `n` of this tuple */
144
+ inline def apply (n : Int ): Tuple .Elem [V , n.type ] =
145
+ inline x.toTuple match
146
+ case tup : NonEmptyTuple => tup(n).asInstanceOf [Tuple .Elem [V , n.type ]]
147
+ case tup => tup.productElement(n).asInstanceOf [Tuple .Elem [V , n.type ]]
148
+
149
+ /** The number of elements in this tuple */
150
+ inline def size : Tuple .Size [V ] = x.toTuple.size
151
+
152
+ /** The last element value of this tuple */
153
+ inline def last : Tuple .Last [V ] = apply(size - 1 ).asInstanceOf [Tuple .Last [V ]]
154
+
155
+ /** The tuple consisting of all elements of this tuple except the last one */
156
+ inline def init : NamedTuple [Tuple .Init [N ], Tuple .Init [V ]] =
157
+ x.toTuple.take(size - 1 ).asInstanceOf [NamedTuple [Tuple .Init [N ], Tuple .Init [V ]]]
158
+
159
+ /** The tuple consisting of all elements of this tuple except the first one */
160
+ inline def tail : NamedTuple [Tuple .Tail [N ], Tuple .Tail [V ]] =
161
+ x.toTuple.drop(1 ).asInstanceOf [NamedTuple [Tuple .Tail [N ], Tuple .Tail [V ]]]
162
+
163
+ /** The tuple consisting of the first `n` elements of this tuple, or all
164
+ * elements if `n` exceeds `size`.
165
+ */
166
+ inline def take (n : Int ): NamedTuple [Tuple .Take [N , n.type ], Tuple .Take [V , n.type ]] =
167
+ x.toTuple.take(n)
168
+
169
+ /** The tuple consisting of all elements of this tuple except the first `n` ones,
170
+ * or no elements if `n` exceeds `size`.
171
+ */
172
+ inline def drop (n : Int ): NamedTuple [Tuple .Drop [N , n.type ], Tuple .Drop [V , n.type ]] =
173
+ x.toTuple.drop(n)
174
+
175
+ /** The tuple `(x.take(n), x.drop(n))` */
176
+ inline def splitAt (n : Int ):
177
+ (NamedTuple [Tuple .Take [N , n.type ], Tuple .Take [V , n.type ]],
178
+ NamedTuple [Tuple .Drop [N , n.type ], Tuple .Drop [V , n.type ]]) =
179
+ // would be nice if this could have type `Split[NamedTuple[N, V]]` instead, but
180
+ // we get a type error then. Similar for other methods here.
181
+ x.toTuple.splitAt(n)
182
+
183
+ /** The tuple consisting of all elements of this tuple followed by all elements
184
+ * of tuple `that`. The names of the two tuples must be disjoint.
185
+ */
186
+ inline def ++ [N2 <: Tuple , V2 <: Tuple ](that : NamedTuple [N2 , V2 ])(using Tuple .Disjoint [N , N2 ] =:= true )
187
+ : NamedTuple [Tuple .Concat [N , N2 ], Tuple .Concat [V , V2 ]]
188
+ = x.toTuple ++ that.toTuple
189
+
190
+ /** The named tuple consisting of all element values of this tuple mapped by
191
+ * the polymorphic mapping function `f`. The names of elements are preserved.
192
+ * If `x = (n1 = v1, ..., ni = vi)` then `x.map(f) = `(n1 = f(v1), ..., ni = f(vi))`.
193
+ */
194
+ inline def map [F [_]](f : [t] => t => F [t]): NamedTuple [N , Tuple .Map [V , F ]] =
195
+ x.toTuple.map(f).asInstanceOf [NamedTuple [N , Tuple .Map [V , F ]]]
196
+
197
+ /** The named tuple consisting of all elements of this tuple in reverse */
198
+ inline def reverse : NamedTuple [Tuple .Reverse [N ], Tuple .Reverse [V ]] =
199
+ x.toTuple.reverse
200
+
201
+ /** The named tuple consisting of all elements values of this tuple zipped
202
+ * with corresponding element values in named tuple `that`.
203
+ * If the two tuples have different sizes,
204
+ * the extra elements of the larger tuple will be disregarded.
205
+ * The names of `x` and `that` at the same index must be the same.
206
+ * The result tuple keeps the same names as the operand tuples.
207
+ */
208
+ inline def zip [V2 <: Tuple ](that : NamedTuple [N , V2 ]): NamedTuple [N , Tuple .Zip [V , V2 ]] =
209
+ x.toTuple.zip(that.toTuple)
210
+
211
+ /** A list consisting of all element values */
212
+ inline def toList : List [Tuple .Union [V ]] = x.toTuple.toList.asInstanceOf [List [Tuple .Union [V ]]]
213
+
214
+ /** An array consisting of all element values */
215
+ inline def toArray : Array [Object ] = x.toTuple.toArray
216
+
217
+ /** An immutable array consisting of all element values */
218
+ inline def toIArray : IArray [Object ] = x.toTuple.toIArray
219
+
220
+ end extension
215
221
216
222
/** The names of a named tuple, represented as a tuple of literal string values. */
217
223
type Names [X <: AnyNamedTuple ] <: Tuple = X match
0 commit comments