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.


