Question

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?

Was it helpful?

Solution

There are multiple common approaches to avoid repeating a complex update-step:

  1. Use a lambda:

    auto g = [&]{ return mmmmm(rewqreqw(rewqrqew()), rewqrewq(), rewqreqw()); };
    for (auto x = g(); p(x); x = g(x))
        f(x);
    
  2. 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);
    
  3. 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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
scroll top