【发布时间】: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;
}
注意一个需要正确处理的区别:变量(i、j、k)已成为全局变量,或者至少是公开的。
【问题讨论】:
-
枚举器?我认为(可能是错误的)MoveNext、MovePrev、Start、End 属于 Enumerator 样式/名称...
-
谢谢。到目前为止,我只发现“枚举器”被描述为“迭代器”的实现接口,并且总是与现有的可枚举集合(而不是延迟计算的值)相关联,但也许还有更多......
-
是的,这里没有真正的术语......你基本上只是循环遍历一个数组,并检查一个条件......没有什么特别或具体的。我以为你指的是你循环的方式(MoveNext 而不是 For Loop)......对不起,我不能帮助你更多。
-
对;抱歉,上面的函数名称可能混淆了——转换后的实现中没有这样的“数组”。这个想法是不计算任何这样的数组,只一个一个地计算它的元素(从而避免对可能永远不会使用的值进行昂贵的计算)。
-
好的...如果您知道该术语是什么,请告诉我...
标签: loops iterator generator lazy-evaluation code-conversion