Saving a few lines of code. Part I - Infinite loops.

Tuesday, June 17, 2008 by Hristo Kosev | Comments 4

Inspired by Scott Hanselman's quest to read source code to be a better developer I decided to start a series of blog posts and write about anything which comes to my mind in the everyday encountering with THE code here at Telerik. As Scott is doing a great job with his quest I would rather focus on topics in which the distinction between right and wrong is not clear enough. I'm not talking about starting flame wars but rather talking about all the aspects and the different pros and cons of each approach.

Today's topic will be about infinite loops and mostly about infinite loops in which you additionally need some counter in order to use it as an indexer for a collection or for some logging purposes. Typically you need such loops when the break condition is not easily definable. In most cases first you don't even need a counter and the most natural thing to write is:

while (true)  
{  
    ...  
    if (some_condition)  
        break;  
} 

 

Later on you may extend this code with:

int i = 0;  
while (true)  
{  
    ...  
    if (some_condition)  
        break;  
 
    i++;  
} 

 

Of course there's nothing wrong with this unless you (like me) dislike using the "while (true)" statement. May be I dislike it because of this - it acts like a statement but still it's not a "legal" statement. Anyway, this is just my prejudice and you don't need to take it into consideration.
The other way to do the same is writing:

for (int i = 0; i < int.MaxValue; i++)  
{  
    ...  
    if (some_condition)  
        break;  
} 

 

This looks pretty neat and now we don't have "so infinite" loop which could possibly cause an OutOfMemoryException.
Inspired by Matthew Podwysocki's "quest to deliver F# goodies to C#" you could use the Unfold method to define an infinite collection. I've attached a sample project where you could find the necessary classes. With the InitializeInfinite method you could do the following:

var infiniteSequence = UnfoldHelper.InitializeInfinite(x => x + 1);  
foreach (var i in infiniteSequence)  
{  
    ...  
    if (some_condition)  
        break;  
}  
 

 

The benefit of using the Unfold method is that you could easily define different both finite and infinite collections without the need to create new classes and yielding custom sequences.
For example with Unfold you could get and the Fibonacci sequence the following way:

 
Unfold(x => Option.Some(Tuple.New(x.Item1, Tuple.New(x.Item2, x.Item1 + x.Item2))), Tuple.New(1, 1));   
 

 

Not that you'll need the Fibonacci sequence (maybe for calculating the story points of a large user story :) that often but just in case.
Maybe you'll feel tempted to do the following and save an extra line of code:

UnfoldHelper.InitializeInfinite(x => x + 1).ForEach(i =>  
{  
    ...  
    if (some_condition)  
        return;  
}); 

 

First maybe you've noticed that I've used a custom "ForEach" extension method rather than calling ToList().ForEach. Calling the ToList() method for an infinite sequence is a BAD idea. Second the truth is that even with a custom ForEach method the "return" won't get you out of the Action as the ForEach extension method won't respect it. We could achieve a good result with a Func returning a boolean but this way the lines of code will grow which is not the desired effect :)

Should you think of other approaches or pros and cons which I’ve not mentioned, feel free to comment.

Source Code

4 Comments

  • Stefan Dobrev 17 Jun 2008
    I would rather stay with the "well know" industry approaches: while(true) or for(;;) If I have to create some helper I will call it something like: Repeat.Forever(some lambda here)
  • Hristo Kosev 18 Jun 2008
    Oh, I forgot about the for(;;) statement. May be I did it subconsciously :) As for the Repeat.Forever suggestion... it's really better than using the UnfoldHelper.InitializeInfinite. I would recommend Repeat.Infinite though as it will allow Repeat.Finite.
  • Joe Zydeco 20 Jun 2008
    Wow, how can we make code *more * unreadable in the name of saving a few lines? I bet the compiler has a field day with that one too, churning all all kinds of unnecessary junk. Instead of while(true) {}, how about using a boolean running=true and then use a while(running) { if (some condition) running = false }; A lot easier to understand by someone else looking at your code.
  • Xcd Esz 16 Jul 2008
    I have to agree with Joe. Breaks (and returns) in the middle of your loops will make it difficult to follow the logic -- if you have a complicated expression. Remember that having too many lines of code isn't the real problem -- it's only a symptom that you need to break something down into smaller peices.

Add comment

  1. Formatting options
       
     
     
     
     
       
  2. (optional, emails won't be shown on public pages)
  3. (optional)