File tree Expand file tree Collapse file tree 3 files changed +54
-1
lines changed
Expand file tree Collapse file tree 3 files changed +54
-1
lines changed Original file line number Diff line number Diff line change @@ -4351,14 +4351,15 @@ type classes are called `bind many`:idx: types.
43514351
43524352Procs written with the implicitly generic style will often need to refer to the
43534353type parameters of the matched generic type. They can be easily accessed using
4354- the dot syntax:
4354+ `` sugar.extractGeneric `` or the dot syntax:
43554355
43564356.. code-block :: nim
43574357 type Matrix[T, Rows, Columns] = object
43584358 ...
43594359
43604360 proc `[]`(m: Matrix, row, col: int): Matrix.T =
43614361 m.data[col * high(Matrix.Columns) + row]
4362+ # we could've also used ``extractGeneric(Matrix, 0)``
43624363
43634364 Alternatively, the `type ` operator can be used over the proc params for similar
43644365effect when anonymous or distinct type classes are used.
Original file line number Diff line number Diff line change @@ -198,3 +198,34 @@ macro dump*(x: typed): untyped =
198198 let r = quote do :
199199 debugEcho `s`, " = " , `x`
200200 return r
201+
202+ macro extractGeneric * (T: typedesc , index:static [int ]): untyped =
203+ # # extract generic type numbered ``index`` used to construct ``T``. Note:
204+ # # ``-1`` returns ``Foo`` in ``Foo[T]``
205+ runnableExamples:
206+ type Foo [T1 , T2 ]= object
207+ doAssert extractGeneric (Foo [float , string ], 0 ) is float
208+ doAssert extractGeneric (Foo [float , string ], 1 ) is string
209+ doAssert extractGeneric (Foo [float , string ], - 1 ) is Foo
210+
211+ var impl = getTypeImpl (T)
212+ expectKind (impl, nnkBracketExpr)
213+ impl = impl[1 ]
214+ while true :
215+ case impl.kind
216+ of nnkSym:
217+ impl = impl.getImpl
218+ continue
219+ of nnkTypeDef:
220+ impl = impl[2 ]
221+ continue
222+ of nnkBracketExpr:
223+ if index == - 1 :
224+ impl= impl[0 ] # return `Foo` in `Foo[T]`
225+ else :
226+ impl= impl[1 + index] # return `T` in `Foo[T]` (when index = 0)
227+ break
228+ else :
229+ error " internal error: impl.kind: " & $ impl.kind
230+ impl
231+
Original file line number Diff line number Diff line change 1+ discard """
2+ file: "tsugar.nim"
3+ output: ""
4+ """
5+ import sugar
6+ import macros
7+
8+ block extractGeneric:
9+ type Foo [T1 , T2 ]= object
10+ type Foo2 = Foo [float , string ]
11+ doAssert extractGeneric (Foo [float , string ], 1 ) is string
12+ doAssert extractGeneric (Foo2 , 1 ) is string
13+ # workaround for seq[int].T not working,
14+ # see https://github.com/nim-lang/Nim/issues/8433
15+ doAssert extractGeneric (seq [int ], 0 ) is int
16+ doAssert extractGeneric (seq [seq [string ]], 0 ) is seq [string ]
17+ doAssert: not compiles (extractGeneric (seq [int ], 1 ))
18+ doAssert extractGeneric (seq [int ], - 1 ) is seq
19+
20+ type Foo3 [T] = T
21+ doAssert extractGeneric (Foo3 [int ], 0 ) is int
You can’t perform that action at this time.
0 commit comments