Special Types ============= static[T] --------- **Note**: static[T] is still in development. As their name suggests, static parameters must be known at compile-time: .. code-block:: nim proc precompiledRegex(pattern: static[string]): RegEx = var res {.global.} = re(pattern) return res precompiledRegex("/d+") # Replaces the call with a precompiled # regex, stored in a global variable precompiledRegex(paramStr(1)) # Error, command-line options # are not known at compile-time For the purposes of code generation, all static params are treated as generic params - the proc will be compiled separately for each unique supplied value (or combination of values). Static params can also appear in the signatures of generic types: .. code-block:: nim type Matrix[M,N: static[int]; T: Number] = array[0..(M*N - 1), T] # Note how `Number` is just a type constraint here, while # `static[int]` requires us to supply a compile-time int value AffineTransform2D[T] = Matrix[3, 3, T] AffineTransform3D[T] = Matrix[4, 4, T] var m1: AffineTransform3D[float] # OK var m2: AffineTransform2D[string] # Error, `string` is not a `Number` typedesc -------- `typedesc` is a special type allowing one to treat types as compile-time values (i.e. if types are compile-time values and all values have a type, then typedesc must be their type). When used as a regular proc param, typedesc acts as a type class. The proc will be instantiated for each unique type parameter and one can refer to the instantiation type using the param name: .. code-block:: nim proc new(T: typedesc): ref T = echo "allocating ", T.name new(result) var n = Node.new var tree = new(BinaryTree[int]) When multiple typedesc params are present, they act like a distinct type class (i.e. they will bind freely to different types). To force a bind-once behavior one can use a named alias or an explicit `typedesc` generic param: .. code-block:: nim proc acceptOnlyTypePairs[T: typedesc, U: typedesc](A, B: T; C, D: U) Once bound, typedesc params can appear in the rest of the proc signature: .. code-block:: nim template declareVariableWithType(T: typedesc, value: T) = var x: T = value declareVariableWithType int, 42 Overload resolution can be further influenced by constraining the set of types that will match the typedesc param: .. code-block:: nim template maxval(T: typedesc[int]): int = high(int) template maxval(T: typedesc[float]): float = Inf var i = int.maxval var f = float.maxval var s = string.maxval # error, maxval is not implemented for string The constraint can be a concrete type or a type class.