@@ -28,100 +28,26 @@ 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
35
38
/** The underlying tuple without the names */
36
39
inline def toTuple : V = x
37
40
38
- /** The number of elements in this tuple */
39
- inline def size : Tuple .Size [V ] = toTuple.size
40
-
41
41
// This intentionally works for empty named tuples as well. I think NonEmptyTuple is a dead end
42
42
// and should be reverted, just like NonEmptyList is also appealing at first, but a bad idea
43
43
// in the end.
44
44
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
45
/** 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
46
+ inline def head : Tuple .Elem [V , 0 ] = x.apply(0 )
91
47
92
48
// inline def :* [L] (x: L): NamedTuple[Append[N, ???], Append[V, L] = ???
93
49
// inline def *: [H] (x: H): NamedTuple[??? *: N], H *: V] = ???
94
50
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
51
end extension
126
52
127
53
/** The size of a named tuple, represented as a literal constant subtype of Int */
@@ -212,6 +138,85 @@ end NamedTuple
212
138
@ experimental
213
139
object NamedTupleDecomposition :
214
140
import NamedTuple .*
141
+ extension [N <: Tuple , V <: Tuple ](x : NamedTuple [N , V ])
142
+ /** The value (without the name) at index `n` of this tuple */
143
+ inline def apply (n : Int ): Tuple .Elem [V , n.type ] =
144
+ inline x.toTuple match
145
+ case tup : NonEmptyTuple => tup(n).asInstanceOf [Tuple .Elem [V , n.type ]]
146
+ case tup => tup.productElement(n).asInstanceOf [Tuple .Elem [V , n.type ]]
147
+
148
+ /** The number of elements in this tuple */
149
+ inline def size : Tuple .Size [V ] = x.toTuple.size
150
+
151
+ /** The last element value of this tuple */
152
+ inline def last : Tuple .Last [V ] = apply(size - 1 ).asInstanceOf [Tuple .Last [V ]]
153
+
154
+ /** The tuple consisting of all elements of this tuple except the last one */
155
+ inline def init : NamedTuple [Tuple .Init [N ], Tuple .Init [V ]] =
156
+ x.toTuple.take(size - 1 ).asInstanceOf [NamedTuple [Tuple .Init [N ], Tuple .Init [V ]]]
157
+
158
+ /** The tuple consisting of all elements of this tuple except the first one */
159
+ inline def tail : NamedTuple [Tuple .Tail [N ], Tuple .Tail [V ]] =
160
+ x.toTuple.drop(1 ).asInstanceOf [NamedTuple [Tuple .Tail [N ], Tuple .Tail [V ]]]
161
+
162
+ /** The tuple consisting of the first `n` elements of this tuple, or all
163
+ * elements if `n` exceeds `size`.
164
+ */
165
+ inline def take (n : Int ): NamedTuple [Tuple .Take [N , n.type ], Tuple .Take [V , n.type ]] =
166
+ x.toTuple.take(n)
167
+
168
+ /** The tuple consisting of all elements of this tuple except the first `n` ones,
169
+ * or no elements if `n` exceeds `size`.
170
+ */
171
+ inline def drop (n : Int ): NamedTuple [Tuple .Drop [N , n.type ], Tuple .Drop [V , n.type ]] =
172
+ x.toTuple.drop(n)
173
+
174
+ /** The tuple `(x.take(n), x.drop(n))` */
175
+ inline def splitAt (n : Int ):
176
+ (NamedTuple [Tuple .Take [N , n.type ], Tuple .Take [V , n.type ]],
177
+ NamedTuple [Tuple .Drop [N , n.type ], Tuple .Drop [V , n.type ]]) =
178
+ // would be nice if this could have type `Split[NamedTuple[N, V]]` instead, but
179
+ // we get a type error then. Similar for other methods here.
180
+ x.toTuple.splitAt(n)
181
+
182
+ /** The tuple consisting of all elements of this tuple followed by all elements
183
+ * of tuple `that`. The names of the two tuples must be disjoint.
184
+ */
185
+ inline def ++ [N2 <: Tuple , V2 <: Tuple ](that : NamedTuple [N2 , V2 ])(using Tuple .Disjoint [N , N2 ] =:= true )
186
+ : NamedTuple [Tuple .Concat [N , N2 ], Tuple .Concat [V , V2 ]]
187
+ = x.toTuple ++ that.toTuple
188
+
189
+ /** The named tuple consisting of all element values of this tuple mapped by
190
+ * the polymorphic mapping function `f`. The names of elements are preserved.
191
+ * If `x = (n1 = v1, ..., ni = vi)` then `x.map(f) = `(n1 = f(v1), ..., ni = f(vi))`.
192
+ */
193
+ inline def map [F [_]](f : [t] => t => F [t]): NamedTuple [N , Tuple .Map [V , F ]] =
194
+ x.toTuple.map(f)
195
+
196
+ /** The named tuple consisting of all elements of this tuple in reverse */
197
+ inline def reverse : NamedTuple [Tuple .Reverse [N ], Tuple .Reverse [V ]] =
198
+ x.toTuple.reverse
199
+
200
+ /** The named tuple consisting of all elements values of this tuple zipped
201
+ * with corresponding element values in named tuple `that`.
202
+ * If the two tuples have different sizes,
203
+ * the extra elements of the larger tuple will be disregarded.
204
+ * The names of `x` and `that` at the same index must be the same.
205
+ * The result tuple keeps the same names as the operand tuples.
206
+ */
207
+ inline def zip [V2 <: Tuple ](that : NamedTuple [N , V2 ]): NamedTuple [N , Tuple .Zip [V , V2 ]] =
208
+ x.toTuple.zip(that.toTuple)
209
+
210
+ /** A list consisting of all element values */
211
+ inline def toList : List [Tuple .Union [V ]] = x.toTuple.toList
212
+
213
+ /** An array consisting of all element values */
214
+ inline def toArray : Array [Object ] = x.toTuple.toArray
215
+
216
+ /** An immutable array consisting of all element values */
217
+ inline def toIArray : IArray [Object ] = x.toTuple.toIArray
218
+
219
+ end extension
215
220
216
221
/** The names of a named tuple, represented as a tuple of literal string values. */
217
222
type Names [X <: AnyNamedTuple ] <: Tuple = X match
0 commit comments