Skip to content

Commit 83ba0de

Browse files
Backport "Finalize named tuples" to 3.6.0 (#21773)
Backports #21710 to 3.6.0-RC1 --------- Co-authored-by: Eugene Flesselle <[email protected]>
1 parent c8dbbdc commit 83ba0de

File tree

2 files changed

+22
-30
lines changed

2 files changed

+22
-30
lines changed

docs/_docs/reference/other-new-features/named-tuples.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ NamedTuple[("name", "age"), (String, Int)]
127127

128128
A `NamedTuple[N, V]` type is publicly known to be a supertype (but not a subtype) of its value paramater `V`, which means that regular tuples can be assigned to named tuples but not _vice versa_.
129129

130-
The `NamedTuple` object contains a number of extension methods for named tuples hat mirror the same functions in `Tuple`. Examples are
130+
The `NamedTuple` object contains a number of extension methods for named tuples that mirror the same functions in `Tuple`. Examples are
131131
`apply`, `head`, `tail`, `take`, `drop`, `++`, `map`, or `zip`.
132132
Similar to `Tuple`, the `NamedTuple` object also contains types such as `Elem`, `Head`, `Concat`
133133
that describe the results of these extension methods.
@@ -154,7 +154,7 @@ that `c: C`, and that `n` is not otherwise legal as a name of a selection on `c`
154154
Then `c.n` is a legal selection, which expands to `c.selectDynamic("n").asInstanceOf[T]`.
155155

156156
It is the task of the implementation of `selectDynamic` in `C` to ensure that its
157-
computed result conforms to the predicted type `T`
157+
computed result conforms to the predicted type `T`.
158158

159159
As an example, assume we have a query type `Q[T]` defined as follows:
160160

library/src-bootstrapped/scala/NamedTuple.scala

+20-28
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ object NamedTuple:
2525
extension [V <: Tuple](x: V)
2626
inline def withNames[N <: Tuple]: NamedTuple[N, V] = x
2727

28+
import NamedTupleDecomposition.{Names, DropNames}
2829
export NamedTupleDecomposition.{
2930
Names, DropNames,
3031
apply, size, init, head, last, tail, take, drop, splitAt, ++, map, reverse, zip, toList, toArray, toIArray
@@ -134,78 +135,69 @@ object NamedTupleDecomposition:
134135
import NamedTuple.*
135136
extension [N <: Tuple, V <: Tuple](x: NamedTuple[N, V])
136137
/** The value (without the name) at index `n` of this tuple */
137-
inline def apply(n: Int): Tuple.Elem[V, n.type] =
138+
inline def apply(n: Int): Elem[NamedTuple[N, V], n.type] =
138139
inline x.toTuple match
139-
case tup: NonEmptyTuple => tup(n).asInstanceOf[Tuple.Elem[V, n.type]]
140-
case tup => tup.productElement(n).asInstanceOf[Tuple.Elem[V, n.type]]
140+
case tup: NonEmptyTuple => tup(n).asInstanceOf[Elem[NamedTuple[N, V], n.type]]
141+
case tup => tup.productElement(n).asInstanceOf[Elem[NamedTuple[N, V], n.type]]
141142

142143
/** The number of elements in this tuple */
143-
inline def size: Tuple.Size[V] = x.toTuple.size
144+
inline def size: Size[NamedTuple[N, V]] = x.toTuple.size
144145

145146
/** The first element value of this tuple */
146-
inline def head: Tuple.Elem[V, 0] = apply(0)
147+
inline def head: Head[NamedTuple[N, V]] = apply(0)
147148

148149
/** The last element value of this tuple */
149-
inline def last: Tuple.Last[V] = apply(size - 1).asInstanceOf[Tuple.Last[V]]
150+
inline def last: Last[NamedTuple[N, V]] = apply(size - 1).asInstanceOf[Last[NamedTuple[N, V]]]
150151

151152
/** The tuple consisting of all elements of this tuple except the last one */
152-
inline def init: NamedTuple[Tuple.Init[N], Tuple.Init[V]] =
153-
x.toTuple.take(size - 1).asInstanceOf[NamedTuple[Tuple.Init[N], Tuple.Init[V]]]
153+
inline def init: Init[NamedTuple[N, V]] =
154+
x.take(size - 1).asInstanceOf[Init[NamedTuple[N, V]]]
154155

155156
/** The tuple consisting of all elements of this tuple except the first one */
156-
inline def tail: NamedTuple[Tuple.Tail[N], Tuple.Tail[V]] =
157-
x.toTuple.drop(1).asInstanceOf[NamedTuple[Tuple.Tail[N], Tuple.Tail[V]]]
157+
inline def tail: Tail[NamedTuple[N, V]] = x.toTuple.drop(1)
158158

159159
/** The tuple consisting of the first `n` elements of this tuple, or all
160160
* elements if `n` exceeds `size`.
161161
*/
162-
inline def take(n: Int): NamedTuple[Tuple.Take[N, n.type], Tuple.Take[V, n.type]] =
163-
x.toTuple.take(n)
162+
inline def take(n: Int): Take[NamedTuple[N, V], n.type] = x.toTuple.take(n)
164163

165164
/** The tuple consisting of all elements of this tuple except the first `n` ones,
166165
* or no elements if `n` exceeds `size`.
167166
*/
168-
inline def drop(n: Int): NamedTuple[Tuple.Drop[N, n.type], Tuple.Drop[V, n.type]] =
169-
x.toTuple.drop(n)
167+
inline def drop(n: Int): Drop[NamedTuple[N, V], n.type] = x.toTuple.drop(n)
170168

171169
/** The tuple `(x.take(n), x.drop(n))` */
172-
inline def splitAt(n: Int):
173-
(NamedTuple[Tuple.Take[N, n.type], Tuple.Take[V, n.type]],
174-
NamedTuple[Tuple.Drop[N, n.type], Tuple.Drop[V, n.type]]) =
175-
// would be nice if this could have type `Split[NamedTuple[N, V]]` instead, but
176-
// we get a type error then. Similar for other methods here.
177-
x.toTuple.splitAt(n)
170+
inline def splitAt(n: Int): Split[NamedTuple[N, V], n.type] = x.toTuple.splitAt(n)
178171

179172
/** The tuple consisting of all elements of this tuple followed by all elements
180173
* of tuple `that`. The names of the two tuples must be disjoint.
181174
*/
182175
inline def ++ [N2 <: Tuple, V2 <: Tuple](that: NamedTuple[N2, V2])(using Tuple.Disjoint[N, N2] =:= true)
183-
: NamedTuple[Tuple.Concat[N, N2], Tuple.Concat[V, V2]]
176+
: Concat[NamedTuple[N, V], NamedTuple[N2, V2]]
184177
= x.toTuple ++ that.toTuple
185178

186179
/** The named tuple consisting of all element values of this tuple mapped by
187180
* the polymorphic mapping function `f`. The names of elements are preserved.
188181
* If `x = (n1 = v1, ..., ni = vi)` then `x.map(f) = `(n1 = f(v1), ..., ni = f(vi))`.
189182
*/
190-
inline def map[F[_]](f: [t] => t => F[t]): NamedTuple[N, Tuple.Map[V, F]] =
191-
x.toTuple.map(f).asInstanceOf[NamedTuple[N, Tuple.Map[V, F]]]
183+
inline def map[F[_]](f: [t] => t => F[t]): Map[NamedTuple[N, V], F] =
184+
x.toTuple.map[F](f)
192185

193186
/** The named tuple consisting of all elements of this tuple in reverse */
194-
inline def reverse: NamedTuple[Tuple.Reverse[N], Tuple.Reverse[V]] =
195-
x.toTuple.reverse
187+
inline def reverse: Reverse[NamedTuple[N, V]] = x.toTuple.reverse
196188

197-
/** The named tuple consisting of all elements values of this tuple zipped
189+
/** The named tuple consisting of all element values of this tuple zipped
198190
* with corresponding element values in named tuple `that`.
199191
* If the two tuples have different sizes,
200192
* the extra elements of the larger tuple will be disregarded.
201193
* The names of `x` and `that` at the same index must be the same.
202194
* The result tuple keeps the same names as the operand tuples.
203195
*/
204-
inline def zip[V2 <: Tuple](that: NamedTuple[N, V2]): NamedTuple[N, Tuple.Zip[V, V2]] =
196+
inline def zip[V2 <: Tuple](that: NamedTuple[N, V2]): Zip[NamedTuple[N, V], NamedTuple[N, V2]] =
205197
x.toTuple.zip(that.toTuple)
206198

207199
/** A list consisting of all element values */
208-
inline def toList: List[Tuple.Union[V]] = x.toTuple.toList.asInstanceOf[List[Tuple.Union[V]]]
200+
inline def toList: List[Tuple.Union[V]] = x.toTuple.toList
209201

210202
/** An array consisting of all element values */
211203
inline def toArray: Array[Object] = x.toTuple.toArray

0 commit comments

Comments
 (0)