迭代器

让我们回到简单的计数示例:

  1. echo "Counting to ten: "
  2. for i in countup(1, 10):
  3. echo i

一个 countup 过程可以支持这个循环吗?让我们试试:

  1. proc countup(a, b: int): int =
  2. var res = a
  3. while res <= b:
  4. return res
  5. inc(res)

这不行,问题在于过程不应当只 return ,但是迭代器后的return和 continue 已经完成。这 return and continue 叫做 yield 语句。现在只剩下用 iterator 替换 proc 关键字, 它来了——我们的第一个迭代器:

  1. iterator countup(a, b: int): int =
  2. var res = a
  3. while res <= b:
  4. yield res
  5. inc(res)

迭代器看起来像过程,但有几点重要的差异:

  • 迭代器只能从循环中调用。
  • 迭代器不能包含 return 语句(过程不能包含 yield 语句)。
  • 迭代器没有隐式 result 变量。
  • 迭代器不支持递归。
  • 迭代器不能前向声明,因为编译器必须能够内联迭代器。(这个限制将在编译器的未来版本中消失。)

你也可以用 closure 迭代器得到一个不同的限制集合。详见 一等迭代器 。 迭代器可以和过程有同样的名字和形参,因为它们有自己的命名空间。 因此,通常的做法是将迭代器包装在同名的proc中,这些迭代器会累积结果并将其作为序列返回, 像 strutils模块 中的 split