1
1
package scala
2
2
import compiletime .ops .boolean .*
3
+ import compiletime .ops .int .*
4
+ import scala .annotation .experimental
5
+ import scala .annotation .implicitNotFound
3
6
4
7
object NamedTuple :
5
8
@@ -25,10 +28,10 @@ object NamedTuple:
25
28
extension [V <: Tuple ](x : V )
26
29
inline def withNames [N <: Tuple ]: NamedTuple [N , V ] = x
27
30
28
- import NamedTupleDecomposition .{Names , DropNames }
31
+ import NamedTupleDecomposition .{Names , DropNames , Decompose }
29
32
export NamedTupleDecomposition .{
30
- Names , DropNames ,
31
- apply , size , init , head , last , tail , take , drop , splitAt , ++ , map , reverse , zip , toList , toArray , toIArray
33
+ Names , DropNames , Decompose ,
34
+ apply , size , init , head , last , tail , take , drop , splitAt , ++ , copyFrom , map , reverse , zip , toList , toArray , toIArray
32
35
}
33
36
34
37
extension [N <: Tuple , V <: Tuple ](x : NamedTuple [N , V ])
@@ -116,6 +119,14 @@ object NamedTuple:
116
119
case Names [Y ] =>
117
120
NamedTuple [Names [X ], Tuple .Zip [DropNames [X ], DropNames [Y ]]]
118
121
122
+ @ experimental
123
+ type Copy [X <: AnyNamedTuple , Y <: AnyNamedTuple ] = (Decompose [X ], Decompose [Y ]) match
124
+ case ((nx, vx), (ny, vy)) =>
125
+ NamedTuple [
126
+ nx,
127
+ NamedTupleDecomposition .Copy0 [nx, vx, ny, vy, EmptyTuple ]
128
+ ]
129
+
119
130
/** A type specially treated by the compiler to represent all fields of a
120
131
* class argument `T` as a named tuple. Or, if `T` is already a named tuple,
121
132
* `From[T]` is the same as `T`.
@@ -176,6 +187,18 @@ object NamedTupleDecomposition:
176
187
: Concat [NamedTuple [N , V ], NamedTuple [N2 , V2 ]]
177
188
= x.toTuple ++ that.toTuple
178
189
190
+ /** The named tuple consisting of all elements of this tuple, with fields replaced by those from `that`.
191
+ * The field names of the update tuple of updates must all be present in this tuple, but not all fields are required.
192
+ */
193
+ @ experimental
194
+ inline def copyFrom [N2 <: Tuple , V2 <: Tuple ](that : NamedTuple [N2 , V2 ])(using Tuple .ContainsAll [N2 , N ] =:= true )
195
+ : Copy [NamedTuple [N , V ], NamedTuple [N2 , V2 ]]
196
+ = scala.runtime.Tuples .copy(
197
+ self = x.toTuple,
198
+ that = that.toTuple,
199
+ indices = compiletime.constValueTuple[Tuple .Indices [N , N2 ]]
200
+ ).asInstanceOf [Copy [NamedTuple [N , V ], NamedTuple [N2 , V2 ]]]
201
+
179
202
/** The named tuple consisting of all element values of this tuple mapped by
180
203
* the polymorphic mapping function `f`. The names of elements are preserved.
181
204
* If `x = (n1 = v1, ..., ni = vi)` then `x.map(f) = `(n1 = f(v1), ..., ni = f(vi))`.
@@ -207,10 +230,29 @@ object NamedTupleDecomposition:
207
230
208
231
end extension
209
232
233
+ @ experimental
234
+ type LookupName [X , N <: Tuple , V <: Tuple ] <: Option [Any ] =
235
+ (N , V ) match
236
+ case (X *: _, v *: _) => Some [v]
237
+ case (_ *: ns, _ *: vs) => LookupName [X , ns, vs]
238
+ case (EmptyTuple , EmptyTuple ) => None .type
239
+
240
+ @ experimental
241
+ type Copy0 [Nx <: Tuple , Vx <: Tuple , Ny <: Tuple , Vy <: Tuple , Acc <: Tuple ] <: Tuple =
242
+ (Nx , Vx ) match
243
+ case (nx *: nxs, vx *: vxs) => LookupName [nx, Ny , Vy ] match
244
+ case Some [vy] => Copy0 [nxs, vxs, Ny , Vy , vy *: Acc ]
245
+ case _ => Copy0 [nxs, vxs, Ny , Vy , vx *: Acc ]
246
+ case (EmptyTuple , EmptyTuple ) => Tuple .Reverse [Acc ]
247
+
210
248
/** The names of a named tuple, represented as a tuple of literal string values. */
211
249
type Names [X <: AnyNamedTuple ] <: Tuple = X match
212
250
case NamedTuple [n, _] => n
213
251
214
252
/** The value types of a named tuple represented as a regular tuple. */
215
253
type DropNames [NT <: AnyNamedTuple ] <: Tuple = NT match
216
254
case NamedTuple [_, x] => x
255
+
256
+ @ experimental
257
+ type Decompose [NT <: AnyNamedTuple ] <: Tuple = NT match
258
+ case NamedTuple [n, x] => (n, x)
0 commit comments