I often find a situation where I need to write duplicate codes in a for loop, where the "init step" to identical to the "update step":
// duplicate `next()`
for (let x = next(); p(x); x = next()) {
f(x)
}
// the same in a while loop
let x = next()
while (p(x)) {
f(x)
x = next()
}
It is not much a problem when next()
is short, but often it's not:
// problem is evident when next is long or even inline
let x = mmmmm(rewqreqw(rewqrqew()), rewqrewq(), rewqreqw())
while (p(x)) {
f(x)
x = mmmmm(rewqreqw(rewqrqew()), rewqrewq(), rewqreqw())
}
How can I deal with this situation?
-
2Related question: What is priming the pump? Sometimes called a priming readcandied_orange– candied_orange2019年09月27日 08:51:21 +00:00Commented Sep 27, 2019 at 8:51
2 Answers 2
There are multiple common approaches to avoid repeating a complex update-step:
Use a lambda:
auto g = [&]{ return mmmmm(rewqreqw(rewqrqew()), rewqrewq(), rewqreqw()); }; for (auto x = g(); p(x); x = g(x)) f(x);
Use a dummy initialization and assign in the condition:
auto x = dummy; while (p(x = mmmmm(rewqreqw(rewqrqew()), rewqrewq(), rewqreqw()))) f(x);
A variant using the comma-operator:
auto x = dummy; while (x = mmmmm(rewqreqw(rewqrqew()), rewqrewq(), rewqreqw()), p(x)) f(x);
Use an infinite loop with a
break
:for (;;) { auto x = mmmmm(rewqreqw(rewqrqew()), rewqrewq(), rewqreqw()); if (!p(x)) break; f(x); }
Which looks and performs best in your case?
You decide.
-
All of them looks equally good for me. Thanks.Chiawen– Chiawen2019年09月27日 05:42:29 +00:00Commented Sep 27, 2019 at 5:42
I'm not sure what language you're using, but many languages have an abstraction already for calling a function to produce the next element of a sequence, in a more precise way than a for or while loop. It's often called an iterator or a generator.
For example, in Scala, you can write:
Iterator.continually(next()).takeWhile(p).map(f)
If your language supports higher-order functions, you can create your own abstraction easily. It's also sometimes implemented in OOP languages by implementing an interface with something like a getNext
and a hasNext
function.
Explore related questions
See similar questions with these tags.