泛型

泛型是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. new(result)
  9. result.data = data
  10.  
  11. proc add*[T](root: var BinaryTree[T], n: BinaryTree[T]) =
  12. # 插入节点
  13. if root == nil:
  14. root = n
  15. else:
  16. var it = root
  17. while it != nil:
  18. # 比较数据; 使用对任何有 ``==`` and ``<`` 操作符的类型有用的泛型 ``cmp`` 过程
  19. var c = cmp(it.data, n.data)
  20. if c < 0:
  21. if it.le == nil:
  22. it.le = n
  23. return
  24. it = it.le
  25. else:
  26. if it.ri == nil:
  27. it.ri = n
  28. return
  29. it = it.ri
  30.  
  31. proc add*[T](root: var BinaryTree[T], data: T) =
  32. # 方便过程:
  33. add(root, newNode(data))
  34.  
  35. iterator preorder*[T](root: BinaryTree[T]): T =
  36. # 二叉树前序遍历。
  37. # 因为递归迭代器没有实现,用显式的堆栈(更高效):
  38. var stack: seq[BinaryTree[T]] = @[root]
  39. while stack.len > 0:
  40. var n = stack.pop()
  41. while n != nil:
  42. yield n.data
  43. add(stack, n.ri) # 右子树push到堆栈
  44. n = n.le # 跟随左指针
  45.  
  46. var
  47. root: BinaryTree[string] # 用 ``string`` 实例化一个二叉树
  48. add(root, newNode("hello")) # 实例化 ``newNode`` 和 ``add``
  49. add(root, "world") # 实例化第二个 ``add`` 过程
  50. for str in preorder(root):
  51. stdout.writeLine(str)

该示例显示了通用二叉树。根据上下文,括号用于引入类型参数或实例化通用过程、迭代器或类型。如示例所示,泛型使用重载:使用“add”的最佳匹配。 序列的内置 add 过程没有隐藏,而是在 preorder 迭代器中使用。