nim- 迭代器iterator

Nim - 迭代器 Iterator

让我们回到之前的示例代码:

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

可以编写一个支持此循环的计数过程吗(迭代器计数函数)?咱们试试吧:

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

然而这不能工作,这个问题是此过程不仅仅返回最后进行了返回,而且在返回之后继续做了迭代递增的操作(inc(res))。这个returncontinue被称做yield语句。现在我们要做的事情就是用iterator关键字代替proc关键字,这就是我们的第一个迭代器了。

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

迭代器看起来和过程非常相似,但是还是有记得重要的区别的:

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

但是,你可以使用闭包(匿名)迭代器来获得一组不同的约束,查看 first-class iterators 获得更多的细节。迭代器可以具有与进程相同的名称和参数,因为本质上它们有自己的名称空间。因此,通常将迭代器包装在同名的进程中,这些进程累积迭代器的结果并将其作为序列返回,就像从structils modulesplit一样。

一个简单的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
iterator addOne(a, b: int): int =
var res = a
while res <= b:
yield res
inc(res)

iterator reverseOut(a, b: int): int =
var res = b
while res >= a:
yield res
dec(res)

when isMainModule:
for i in addOne(1, 10):
echo i


for i in reverseOut(1, 10):
echo i

nim- 迭代器iterator
http://cvrain.cloudvl.cn/2023/11/29/Nim/nim-iterator/
作者
ClaudeRainer
发布于
2023年11月29日
许可协议