Source Edit

This module defines compile-time reflection procs for working with types.

Unstable API.

Example:

  1. import std/typetraits
  2. type A = enum a0 = 2, a1 = 4, a2
  3. type B = enum b0 = 2, b1, b2
  4. assert A is enum
  5. assert A is HoleyEnum
  6. assert A isnot OrdinalEnum
  7. assert B isnot HoleyEnum
  8. assert B is OrdinalEnum
  9. assert int isnot HoleyEnum
  10. type C[T] = enum h0 = 2, h1 = 4
  11. assert C[float] is HoleyEnum

Imports

since, macros

Types

  1. HoleyEnum = (not Ordinal) and enum

Enum with holes. Source Edit

  1. OrdinalEnum = Ordinal and enum

Enum without holes. Source Edit

  1. StaticParam[value] = object

Used to wrap a static value in genericParams. Source Edit

Procs

  1. proc arity(t: typedesc): int {.magic: "TypeTrait", ...raises: [], tags: [],
  2. forbids: [].}

Returns the arity of t. This is the number of “type” components or the number of generic parameters a given type t has.

Example:

  1. doAssert arity(int) == 0
  2. doAssert arity(seq[string]) == 1
  3. doAssert arity(array[3, int]) == 2
  4. doAssert arity((int, int, float, string)) == 4

Source Edit

  1. proc distinctBase(T: typedesc; recursive: static bool = true): typedesc {.
  2. magic: "TypeTrait", ...raises: [], tags: [], forbids: [].}

Returns the base type for distinct types, or the type itself otherwise. If recursive is false, only the immediate distinct base will be returned.

See also:

Example:

  1. type MyInt = distinct int
  2. type MyOtherInt = distinct MyInt
  3. doAssert distinctBase(MyInt) is int
  4. doAssert distinctBase(MyOtherInt) is int
  5. doAssert distinctBase(MyOtherInt, false) is MyInt
  6. doAssert distinctBase(int) is int

Source Edit

  1. proc genericHead(t: typedesc): typedesc {.magic: "TypeTrait", ...raises: [],
  2. tags: [], forbids: [].}

Accepts an instantiated generic type and returns its uninstantiated form. A compile-time error will be produced if the supplied type is not generic.

See also:

Example:

  1. type
  2. Foo[T] = object
  3. FooInst = Foo[int]
  4. Foo2 = genericHead(FooInst)
  5. doAssert Foo2 is Foo and Foo is Foo2
  6. doAssert genericHead(Foo[seq[string]]) is Foo
  7. doAssert not compiles(genericHead(int))
  8. type Generic = concept f
  9. type _ = genericHead(typeof(f))
  10. proc bar(a: Generic): typeof(a) = a
  11. doAssert bar(Foo[string].default) == Foo[string]()
  12. doAssert not compiles bar(string.default)
  13. when false: # these don't work yet
  14. doAssert genericHead(Foo[int])[float] is Foo[float]
  15. doAssert seq[int].genericHead is seq

Source Edit

  1. proc hasClosure(fn: NimNode): bool {....raises: [], tags: [], forbids: [].}

Returns true if the func/proc/etc fn has closure. fn has to be a resolved symbol of kind nnkSym. This implies that the macro that calls this proc should accept typed arguments and not untyped arguments. Source Edit

  1. proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait", ...raises: [], tags: [],
  2. forbids: [].}

Returns true for named tuples, false for any other type.

Example:

  1. doAssert not isNamedTuple(int)
  2. doAssert not isNamedTuple((string, int))
  3. doAssert isNamedTuple(tuple[name: string, age: int])

Source Edit

  1. proc name(t: typedesc): string {.magic: "TypeTrait", ...raises: [], tags: [],
  2. forbids: [].}

Returns the name of t.

Alias for system.`$`(t) since Nim v0.20.

Example:

  1. doAssert name(int) == "int"
  2. doAssert name(seq[string]) == "seq[string]"

Source Edit

  1. proc stripGenericParams(t: typedesc): typedesc {.magic: "TypeTrait", ...raises: [],
  2. tags: [], forbids: [].}

This trait is similar to genericHead, but instead of producing an error for non-generic types, it will just return them unmodified.

Example:

  1. type Foo[T] = object
  2. doAssert stripGenericParams(Foo[string]) is Foo
  3. doAssert stripGenericParams(int) is int

Source Edit

  1. proc supportsCopyMem(t: typedesc): bool {.magic: "TypeTrait", ...raises: [],
  2. tags: [], forbids: [].}

Returns true if t is safe to use for copyMem.

Other languages name a type like these blob.

Source Edit

  1. proc tupleLen(T: typedesc[tuple]): int {.magic: "TypeTrait", ...raises: [],
  2. tags: [], forbids: [].}

Returns the number of elements of the tuple type T.

See also:

Example:

  1. doAssert tupleLen((int, int, float, string)) == 4
  2. doAssert tupleLen(tuple[name: string, age: int]) == 2

Source Edit

Macros

  1. macro enumLen(T: typedesc[enum]): int

Returns the number of items in the enum T.

Example:

  1. type Foo = enum
  2. fooItem1
  3. fooItem2
  4. doAssert Foo.enumLen == 2

Source Edit

Templates

  1. template distinctBase[T](a: T; recursive: static bool = true): untyped

Overload of distinctBase for values.

Example:

  1. type MyInt = distinct int
  2. type MyOtherInt = distinct MyInt
  3. doAssert 12.MyInt.distinctBase == 12
  4. doAssert 12.MyOtherInt.distinctBase == 12
  5. doAssert 12.MyOtherInt.distinctBase(false) is MyInt
  6. doAssert 12.distinctBase == 12

Source Edit

  1. template elementType(a: untyped): typedesc

Returns the element type of a, which can be any iterable (over which you can iterate).

Example:

  1. iterator myiter(n: int): auto =
  2. for i in 0 ..< n:
  3. yield i
  4. doAssert elementType(@[1,2]) is int
  5. doAssert elementType("asdf") is char
  6. doAssert elementType(myiter(3)) is int

Source Edit

  1. template genericParams(T: typedesc): untyped

Returns the tuple of generic parameters for the generic type T.

Note: For the builtin array type, the index generic parameter will always become a range type after it’s bound to a variable.

Example:

  1. type Foo[T1, T2] = object
  2. doAssert genericParams(Foo[float, string]) is (float, string)
  3. type Bar[N: static float, T] = object
  4. doAssert genericParams(Bar[1.0, string]) is (StaticParam[1.0], string)
  5. doAssert genericParams(Bar[1.0, string]).get(0).value == 1.0
  6. doAssert genericParams(seq[Bar[2.0, string]]).get(0) is Bar[2.0, string]
  7. var s: seq[Bar[3.0, string]]
  8. doAssert genericParams(typeof(s)) is (Bar[3.0, string],)
  9. doAssert genericParams(array[10, int]) is (StaticParam[10], int)
  10. var a: array[10, int]
  11. doAssert genericParams(typeof(a)) is (range[0..9], int)

Source Edit

  1. template get(T: typedesc[tuple]; i: static int): untyped

Returns the i-th element of T.

Example:

  1. doAssert get((int, int, float, string), 2) is float

Source Edit

  1. template pointerBase[T](_: typedesc[ptr T | ref T]): typedesc

Returns T for ref T | ptr T.

Example:

  1. assert (ref int).pointerBase is int
  2. type A = ptr seq[float]
  3. assert A.pointerBase is seq[float]
  4. assert (ref A).pointerBase is A # not seq[float]
  5. assert (var s = "abc"; s[0].addr).typeof.pointerBase is char

Source Edit

  1. template toSigned(T: typedesc[SomeInteger and not range]): untyped

Returns a signed type with same bit size as T.

Example:

  1. assert int8.toSigned is int8
  2. assert uint16.toSigned is int16
  3. # range types are currently unsupported:
  4. assert not compiles(toSigned(range[0..7]))

Source Edit

  1. template toUnsigned(T: typedesc[SomeInteger and not range]): untyped

Returns an unsigned type with same bit size as T.

Example:

  1. assert int8.toUnsigned is uint8
  2. assert uint.toUnsigned is uint
  3. assert int.toUnsigned is uint
  4. # range types are currently unsupported:
  5. assert not compiles(toUnsigned(range[0..7]))

Source Edit

  1. template tupleLen(t: tuple): int

Returns the number of elements of the tuple t.

See also:

Example:

  1. doAssert tupleLen((1, 2)) == 2

Source Edit

Exports

$, $, $, $, $, $, $, $, $, $, $, $, $, $, $, $, $, $, $, $, $, $