将迭代计算转换为迭代器——这叫什么?

Converting iterated calculation to iterator -- what's this called?

这一定是一个常见的代码转换,所以我很惊讶我无法轻易找到它的名称,也不知道如何最好地做到这一点。

原代码(伪):

sub generate_array {
  for(i=0,n=0;i<X;++i)
    for(j=0;j<Y;++j)
      for(k=0;k<p[i][j];++k,++n)
        a[n] = calculation(i,j,k,n,p);
  return a;
}

m=generate_array();
for(i=0;i<size(m);++i)
  if (some_cond(m[i]) break;
  work_with(m[i]);

出于时间效率的原因,我想对数组进行惰性求值:

sub array_start() {...}
sub array_next() {... return val}

array_start();
while (m = array_next())
  if some_cond(m) break;
  work_with(m);

是的,它通常被称为"lazy evaluation"(设计模式),但是这种特定的和基本的代码转换类型不是更特定的东西吗?我还查阅了 "iterator" 和 "factory" 设计模式,以及 "loop unrolling",但没有什么概念能很好地适合我正在谈论的内容。有任何想法吗?我错过了什么?指导表示赞赏。

更新

答案是“generator”,如下所示。至于代码的 "conversion",上面的核心变化是 a[n] = --> yield,当然使用任何定义生成器而不是子例程的语法。但是也可以实现这个想法 "by hand" (至少对于这个简单的案例),如果你的语言不支持它 and/or 你不想使用第 3 方包来实现它, 通过 "unnesting" 所有循环:

sub array_next {
  if (++k >= p[i][j])
    k = 0;
    if (++j >= Y)
      j = 0;
      if (++i >= X)
        return false
  return calculation(i,j,k,p)
}

sub array_start {
  i = j = k = 0;
}

请注意需要正确处理的差异:变量(ijk)已成为全局变量,或至少已公开。

你这里做的不完全是惰性求值因为它通常是指对某个表达式的延迟求值,这在函数式编程中很常见。来自 Lazy Evaluation 上的维基百科文章:

[...] lazy evaluation, or call-by-need is an evaluation strategy which delays the evaluation of an expression until its value is needed [...]

您在这里构建的内容非常符合术语 generator。来自 Generators 上的维基百科文章:

[...] a generator is a special routine that can be used to control the iteration behaviour of a loop. In fact, all generators are iterators. A generator is very similar to a function that returns an array, in that a generator has parameters, can be called, and generates a sequence of values. However, instead of building an array containing all the values and returning them all at once, a generator yields the values one at a time, which requires less memory and allows the caller to get started processing the first few values immediately.

如果生成的序列是无限的,生成器通常称为 。但是,术语流也用于按需计算的有限序列。