泛型

泛型是Nim用 类型形参 参数化过程、迭代器或类型的方法 。 根据上下文,括号用于引入类型形参或实例化泛型过程、迭代器或类型。

以下示例显示了可以建模的通用二叉树:

  1. type
  2. BinaryTree*[T] = ref object # 二叉树是左右子树带有泛型形参 ``T`` 的泛型类型,其值可能为nil
  3. le, ri: BinaryTree[T]
  4. data: T # 数据存储在节点中。
  5.  
  6. proc newNode*[T](data: T): BinaryTree[T] =
  7. # 构造一个节点
  8. result = BinaryTree[T](le: nil, ri: nil, data: data)
  9.  
  10. proc add*[T](root: var BinaryTree[T], n: BinaryTree[T]) =
  11. # 把节点插入到一颗树
  12. if root == nil:
  13. root = n
  14. else:
  15. var it = root
  16. while it != nil:
  17. # 比较数据项;使用泛型 ``cmp`` proc,适用于任何具有``==``和````运算符的类型
  18. var c = cmp(it.data, n.data)
  19. if c < 0:
  20. if it.le == nil:
  21. it.le = n
  22. return
  23. it = it.le
  24. else:
  25. if it.ri == nil:
  26. it.ri = n
  27. return
  28. it = it.ri
  29.  
  30. proc add*[T](root: var BinaryTree[T], data: T) =
  31. # 便利过程:
  32. add(root, newNode(data))
  33.  
  34. iterator preorder*[T](root: BinaryTree[T]): T =
  35. # 前序遍历二叉树
  36. # 由于递归迭代器尚未实现,因此它使用显式堆栈(因为更高效):
  37. var stack: seq[BinaryTree[T]] = @[root]
  38. while stack.len > 0:
  39. var n = stack.pop()
  40. while n != nil:
  41. yield n.data
  42. add(stack, n.ri) # 将右子树推入堆栈
  43. n = n.le # 跟着左指针
  44.  
  45. var
  46. root: BinaryTree[string] # 使用 ``string`` 实例化二叉树
  47. add(root, newNode("hello")) # 实例化 ``newNode`` 和 ``add``
  48. add(root, "world") # 实例化第二个 ``add`` proc
  49. for str in preorder(root):
  50. stdout.writeLine(str)

T 被称为 泛型类型形参 或 类型变量 。