【问题标题】:Converting iterated calculation to iterator -- what's this called?将迭代计算转换为迭代器——这叫什么?
【发布时间】:2015-12-21 15:12:10
【问题描述】:

这一定是一种常见的代码转换,所以我很惊讶我无法轻易找到它的名称,也无法找到最好的方法。

原始代码(伪):

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);

是的,它通常称为“惰性求值”(设计模式),但这种特定且基本的代码转换类型不是更具体吗?我还查阅了“迭代器”和“工厂”设计模式,以及“循环展开”,但没有什么能很好地适应我正在谈论的内容。有任何想法吗?我错过了什么?感谢指导。

更新

答案是“generator”,如下所示。至于代码的“转换”,上面的核心变化将是a[n] = --> yield,当然使用定义生成器而不是子例程的任何语法。但是,如果您的语言不支持它和/或您不想使用 3rd-party 包来实现它,也可以“手动”实现这个想法(至少对于这个简单的情况),通过“取消嵌套”所有循环:

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)已成为全局变量,或者至少是公开的。

【问题讨论】:

  • 枚举器?我认为(可能是错误的)MoveNext、MovePrev、Start、End 属于 Enumerator 样式/名称...
  • 谢谢。到目前为止,我只发现“枚举器”被描述为“迭代器”的实现接口,并且总是与现有的可枚举集合(而不是延迟计算的值)相关联,但也许还有更多......
  • 是的,这里没有真正的术语......你基本上只是循环遍历一个数组,并检查一个条件......没有什么特别或具体的。我以为你指的是你循环的方式(MoveNext 而不是 For Loop)......对不起,我不能帮助你更多。
  • 对;抱歉,上面的函数名称可能混淆了——转换后的实现中没有这样的“数组”。这个想法是计算任何这样的数组,只一个一个地计算它的元素(从而避免对可能永远不会使用的值进行昂贵的计算)。
  • 好的...如果您知道该术语是什么,请告诉我...

标签: loops iterator generator lazy-evaluation code-conversion


【解决方案1】:

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

[...] 惰性求值或按需调用是一种求值策略 延迟表达式的评估,直到需要它的值[...]

您在此处构建的内容非常适合 generator 一词。来自Generators 上的维基百科文章:

[...] 生成器是一个特殊的例程,可用于控制 循环的迭代行为。事实上,所有的发电机都是 迭代器。生成器与返回的函数非常相似 一个数组,其中一个生成器有参数,可以被调用,并且 生成一系列值。但是,而不是构建一个数组 包含所有值并一次返回它们,一个生成器 一次产生一个值,这需要更少的内存并允许 调用者立即开始处理前几个值。

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

【讨论】:

  • 是的,就是这样!作为一个纯粹主义者(以及我自己的教育和效率控制),我将在上面的代码中为自己实现这个概念,通过取消所有循环,而不是找到一个包给我​​一个yield 功能。但很高兴知道,这种设计需求之前已经被识别、命名和解决了!
猜你喜欢
  • 1970-01-01
  • 2020-05-18
  • 1970-01-01
  • 2011-03-24
  • 1970-01-01
  • 2016-12-14
  • 1970-01-01
  • 2011-09-02
  • 2011-02-05
相关资源
最近更新 更多