Generics

18.1 Generic Procedures

proc maxOf[T](a, b: T): T = (if a > b: a else: b)
echo maxOf(3, 7), maxOf("a", "b")
echo maxOf[float](1, 2.5)          # explicit instantiation

18.2 Generic Types

type
  Stack[T] = object
    items: seq[T]

proc push[T](s: var Stack[T], x: T) = s.items.add x
proc pop[T](s: var Stack[T]): T = s.items.pop()
proc isEmpty[T](s: Stack[T]): bool = s.items.len == 0

var st: Stack[int]
st.push 1; st.push 2
echo st.pop()

type Pair[K, V] = object
  key: K
  val: V

18.3 Constraints

proc sumAll[T: SomeNumber](xs: openArray[T]): T =
  for x in xs: result += x
proc show[T: string | int](x: T) = echo x
proc process[T: Comparable](x: T) = discard        # concept constraint (Module 30)

18.4 mixin and bind

Symbol lookup in generics: mixin defers lookup to instantiation (open symbol), bind forces early binding.

proc serialize[T](x: T): string =
  mixin toJsonStr        # resolved where serialize is instantiated
  toJsonStr(x)

18.5 Generic Specialization with when

proc describe[T](x: T): string =
  when T is SomeInteger: "integer"
  elif T is string: "string"
  elif compiles(x.len): "has length"
  else: "unknown"