1

I'm wondering if there's a way to write a function that takes one input, a max count for the number of times to loop, that will do an infinite loop if the number is negative, without using an if-else

i.e.

void func(int nAttempts) // if nAttempts <= 0, do an infinite loop
{
  if ( nAttempts <= 0 )
  { // do an infinite loop
  }
  else
  { // do a loop up to nAttemtps
  }
}

I'd like to know if there's a way to do that without an if-else

riqitang
  • 3,241
  • 4
  • 37
  • 47

4 Answers4

9

while ((nAttempts < 0) || (nAttempts-- > 0)) {...}

but... why? This makes your code less readable, where an if/else makes it pretty clear what your intentions are.

mah
  • 39,056
  • 9
  • 76
  • 93
  • yeah this one's good, I didn't specify but it is for C++ and C++ takes advantage of short-circuiting, like Craig pointed out – riqitang Apr 11 '14 at 17:49
  • I agree that "but why?" is the more appropriate response to this question. Just because you can do something doesn't mean you should. – maxywb Apr 11 '14 at 17:50
  • C also does short circuiting. If you want a solution that doesn't need short circuiting, one could be done with the ternary operator. – mah Apr 11 '14 at 17:51
  • yeah but ternary is pretty much an if-else :P – riqitang Apr 11 '14 at 17:53
  • 1
    I spent a few more minutes writing my description and really dissecting lazy evaluation and such, but we have the same answer. +1 – M2tM Apr 11 '14 at 17:53
  • @sean yep, pretty much, but where it comes to assignments it definitely doesn't look like an if/else. For example, `bool keep_looping = nAttempts!=0; while (keep_looping) { keep_looping = (nAttempts > 0)?(--nAttempts > 0):keep_looping; }` – mah Apr 11 '14 at 17:57
  • Nice, your solution contains the [--> operator](http://stackoverflow.com/questions/1642028). – JohnCand Apr 13 '14 at 22:28
5

I take it this is some sort of a trick question? Here's my take:

void f(int n)
{
    n < 0 ? []{ while(true); }() : [&]{ while(n--); }() ;  
}
jrok
  • 54,456
  • 9
  • 109
  • 141
  • Cute, but probably not what the poster intended. :) I'll give you a +1 anyway. – M2tM Apr 11 '14 at 17:54
  • not a trick question, just curiosity. lots of good answers given, yours is probably the most confusing looking :P – riqitang Apr 11 '14 at 17:56
  • @Sean He is using a **ternary operator** instead of an if statement, and **C++ lambdas** which are immediately evaluated with **operator()** (or the **call operator**). You can google those terms if you're curious. – M2tM Apr 11 '14 at 17:58
  • @M2tM I know what ternary operators are, the confusing thing was the square brackets (the second part of your comment, thank you btw) – riqitang Apr 11 '14 at 18:02
4

The loop itself has a conditional inside of it, it is not an explicit if, but it is a branch. The actual evaluation of that expression is turing complete as well due to lazy evaluation. As a result, this question is kind of nonsensical since even without an if statement, there is still a conditional statement taking place. However, the answer to your question is the following:

void optionalInfiniteLoop(int nAttempts){
    while(nAttempts < 0 || nAttempts-- != 0){
        ...
    }
}

Looking at this and understanding lazy evaluation, nAttempts < 0 is evaluated first. If it is true, the || does not need to run, and so it will never wrap the int around by subtracting too far. If it is false, then the second part of the while loop evaluates until nAttempts becomes 0. I don't think you'd save anything by doing this, and indeed, you may be forcing the computer to do slightly more work every iteration by checking nAttempts < 0 instead of just doing that once.

The performance is almost definitely not going to be measurable in the context of an application, and I think the above looks cleaner, but it's really more of a stylistic approach than a technical one.

M2tM
  • 4,415
  • 1
  • 34
  • 43
  • good point about the computer doing slightly more work by evaluating nAttempts<0 every time instead of just once – riqitang Apr 11 '14 at 18:04
  • Careful about assuming that it's automatically more expensive though, it may be just as efficient as a result of branch prediction or compiler optimization. – M2tM Apr 11 '14 at 18:31
0
void func( int nAttempts )
{
    while (nAttempts)
    {
        // do stuff
        --nAttempts;
    }
}

Basically at the end of every iteration, you subtract one 'try'. When it hits 0 you stop. If it was already negative to begin with, it will become increasingly negative (though I suppose eventually it would overflow).

Cory Kramer
  • 114,268
  • 16
  • 167
  • 218