views:

197

answers:

5

Hi,

Is for keyword obsolete or may become obsolete just as goto in languages like C# or Java? In a few years, will it be strange and suspicious to see an object-oriented code which uses for, like today, it's very suspicious to see gotos?

In other words, is there any reason to know and use for in programs?


I notice that there are a bunch of weaknesses with for that doesn't exist when using foreach:

'For' is rarely used and we rarely need it:

Don't know about scientific development, but to do general stuff, software products and websites not dealing especially with calculus, for is used extremely rarely. I've seen and done many projects where there were no for loop in thousands of lines of code. Probably even when dealing with calculus, manipulating arrays, collections or matrices or ranges is something much more frequent, elegant and useful than a loop.

A few places when it seems that for is required, in fact, it is not, and a collection-oriented solution may be used instead.

Reading source code of beginner developers, I also find for used to do what .NET Framework already does. For example, to fill an array with the same value, repeated N times, some people will use a loop, when they must rather use Enumerable.Repeat().

Sometimes, I see that a loop is used to walk through an array, a collection or an enumerable. foreach would be a much more elegant solution, and shorter to write.

'For' is not Jimmy-proof:

Probably I'm a very bad developer, but very often, when I use for, I make the same mistake again and again: putting something other than a predefined variable in the loop range, like this:

int SomeValue
{
    get
    {
        // Resources-expensive operation goes here.
    }
}

for (int i = 0; i < this.SomeValue; i++)
{
    // Code here.
}

// Instead, a less stupid developer would write:
int someValue = this.SomeValue;
for (int i = 0; i < someValue; i++)
{
    // ...
}

Of course, what's wrong with that is that this.SomeValue is called at each iteration, wasting resources. For example, this evening, I found a terrible mistake I've done: a loop used a 0..N range where N was a property making a query to a database. It was really surprising to see in the SQL Profiler than the same query was repeated 10 000 times.

'For' is ugly:

Maybe it's too subjective, but when manipulating collections all the time, what isn't a second solution more natural to write/read?

// Solution 1. C style.
for (int i = 0; i < 10; i++)
{
    // Do something.
}

// Solution 2. Enumerable-oriented.
foreach (var i in Enumerable.Range(0, 10))
{
    // Do something.
}

By the way, I find the second one easier to understand. Is a difference between:

for (i = 0; i < 10; i++)
for (i = 0; i <= 10; i++)
for (i = 1; i < 10; i++)
for (i = 1; i <= 10; i++)

easy to see? Whereas Enumerable.Range() accepts only two parameters, which are extremely clear: the first one - where to start, and the number of elements.

What about more elaborate code?

foreach (string containingTwo in Enumerable.Range(0, 10).
    Where(c => c.ToString().Contains('2')).
    Select(c => c.ToString().PadLeft(8)))
{
    Console.Write(containingTwo);
}

'For' is too rigid:

It's difficult to extend for. Let's say we want to display a list of pages on a website without using ASP.NET paging control. The most obvious solution would be to display numbers with a for (int i = 1; i <= countPages; i++).

Now, what if the requirements change and we don't want to display every page, but only the first two, the last two, the current and the nearest pages to the current?

If we were using a collection, it would be easy to change. Actually, with a loop, it is not.

'For' is not Linq friendly:

There are plenty of things Linq can do, avoiding writing it by hand. But when we use for, there is no place for Linq. If there is a filtering to do, we must do it ourselves. If the results must be converted, this must be done on a separate line. Yes, of course, lambda expressions can be used inside a simple loop too, but there is no an easy-to-read way to write all the stuff in a single, short line of code. Sum or Average are just not available, just as Join or Except or GroupBy.

+1  A: 

Although some might dislike for, I still see it all the time, and it's a very compact and (in my opinion) readable way to generate loops. I know in Java, everyone uses for loops, in fact I rarely see a foreach construction. That said, there will always be people who will continue to use for loops and people who will hate those people.

On your other question, it is definitely necessary for you to know how to do a for loop (and believe me, it isn't hard), just like you need to know how to do a while loop. There are some things that foreach will be able to do effectively, so you'll occasionally use for. As to whether you use it, that's your choice.

Rafe Kettler
+1  A: 

In Java (and some other languages), you still use the for keyword for a "for each" loop:

for (String s : myListOfString) { 
    // code code code
}

So you might want to rephrase the question, but if you mean "do you think we'll stop using for (int i=0; i<something; i++) loops, then you might definitely be right. In Python, the equivalent of for (int i=0;... loops (for i in range(len(myList))) is discouraged for iterating over a collection (see delnan's comment -- well put), more or less for the reasons you mentioned in your original question.

MatrixFrog
In Python, for always iterates and never counts. But you have the built-in range(), which gives you the numbers you'd count through manually. But its use is only "highly discouraged" when you're using them to iterate a collection (which could be iterated right away). Sometimes, counting is exactly what you want - but not often enough to be included as a seperate syntax.
delnan
Edited to take delnan's comment into account.
MatrixFrog
I don't see exactly why this is the accepted answer. It didn't touch on the question posed at all, except to nit pick the wording (and the "then you might definitely be right" doesn't count, there's no reason for it, it's just thrown out there).
Blindy
@Blindy - with lots of reasons in the question, perhaps there's not so much left to say other than "you might definitely be right" unless you disagree. Possibly the question goes a bit too far, substantially answering (rather than just explaining) itself.
Steve314
@Blindy: I accepted the answer for several reasons. One of them is showing how things are done in Python (also thanks to delnan comment). Another is probably to show that my question was badly formulated and does not make too much sense. ;)
MainMa
+1  A: 

The biggest issue I have with for loops is when they are nested and I accidentally write an i instead of a j or vice-versa... especially inside the for header, such as during the increment or condition part. Luckily I have trained myself to be extra careful in such situations :D

Although not OO, I think for loops are (mostly) obsolete in functional programming.

trinithis
+1  A: 

Am I wrong or should

for (int i = 0; i = someValue; i++)

be

for (int i = 0; i <= someValue; i++)

Also aren't for loops usually better optimized then foreach loops or can the c# jit optimize

foreach (var i in Enumerable.Range(0, 10))
{
    // Do something.
}

into the bytecode equivalent of

for (int i = 0; i < 10; i++)
{
    // Do something.
}

insert standard argument about optimization vs clarity here

If it was up to me we would all be using smalltalk style for loops, ie calling a anonymous function on each of a collection but that might have serious slowdown potential.

Roman A. Taycher
I don't know C#, but the "for each" loop should definitely be faster if you're iterating through a *collection*, not just counting numbers from 0 to n. If the fastest way to iterate is simply indexing, the collection will do that. If there's a faster way (e.g. a linked list) then it will do that instead.
MatrixFrog
And yes, you're right, that's a typo in the question. And it probably wouldn't have happened using a "for each" loop!
MatrixFrog
+4  A: 

In my current C# project, there is one place that still uses a traditional for loop, and that deals with shifting an array left and right to find the best match between two curves. In this case, foreach is simply not semantically proper enough for a stranger to figure out what is going on. This just looks right:

for(int shift = -5; shift <= 5; shift++)
    // shift data and compare

Yes, I could technically use a foreach over a Range(-5,5), but that seems to me like a dirty hack for accomplishing the same thing. I'm not operating on the numbers, but rather they are a component of my operation. I feel a foreach should be over the domain objects you wish to retrieve/update/yield.

I also sometimes deal with very large (millions/billions of elements) double[]s. Running a stopwatch over both a for and foreach, I find that the foreach is about 1.5x slower than the for in processing such arrays. I suspect that by the time .NET 5.0 hits, the performance will be quite similar as everything will be treated as some form of IEnumerable. It's basically there already, at least in spirit.

But for the most part I agree. I think eventually, we will see the purpose of the traditional for loop fade in preference for a foreach style loop. However, I hope that this will subsequently be shortened back into for, because it's simply quicker to type. I never understood why they didn't go the Java route on that and simply allow two different expressions inside for.

drharris
There's still the question of whether it's common enough to be justified as core language syntax. After all, a `for` loop can always be rewritten as a `while` loop. Moving the stepping operation to the end may be less than ideal, but it's not that big a deal, and may arguably even be more appropriate.
Steve314
@Steve314 It's definitely still core language syntax. It's widely used, and there are plenty of lesser known constructs that aren't nearly as widely used that are still "core language syntax" like `switch` statements or `do-while` loops.
Rafe Kettler
@Steve314 The question is not whether another loop style will work (all loops can be rewritten in all other keywords), but what is it _expressing_. A `for` loop simply expresses something different than a `while` does. Look at my shift example above; it simply makes sense. Translate it to a while loop and it loses meaning to the reader. Is it possible? Yes. Is it semantically sound? No. Creating a language is more than giving you the bare-bones to work with; it is about providing semantically obvious keywords for you to express your intent in a particular situation.
drharris
@drharris - Yes absolutely, except that no programming language provides a specific syntactic construct for every single possible semantic construct. If "for" is rarely used in some languages, then it can quite reasonably be obsolete. Otherwise - well, you might as well take my comment about "goto", erm, well, erm, seriously I suppose.
Steve314
@Rafe - My main language is C++ so I'm definitely not a foreach addict. I'm surprised if "switch" is a lesser-used construct, but for "do ... while", I'd quite happily call that obsolete too. It's not just rare, it's potentially confusing. I say we need the Ada `exit when` - *not* just an `if () break` because (1) the here-is-an-exit-point keyword is up front and not hidden - easy e.g. to indent at the same level as your begin/end or braces, and (2) you can name which loop you intend to exit, though personally I think this shouldn't be optional.
Steve314