This must be a common code conversion, so I am surprised that I cannot easily find what it is called nor info on how best to do it.
Original code (pseudo):
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]);
For time-efficiency reasons, I want to lazy-eval the array instead thus:
sub array_start() {...}
sub array_next() {... return val}
array_start();
while (m = array_next())
if some_cond(m) break;
work_with(m);
Yes, it's called "lazy evaluation" generally (design pattern), but isn't this specific and basic type of code conversion called something more specific? I've also looked up "iterator" and "factory" design patterns, and "loop unrolling", but nothing is a good conceptual fit to what I'm talking about. Any ideas? What am I missing? Guidance appreciated.
Update
The answer is "generator" as given below. As for the "conversion" of code, the core change from above would be a[n] =
--> yield
, and of course using whatever syntax defines a generator rather than a subroutine. But it's also possible to implement the idea "by hand" (at least for this simple case), if your language doesn't support it and/or you don't want to use a 3rd-party package to implement it, by "unnesting" all the loops:
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;
}
Note a difference that needs to be handled correctly though: the variables (i
, j
, k
) have become global, or at least exposed.