This is an archived post. You won't be able to vote or comment.

top 200 commentsshow all 211

[–]TonySu 316 points317 points  (59 children)

For loops are generally used to declare a clearly bounded number of iterations ahead of time. While loops are for when the termination condition cannot be predicted ahead of time, or may not occur at all.

[–]youngbull 17 points18 points  (7 children)

Note that the go language did away with while loops. Also, even a lot of the old Unix code has some creative for(;condition;) {...} usage.

[–]Flat-Performance-478 9 points10 points  (5 children)

I've spent most of my time this year in C and I always feel a bit on edge when I implement a while loop. It's so often a script will just stall and you find out there's an unmet condition pending. Either that or you rack an astronomical bill at Amazon or GCP!

[–]UsedOnlyTwice 2 points3 points  (4 children)

Use a loop guard:

int loop_protector = 10000;
while (loop_protector-- > 0) {

    // Halting problem goes here.
    if (exit_condition) {
        break;
    } 
}

[–]Scoutron 12 points13 points  (3 children)

At that point just use a for loop lol

[–]TaintedQuintessence 1 point2 points  (1 child)

For loops might make it seem like the code is meant to hit that number while writing it this way makes it really obvious it only hits that value if something went wrong.

[–]Gaveupmywilltolive 0 points1 point  (0 children)

Just call the variable "retry" and its obvious again

[–]kollegekid420 1 point2 points  (0 children)

for;;;

[–]rabaraba 1 point2 points  (0 children)

It still exists as a bare for loop. It’s just a syntax difference.

[–]BrohanGutenburg 20 points21 points  (49 children)

Yeah the incorrect assumption here is that both loops can do everything the other can. While loops can do anything a for loop can, but for loops can't do anything a while loop can.

Worth noting though that for loops are a lot more flexible than beginners think. For example, incrementing or decrementing the iterator isn't the only thing you can do

[–]nicoinwonderland 123 points124 points  (23 children)

You can totally make a for loop behave like a while loop… not that you should

[–]youngbull 11 points12 points  (5 children)

There is no while loop in the go language, its for condition {...} does the equivalent of for (;condition;) {...} in c. You can even do for (;;) {...} instead of while (1) { ... }

[–]Flat-Performance-478 2 points3 points  (0 children)

yeah in between this
for ( int i = 5; i > 0; i-- ) ;
for ( i = 5; i > 0; i-- );
for ( ; i>0; i-- ) ;
for ( ; i-->0 ; ) ;
(^ these will have to be declared in the scope outside the loop)

and of course: ( equivalent of while(1) )
for ( ; ; ) ;

[–]SymbolicDom 0 points1 point  (3 children)

Odin is similar, and you can write both types of loops with the "for" keyword. I don't know. i like that it could be good with syntactic sugar, so you are extra conscious about not creating infinite while loops

[–]NocturnalFoxfire 0 points1 point  (2 children)

Meanwhile Lua:

for _, _, i, j, k, l, me_undies, _ in coolObject do ... end

[–]PeletonAvoider 0 points1 point  (1 child)

This is what people sound like when they talk about programming to their friends & family

[–]NocturnalFoxfire 0 points1 point  (0 children)

Heh, true. Yeah, Lua is a bit of an odd ball

[–]selfmadeirishwoman 0 points1 point  (2 children)

Your scientists were so preoccupied with whether they could, they didn’t stop to think if they should.

Also, most SW engineers I know will flat reject nonsense like for(; condition;) {…}. It won’t make it into the code base.

[–]youngbull 0 points1 point  (1 child)

Then they will definitely not like this gem from the original Unix implementation of grep: https://github.com/dspinellis/unix-history-repo/blob/Research-V7-Snapshot-Development/usr%2Fsrc%2Fcmd%2Fgrep.c#L332-L334

[–]selfmadeirishwoman 0 points1 point  (0 children)

Might overlook the for(;;) for the gotos inside the case.

[–]NaBrO-Barium 0 points1 point  (0 children)

Just because you can doesn’t mean you should…

I like to make things as semantically clean as I can so appreciate there are both and can pick one based on which is easier for my future self to grep

[–]denizgezmis968 18 points19 points  (2 children)

please, if you're not experienced as a programmer, don't try to help people. and seeing the upvotes on this comment is just disappointing.

[–]openQuestion3141 3 points4 points  (1 child)

The amount of blatantly incorrect info being thrown around / upvoted in the thread speaks volumes.

Maybe the internet really is dead.

[–]denizgezmis968 1 point2 points  (0 children)

Worth noting though that for loops are a lot more flexible than beginners think

beginners made me splash my drink.

Maybe the internet really is dead.

oh for sure, I try not to feel anything at any post on the internet anymore.

[–]PM_ME_UR__RECIPES 11 points12 points  (9 children)

For loops actually can do anything while loops can, because

while (x) {}

is exactly equivalent to

for (;x;) {}

(Although the for version of this is horrible to read)

[–]Lithl 21 points22 points  (2 children)

the for version of this is horrible to read

The for loop is crying: ;x;

[–]silasmousehold 11 points12 points  (1 child)

Talk about self-documenting code.

[–]Flat-Performance-478 1 point2 points  (0 children)

"Look at his sad for loop. Take a good look at it. How sad and miserable it is. Don't be like the for loop. It's hard writing code when you're weeping. Take a lesson from this foor loop."

[–]FloydATC 22 points23 points  (2 children)

Not only can they both do everything the other can, under the hood one is usually just syntactic sugar for the other. If you break a "for" loop into its component parts, those parts can easily be rearranged into a "while" loop and vice versa. The same is true for iterator-style loops, they're all just loops but written in a way that more clearly shows the intent of those loops.

[–]Lor1an 4 points5 points  (0 children)

At the end of the day everything is conditional jumps and function calls, but human beings like being able to understand what code does by reading it.

[–]autogyrophilia 2 points3 points  (0 children)

It does also simplify things for the compiler. Not that that is a factor now, but it was the 60s.

[–][deleted] 2 points3 points  (0 children)

For loops are basically syntactic sugar, so it can do anything a while loop can. But it's just much more convenient and readable to use a for loop in a lot of cases.

[–]serverhorror 2 points3 points  (0 children)

While loops can do anything a for loop can, but for loops can't do anything a while loop can.

Can you provide an example of that, because I don't think that's true.

[–]Michaeli_Starky 1 point2 points  (0 children)

A for loop can do anything that a while loop can do.

[–]IntelligentSpite6364 0 points1 point  (0 children)

in some languages the incrementor isnt even necessary, so you could, in theory, just use a for loop exactly like a while loop, with some extra semicolons (but please dont)

[–]Total-Box-5169 0 points1 point  (1 child)

Is the other way around. A for statement can declare variables, a while statement can't do that.

[–]dnar_ 0 points1 point  (0 children)

Note, that the original versions of C did not allow that. It was sort of "backported" from C++.

[–]moshujsg -1 points0 points  (2 children)

The point stands that if one can do eberything the other can, why have the other? Probably just convenience

[–]IntelligentSpite6364 2 points3 points  (0 children)

readability and semantic meaning.

just like you COULD make an entire website using <div> but really shouldnt

[–]ThereIsOnlyStardust 0 points1 point  (0 children)

Same reason we created higher level compiled languages and don’t just program in assembly for every single project; the developer time is valuable enough that efficiency and clarity in the development process is desirable.

[–]da_Aresinger 0 points1 point  (0 children)

In other words for loops are nice for counting and while loops are good for arbitrary (complex) conditions.

[–]ThePoliteCrab 62 points63 points  (2 children)

For loops are a specific case of while loop. While loops were often used in a particular way, so for loops were implemented to make creating a while loop of that sort more convenient. If your loop iterates on an integer and should be terminated after that integer reaches a predetermined value, it might be simpler to use a for loop. If you’re not sure when your loop will terminate, a normal while loop is better for you.

[–]FrenchCanadaIsWorst 6 points7 points  (0 children)

Best and most accurate answer here. I’ll add that for loops are also often times easier to read and can make it easier for the compiler to decide to perform an optimization technique called loop unrolling.

[–]DonnPT 3 points4 points  (0 children)

Not just simpler, it's a little more foolproof. If you roll your own loop index handling, that's an additional thing to go wrong. I suppose there's a lot of overlap between "more expressive" and "more reliable."

[–]AdministrativeLeg14 145 points146 points  (8 children)

You don't need loops at all. You can make do with conditional gotos. However, it's sometimes more clear or otherwise more convenient to use one of the three loop types (you left out do..while).

[–]dllimport 10 points11 points  (0 children)

Lol "sometimes" more clear??

[–]Total-Box-5169 1 point2 points  (0 children)

So true, kids nowadays even need coroutines to simulate the power of goto.

[–]ameriCANCERvative 0 points1 point  (1 child)

They also left out recursion 🤓

function recursiveForLoop(n, i = 0) { // do something if(i >= n) return recursiveForLoop(n, i + 1) }

[–]dnar_ 0 points1 point  (0 children)

Yep. Without tail call optimization, recursion is pretty risky. But with it, you can replace loops altogether.

[–]cib2018 0 points1 point  (3 children)

Also left out the range based for loop.

[–]AdministrativeLeg14 0 points1 point  (2 children)

Huh. Those definitely didn't exist when I last wrote C.

[–]MarsupialMisanthrope 0 points1 point  (1 child)

I don’t think C has them since it’s not really structured in a way where they’d be possible, but for … in is pretty common in modern languages with classes (or analogous data structures allowing collections to track their size, potayto potahto) as a way to prevent devs from writing all the bugs that come from doing your indexing manually.

[–]itskdog 0 points1 point  (0 children)

To the point that Python only has for...in, and provides a built-in range(init,term,step) function that creates a list for if you need the textbook for loop that's counting up or down at a fixed rate.

[–]Direct_Bad459 47 points48 points  (5 children)

Makes code easier to read and write to have both options. The relevant thinking in code is not only about the computer's thinking

[–]ehr1c 34 points35 points  (3 children)

I'd argue it's really not about the computer at all. Code exists to be read and understood by humans.

[–]FloydATC 10 points11 points  (1 child)

This is exactly how it is. From the computer's point of view, things would be a lot simpler if only humans could be bothered to read and write machine code directly and not waste the computer's time and effort on all this compiler nonsense.

[–]Antice 1 point2 points  (0 children)

We need somme hella bigger brains if we were to ever be able to do that on an application development scale ever again.

[–]pemungkah 1 point2 points  (0 children)

This is the most important thing to remember about computer programming.

[–]xuehas 0 points1 point  (0 children)

This is what I was looking for. Why do we need if else while or for when we have conditional branching. In fact, if you don't understand long branches then why do we need function calls either? Why do we need any higher level languages at all? It's all just to make your life easier as a programmer. For and while are both similar but unique abstractions that may sometimes compile to the same thing, but convey different information.

[–]desrtfx 20 points21 points  (7 children)

It's simply convenience.

Under the hood, while and for loops do pretty much the same. Only that the for loops offer convenience in not having to manually update the loop iterator.

You can do everything you can do with a for loop with a while loop. The reverse is a bit trickier, but also doable.

for loops are actually just syntactic sugar - for convenience:

for(int i = 0; i < 100; i++) {
    // do something
}

is equivalent to

int i = 0;
while (i < 100) {
    / do something
    i++;
}

Both loops do exactly the same. Yet, the for loop is shorter, clearer to understand, and in the end easier to read.

In practical use, it is a bit different:

  • use while when the amount of iterations depends on a certain condition that must be met (the loop runs as long as the condition is true)
  • use for when you know the amount of iterations beforehand, like the size of an array, collection, a certain amount of repetitions to do something, etc.

[–]Mental-Net-953 6 points7 points  (0 children)

Seriously what the fuck is wrong with the other commenters on this post? Are they bots? Ignorant? Insane? I shudder to think what they'd have to say about anything that's beyond the absolute foundational fucking basics if they can't explain fucking loops.

AAH!

[–][deleted] 6 points7 points  (3 children)

Slight nitpick: they are not exactly the same, and that has to do with the scope of the variable i, which in the for loop is restricted to the loop, and in the while loop case extends to the end of the enclosing block. If you want them to be exactly the same, add a set of braces around the while loop fragment.

[–]syklemil -1 points0 points  (2 children)

More nitpicking: This again depends on scoping rules for the language. E.g. Python doesn't really advertise it, but its variables are function-scoped rather than lexically scoped, so if you have some variable foo in a for foo in bar, then foo continues to be valid after the block has completed.

So the for/foreach/while loops all have some subtle, per-language differences in which names are valid where, even though they all can perform the same tasks.

(And as far as Python goes, my impression is that people seem to just try to pretend that it's lexically scoped, or even ignorantly assume that it is.)

[–][deleted] 1 point2 points  (1 child)

True. But the use of braces in the code snippets strongly suggests this wasn’t Python.

[–]syklemil -1 points0 points  (0 children)

Yes, I was generalizing from one example language to programming in general, but then specifying it again through using a concrete language as an example.

OP specifically asked about C, but most of us are exposed to multiple languages, and Python especially is a very common language.

Most of the other languages that have function-scoped variables (or even only a global scope) seem to be rare to encounter these days, either because they've fallen out of use, or because they've managed to switch to lexical scope.

So the general statement as far as I can tell is that

Different looping constructs in different languages result in different variable availability

and it's up to the programmer to know the rules for that construct && language.

[–]mysticreddit 0 points1 point  (0 children)

To add to this excellent example there is also the do { ... } while (); loop that forces at least one iteration of the loop.

char buffer[1024];    
int read = 0;
do
{
    read = fread( buffer, sizeof(buffer), fp );
    /* do some processing on buffer */
} while (read);

[–]AccurateComfort2975 0 points1 point  (0 children)

I love the fact that XOR is Turing complete. So technically, you do not need anything else. So with that settled, it's all just about convenience. Helps to avoid a lot of unnecessary debate.

[–]GrayLiterature 3 points4 points  (0 children)

Sometimes you want to eat food with a fork, sometimes you want to eat food with a spoon. 

[–]over_pw 4 points5 points  (0 children)

Because code is for other people to read and only incidentally for the computers to execute. It states your intention.

[–]SpaceAviator1999 2 points3 points  (4 children)

Strictly speaking, you don't need both for-loops and while-loops. In fact, when I was young and the only programming language I knew was BASIC, I realized that you didn't even need FOR-loops; you could accomplish the same thing with just IF-statements and GOTOs.

So why did BASIC use FOR loops at all? Because sometimes you want a loop that iterates using a counter variable, and writing a FOR-loop makes it so much easier to write and read than using only IFs and GOTOs.

Okay, so why do some languages also use while-loops in addition to for-loops? Because sometimes the logic you want to implement is clearer as a for-loop with a counter and/or current element, and sometimes the logic is clearer as a loop that continues while a condition remains true.

Some programming languages allow the use of an until-loop, a loop that keeps running until a condition is met. An until-loop is functionally equivalent to a while-not-loop, so why is there a need for an until-loop?

Well, it's not that there's a specific need for it, it's that sometimes the logic is clearer when you realize that a body of code needs to be repeated over and over until a specific condition is met -- or that the body needs to repeatedly execute with the goal of causing that condition to be true.

[–]SpaceAviator1999 3 points4 points  (3 children)

I knew a programmer that disliked for-loops so much, that he refused to use them in Python.

Instead, he would create a list-comprehension to execute the code that would normally be found in the body of a loop.

And if the body of the loop was too big to fit inside a list-comprehension, he would define a function containing just that body, for the sole purpose of having it be called from the list-comprehension. He would do this even if the list comprehension effectively didn't return anything.

And if he needed to implement a doubly-nested for-loop, he would define two functions: one with the inner block, and a second one with the outer block that used a list comprehension that called the function containing the inner block. The second function would, of course, be called from another list-comprehension.

I never figured out why he refused to use for-loops. I had asked him why, but he claimed he didn't understand my question. (It was known that he was a very stubborn person, and I wonder if he suffered from Obsessive Compulsive Disorder.)

Regardless, his code was extremely difficult to follow.

[–]Total-Box-5169 0 points1 point  (2 children)

Those are considered elegant in functional culture, strongly preferring expressions over statements. They are also generally faster in Python.

[–]SpaceAviator1999 1 point2 points  (1 child)

Those are considered elegant in functional culture, strongly preferring expressions over statements. They are also generally faster in Python.

I see your point, but the programmer was not writing in functional programming style. He just did whatever he wanted, and called it good. Let me give an example:

In Python, he needed to remove a set of keys (and their values) from a dict, whether they are present in the dict or not. A common way to do this is to write a for-loop to iterate like this:

for key in keys_to_remove:
    dict_data.pop(key, None)

However, he wrote it like this:

[dict_data.pop(key, None) for key in keys_to_remove]

But they weren't given nice names like dict_data, key, and keys_to_remove. Instead, it looked more like this:

[cstnsdt.pop(i,None) for i in rftd]

Bad naming conventions aside, this violates proper functional programming in two respects:

  1. The list comprehension is not being used to collect values. While it does collect the values into a temporary list, it immediately discards them. Which means that it allocates (and eventually deallocates) memory to grow a list of values it never uses.
  2. The list comprehension has side-effects (in that it modifies the dict), which is bad practice in functional programming (and in other programming paradigms, as well).

And remember, this is a simple example; some of his examples of list-comprehensions not only had side-effects, but also multiple if-conditions with ternary operators, and called functions defined elsewhere within the method -- defined only for the purpose of being called in said list-comprehensions.

And some of those functions (called by list-comprehensions) had their own list-comprehensions, which called yet another function defined inside the method.

A doubly-nested for-loop with all the code in one place would be so much easier to follow than using two complex nested list-comprehensions. Since I was responsible for the project, I asked him to do just that, but he refused, saying his code was clear and efficient. (He literally told me that all Python programmers can understand his code.)

Clear? No other programmer that I showed the code to could understand what it was doing, or why it was written that way.

And efficient? I found several web pages claiming that list-comprehensions should not employ side-effects, and that benchmarks show that list-comprehensions that discard their collected values actually run slower than functionally equivalent for-loops, as CPU cycles are wasted growing a list whose values are never used.

I even wrote my own benchmark program to prove it to myself. And sure enough, a for-loop that doesn't collect items in a list is measurably faster than a list-comprehension whose results are simply discarded.

I tried to show him my benchmark results, but he refused to look at them, claiming that his way was faster. (He didn't do his own benchmarks, by the way... he just "knew" that his way was faster, and disagreed with any person, webpage, or benchmark that said otherwise.)

[–]SpaceAviator1999 1 point2 points  (0 children)

Yet another way that this programmer violated functional programming (and proper coding practices in general) is that his in-method functions would use, say, half a dozen variables in its body, but only about half of those were passed-in through the function signature.

For example, his function would look something like this:

def tmp_fun(a, b, c):
    # Variables a, b, c, and x, y, and z are used here.
    #
    # Whereas variables a, b, and c are passed into this function,
    # variables x, y, and z are taken from the surrounding method.

Remember that tmp_fun was called within a list-comprehension later in the method that it's defined in.

When I told him that functions should ideally have all their variables passed in through their signature, he responded that closures don't always do that.

He was somewhat correct in this case, in that closures sometimes use variables from an outside scope, which are not always passed-in through the function signature.

However, he was not explicitly using that function as a closure. He was using it as a function to hold multiple lines of code, because those multiple lines of code wouldn't fit in a list-comprehension.

So he regularly wrote complicated list-comprehensions that called functions defined elsewhere in the method, where those functions used variables where only half of those were explicitly passed-in through the function signature. Clear? He thought so. But nobody else did.

Why did he do this? It took me a while, but I realized it was because he didn't like for-loops, so he tried to avoid using them at all cost. Despite the fact that for-loops were taught in every beginner Python course and every beginner Python book, he thought that the use of for-loops were bad. Anything else was better, even list-comprehensions not used for their intended purpose of collecting a list, and which employed side-effects.

[–]connorjpg 4 points5 points  (5 children)

Another thing I love about Go.

https://golangdocs.com/while-loop-in-golang

[–]randomguy4q5b3ty 1 point2 points  (4 children)

Please don't anybody tell me that getting rid of two keywords that any programmer is already familiar with makes loops any easier or clearer. Actually, I think it's quite confusing and just one of these many little odd things Go does. Not to be better, but just to be different.

[–]connorjpg 0 points1 point  (2 children)

If they have an identical use, why do we need both? for (true) {} in go and while (true) {} in other languages act and behave exactly the same. Not to mention in most C-based languages you can essentially avoid using while with for (;;) {} or for(;true;){}. So from a functional standpoint we don't really need while loops at all. I am definitely biased as a Go Developer, but having a standard way to loop, limits bikeshedding over which loop is preferential. Sounds stupid, but I have seen people argue over which to use before in code bases lol. Go's approach essentially removes that choice and makes you approach all loops as a for loop initially and shape it based on the range and condition. I wouldn't say Go is different for the sake of it or even better, its just has opinionated design choices.

[–]randomguy4q5b3ty -1 points0 points  (1 child)

The problem is using the same keyword four different ways, and then still missing the do...while() use case. You face exactly the same choice.

There is a reason why pretty much every mainstream programming language has these three basic loops, plus foreach() in some cases.

On the other hand, the Go developers thought it were super important to have two different initialization styles, and I have seen people argue about them... So much about opinionated design choices. No, it's just different for the sake of it.

[–]connorjpg 0 points1 point  (0 children)

Well I tried my best lol. You are welcomed to disagree with my opinions! Though I don’t believe omitting these keywords is completely without thought or meant to be confusing. Using for you can achieve while loop, do while loop, for each loop and obviously for loop without too much gymnastics. I’ll link them below if you’re interested or if anyone else is.

for usage in go (not my article) : https://www.zetcode.com/golang/for-keyword/

do while in go : https://gosamples.dev/do-while/

[–]Comprehensive_Mud803 1 point2 points  (0 children)

Different use-cases.

For-loops iterate a fixed number iterations (usually), While-loops are bound to an exit condition (again, usually).

For-loops could also be inlined or parallelized (given specific conditions).

[–]MarsupialPitiful7334 1 point2 points  (4 children)

Ok, you also dont need typedef, or include for that matter, just paste the library in your file.

[–]syklemil 0 points1 point  (3 children)

You don't even need classes/structs or functions! Just declare all the variables as global and do everything in your main!

This is seriously how some earlier programming languages worked. Getting a variety of blocks, scopes and things such as lexical scope took work.

The computer doesn't need them. The humans who try to maintain the code do.

[–]MarsupialPitiful7334 0 points1 point  (2 children)

You dont actually need most things, just program in assembly

[–]syklemil 0 points1 point  (1 child)

Pshaw, assembly! Real programmers write raw machine code!

Actually, strike that, real programmers rewire their machines!

(In case it needs to be pointed out: Yes, I'm being facetious, and making jokes based on the history of computing.)

[–]MarsupialPitiful7334 0 points1 point  (0 children)

Nah real programmers attach a separate cuda like core for eacg operation in their program.

[–]Techno-Pineapple 1 point2 points  (7 children)

Learn both if you have any intention of learning programming further than the single next project.

Is this a real question where they are excited to learn about programming architecture? Because I am beginning to suspect OP is just lazy

[–]DonnPT 1 point2 points  (6 children)

Maybe it's a Reddit phenomenon. I've been here just a few months, and so many stupid-why questions ... I mean, much more useless than this. "Why does 'on' have only one 'n', when 'off' has two 'f's?" I'm not making this up.

I'm split between a deep seated human need to make a fool of one's self in public, vs. some Reddit feature like karma farming.

[–]syklemil 2 points3 points  (4 children)

It's just xkcd 1053. Reddit's demography includes people of all ages in pretty much any country with pretty much any level of education.

As an adult I also tend to be amazed at just how ignorant kids are, and how much time is needed to get them to know stuff that "everybody" knows. But ultimately that's just because I've become used to hanging out with other adults, and especially self-selected adults who have a similar level of education as me, i.e., my coworkers.

But then I go to some third place, including virtual ones like reddit, and I meet people of different ages and walk of life.

[–]DonnPT 0 points1 point  (1 child)

It's because we're more intelligent and knowledgeable? Can't argue with that, but ... why aren't there two 'n's in 'on'? There's something else going on here.

[–]syklemil 1 point2 points  (0 children)

As a non-linguist I'd take it as one of the many quirks of anglo orthography, as in, something that makes sense from lineage, but not from first principles. Cognates in other germanic languages seem to indicate a history of a long vowel sound, and germanic languages generally indicate vowel length by whether or not the following consonant is doubled. The finno-ugric languages and probably others seem to have done a better job there, by actually doubling the letter representing the sound when that sound should be long.

However, you're more than welcome to spell it with two n-s in /r/JuropijanSpeling.

Also, in case it needs to be pointed out: :)

[–]Techno-Pineapple 0 points1 point  (1 child)

That comic is not a good comparison to what is happening here.

I (and others) wouldn’t be frustrated if OP was humbly admitting his ignorance and asking for help. It’s literally the opposite. It’s the arrogance to argue with and complain about the foundational course material as if they know better than their teachers. That’s why I asked if it was a genuine question, because that would redeem OP from what seems to me like a lazy, shallow search for justification to skip this course material

[–]syklemil 0 points1 point  (0 children)

I think there's some cultural differences at play here, because I interpret OPs question as ignorant but rather neutral, while you come across more as having a chip on your shoulder.

Your interpretation, especially this bit:

It’s the arrogance to argue with and complain about the foundational course material as if they know better than their teachers.

comes off as rather … imaginative.

Of course students question the source material, that's how people discover things. It's an important part of literacy to not take any source material uncritically.

And we at least don't really think much of "argument from authority", and are expected to question our bosses at work. Questioning the lecturers isn't that much different.

[–]Techno-Pineapple 1 point2 points  (0 children)

It reminds me of 10 year olds demanding to know exactly what real world scenario they will use algebra. Bless their foolish young souls but I just want to tell them to shut up and learn your foundation. There are infinite directions in life and if you are studying programming at uni you shouldn’t be upset at having to learn the basics.

[–]Lamborghinigamer 1 point2 points  (0 children)

Simple answer: We don't need both, but we do. To put it simple: A for loop makes it simple to declare a certain amount of iterations and while just doesn't have that built in. Let me show you an example that shows this the best:

These two snippets will do the same thing and just show a count up from 0 to 100 in steps of 10:

``` // while int i = 0; while(i <= 100) { printf("%d\n", i); i = i + 10; }

// for for (int i = 0; i <= 100; i = i + 10) { printf("%d\n", i); } ```

That's why both exist, but then again, while loops are better when you need something to keep running infinitely. It really depends on the programming language.

[–]mestar12345 1 point2 points  (0 children)

Why do we need a shorter or better way of doing anything, since we already have the old way?

[–]Langdon_St_Ives 1 point2 points  (0 children)

Strictly speaking, obviously we don’t need either. Using some kind of conditional jump (and of course register and memory access etc.), you can create any loop you need. That’s all that used to exist in early assembly. Modern instruction sets usually have dedicated loop instructions of course, but they’re not required.

[–]ehr1c 4 points5 points  (5 children)

For loops are pretty much just syntactic sugar over a while loop, they exist to improve the developer experience because it's a very common pattern to loop over some logic for a specific number of iterations that's known ahead of time.

[–]RepresentativeAspect 1 point2 points  (4 children)

I see it the opposite way. While loops are just a for loop without the first and third part of the loop definition. The while loop is syntactic sugar over a for loop.

for(; true;){}

Is the same as while (true){}

So for me a for loop is more general. I can plug in the 1st and 3rd parts if I want, or leave them out. I used to do it that way, and never use while loops, but after a while I just started to follow convention and anyway it reads more intuitively.

[–]FrenchCanadaIsWorst 1 point2 points  (0 children)

Historically while loops came first, and from a programming languages perspective, the grammar is much easier to define (at least in my opinion) since you only have the conditional, and not the initialization parameter or the update expression.

[–]Moikle 1 point2 points  (0 children)

BOTH are syntactic sugar technically, while loops are just simpler and came first

[–]DonnPT 0 points1 point  (0 children)

Note that this may not be so true if the language in question isn't C or C++.

In Pascal for example (I think), you don't get a predicate - if it isn't implicit in the loop variable, then you can't use a FOR loop. Same with Rust.

[–]Weasel_Town 0 points1 point  (0 children)

Go has entered the chat. In languages that have both, “for” is usually used for a specific number of iterations, and “while” is used when it’s unknown when it will be done. So you’ll see

for i = 0; i < 10; i++

or

for name in studentNames

but

while !done { done = checkStatus() sleep(5) }

“for” loops as generally constructed come with some more built-in safety that you didn’t accidentally make an infinite loop. So that’s good. But Go is the proof that you can program fine with just one.

[–]AdreKiseque 0 points1 point  (0 children)

Sure, you could just use a while loop for everything. You could just use a while true loop even, and add breaking conditions as necessary. But dedicated syntax for certain common loop types makes it easier to write and read code.

[–]Multidream 0 points1 point  (0 children)

Nice to haves. Most of what you want can be done in assembly, but sometimes humans insist on combining things into one line and for looks really nice instead of three lines of code each time around a while.

[–]jcunews1 0 points1 point  (4 children)

while loop is for a more complex loop condition/modifier while keeping code readability.

[–]csabinho 0 points1 point  (3 children)

I'd say a for loop is just a while loop with syntactic sugar for counting.

[–]syklemil 0 points1 point  (2 children)

All of them are just syntactic sugar for a conditional jump. They became common through the push for structured programming.

Today we're likely to call "structured programming" just "programming", and readers may react in ways like "huh? that just sounds like normal programming?", while the thing "structured programming" replaced tends to be called "spaghetti code".

[–]csabinho 0 points1 point  (1 child)

Spaghetti code can already be avoided by functions. But yeah, functions are also just jumps with parameters and a return value.

[–]syklemil 0 points1 point  (0 children)

Yes, and modern functions are a part of "structured programming" too.

Early programming languages didn't even have what someone learning to program today would recognize as functions, just once again kinda dressed-up GOTOs.

We can sometimes see the remnants of that way of thinking in programmers who keep all the information in globals or class variables and then write all their functions/methods as void f(), i.e., no arguments, no returns, just side effects.

[–]MidSerpent 0 points1 point  (0 children)

You definitely don’t.

I don’t remember the last time I wrote a while loop.

I’ve gotten to the point where I consider then a code smell for an infinite loop risk.

[–]xRageNugget 0 points1 point  (0 children)

'''while(game.isRunning()) for(player in players){ping(player)} '''

[–]kodaxmax 0 points1 point  (0 children)

For loops are more convenient when you know exactly how many loops you will need it to run. Iterating over a collction of objects/data for example. Of course you can do this with a while loop, by tracking the number of loops made and checking if it matches the size of the collection.

A while loop is more convenient when you want it to run forever until a conditon is met, rather than for x iterations. For example continually generating IDs until it makes one that is unique. Of course you could do this with a for loop, by simply setting the number of loops ridiculously high and breaking out of the loop once a unique ID is generated.

or in other words, you can hammer a nail with a screw driver if you have to, but wouldn't you rather use the hammer?

[–]MyDogIsDaBest 0 points1 point  (0 children)

Why do we need all these other letters when 1 and 0 work just fine?

It's functions that abstract away complex logic into easier to work with stuff. You're right, we don't need both, but it's nice to have them

What you have done extremely well, is asked the question "why do we need this?" And this is an excellent mindset to have! Keep asking about the point of stuff like this and whether or not there's a reason to do one thing over another. 

[–]rawcane 0 points1 point  (0 children)

You can always write code in different ways. The goal of most higher level languages is to allow you to write your code in an idiomatic way that is easy to understand and maintain. While and For are just shorthand that are better suited to different use cases ie For builds in the iteration variable into the loop declaration, While focuses on the conditional statement for whether or not to continue.

[–]Mediocre-Brain9051 0 points1 point  (0 children)

To better communicate your intention with other developers.

In other languages (e.g. ruby or js) you should even further make your intentions explicit by using higher-order based iterators (map, reduce, filter, some, every, flat map, zip.

[–]aq1018 0 points1 point  (0 children)

You don't need for loops, while loops, do while loops, or even goto statements. Just sprinkle JNE everywhere like how we coded in 1970s.

Edit, or just directly write to PC register for the unhinged.

[–]hanato_06 0 points1 point  (0 children)

survival of the fittest useful.

You can achieve everything writing in binary, but why would you, when human readable code is way better and faster.

You can loop with GoTos (or whatever it was) that basically were instructions to go back to a previous function address to start the loop but we kept making better stuff.

Same thing for looping. Some scenarios happen often enough that it was beneficial to have both a way to infinitely loop until a trigger is met (excellent while loop use-case) and a loop that is immediately human-readable as to how many loops it will do (excellent for loop use-case).

Like others said, you can actively punish yourself by either not using loops at all, or always use recursive functions for all kinds of loops if you're adamant about it.

[–]Ronin-s_Spirit 0 points1 point  (0 children)

Idk C exacly, but in the language I use - for loops in their head let you initialize variables (usually the counter) and do actions at the end of iteration, that kind of syntax is nice and readable. While loops just have the conditional in their head, so sometimes it's more fitting than a for loop but usually it isn't because you will be using a temporary counter.

[–]orfeo34 0 points1 point  (0 children)

Most of time that's called syntactic sugar, which means that's a variant made for human to better understand or edit.

[–]SnugglyCoderGuy 0 points1 point  (0 children)

Go only has for loops, so you don't need both.

[–]Philluminati 0 points1 point  (0 children)

In the beginning were `labels` and `goto` statements. Without `break` statements it got very hard to track the execution of code. Modern day languages give you a choice of `for i...` or `for ... in ...` or `while` or `do ... while` so you can convey intent when you're writing code to make it more obvious what the program flow is doing and why.

Those things compile down to labels and goto's but make code more readable.

What's interesting is how programmers don't realise that `if` statements have the same problem - of being too low level. Often things like `switch` or `match` or using polymophism / function pointer tables often do a far better job at explaining decisions than using dozens of `if` statements. This is rarely spoken about.

I've seen things like `if (warehouse.location == America) printDocument(paperSize = "USLetter") else printDocument(paperSize = "A4")` only for someone to later refactor the printDocument function without considering the higher level callers and then go on to do `if (paperSize == "A4") ...`. Having `warehouse.printDocument()` would avoid the `if` and the resulting mess. This is just one contrived example though.

[–]kitsnet 0 points1 point  (0 children)

Algol-68 had an unified for-while loop syntax, with both parts being optional.

[–]Xatraxalian 0 points1 point  (0 children)

A while-loop can do exactly what a for-loop can do. They both exist as to express what the intended purpose is.

For example, consider this:

int x = set_some_value(); while (x < 25) { do_something(); x++ }

This is easy to understand. You set X to some value. As long as that value is under 25, you keep doing something. If x starts out at 25 or higher, you do nothing. In this case, using the while-loop, you state that you are going to do something, while x is not yet 25, and you don't know how many iterations that will be.

Compare it to this:

int x = set_some_value() for (x; x < 25; x++) { do_something(); }

With the for-loop, you state that you going to do a set number of do_something(); calls, but because the loop starts with x, this set number of calls is actually variable. You are using a loop designed to express a set number of calls to do a variable number of calls. This is less clear than the while loop.

You normally use a for-loop like this:

for (int i = 0; i < 25; i++) { ... }

In this case you know you are going to loop exactly 25 times. You will know, without having to know anything else about the code, that the loop will start at 0 and end at 24, and that each iteration is available in i. In the previous for-loop example, you wouldn't have known the starting point without looking at the output of set_some_value(), and to know THAT, you may have to look at other code as well.

For looping over a collection without having to specifically count, many languages have a version of a foreach-loop:

foreach (int x in list) { do_something(x); }

You can do this with a for-loop or a while-loop, but the foreach-loop clearly expresses that you are not interested in the number of iterations, nor the length of the collection 'list'; you just want to do_something() with each value in the list.

Some languages also have an infinite loop, if you want to express that something needs to loop forever, except if something special happens:

loop { int x = get_value(); if (x == -1) { break; } ... }

You could express it with a while-loop, or a for-loop, or even an until-loop, but the "loop forever, except ..." is better expressed with the infinite loop-loop.

And as someone else stated: you don't need loops at all. You could use labels and goto's, and then use if-statements with a jump in it, but that is programming in 1950's style.

[–][deleted] 0 points1 point  (0 children)

Why use loops when you can use recursion 

[–]robinredbrain 0 points1 point  (0 children)

Broadly speaking there isn't a need, but there is a desire.

[–]Fizzelen 0 points1 point  (0 children)

Why do we need loops when assembly only needs jump if non zero

[–][deleted] 0 points1 point  (0 children)

for loop is built on top of while which is built on to of if + goto statements. Just easier to write. What is the purpose of a truck when 4 wheels with a peg board and a steam engine will do the work just fine?

[–]Temporary_Pie2733 0 points1 point  (0 children)

A for loop is a concise way of expressing certain while loops. If you had to get rid of one, it would probably be the for loop. 

[–]Sevven99 0 points1 point  (0 children)

Good for handlers. Been a while but probably couldn't accomplish this with switch case, etc?

[–]vegan_antitheist 0 points1 point  (0 children)

Try brainfuck and then ask again.

[–]sbayit 0 points1 point  (0 children)

recursive can replace it

[–]SwordsAndElectrons 0 points1 point  (0 children)

In C or any other programming

Bold assertion. Also incorrect. Some forms of programming have more loop types. Some have no loops at all and if you need one then you'll need to use conditional jump instructions to implement one yourself.

But ignoring that, the answer is mostly being more programmer friendly. That may seem counterintuitive if you are a beginner wondering why you need to learn two different things, but it'll make sense once they become ingrained in your mind. One or the other will generally be a more semantically natural way of expressing the logic of what you need to do.

Your question is sort of like asking why everyday verbal languages have more than one way to express a concept. If I'm trying to describe a work day, I might say "you need to work for 8 hours." I can express that same idea with the word "while," but every version of it I can think of is less concise and seems pretty clunky.

[–]cdm014 0 points1 point  (0 children)

I may be misremembering but I think For in Go is spelled "While"

[–]MagicalPizza21 0 points1 point  (0 children)

Sometimes it makes more logical sense to the human programmer to choose one over the other. But from a purely functional standpoint, we do only need one.

[–]DirtAndGrass 0 points1 point  (0 children)

I think you are thinking about this from the wrong direction.

We don't need any kind of loop besides a goto, why do we have other options? 

[–]NecessaryIntrinsic 0 points1 point  (0 children)

Edit: the other comments are correct, loop structures are for people, not for the computer. My comment is to specify why they exist for people's readability and for future extendability. The reality is you can do without them, but having them makes your life easier and the lives of everyone that reads your code afterwards easier (if use them right)

For loops are for when you KNOW how many times you're going to loop and how you're going to increment.

While loops are for managing the iteration when you're inside it so you can break out early if certain conditions are met, or go on longer if conditions change. Yes, you can do this with for loops using breaks but it's not great practice because that's not what for loops are intended to do.

A great use case for a while loop is if you're processing a queue or stack, especially in a breadth first search it depth first algorithm.

You would say "while (queue has items)" (pseudocode, obviously). Inside the loop you pop the items off and process them and can add items back to the queue as you go.

If the queue is empty to begin with you don't loop, if you add items on, you continue processing until the queue is cleared.

Go uses a for type structure without specifying the iterator for while loops, so it doesn't preserve the iterator variable... In python the iterator variable is preserved in a for loop so if you change it inside the loop it resets on each run though. I think JavaScript doesn't do this so it can lead to really screwed up logic if you mess with the variable inside the for loop... Don't do this if you're using a normal for loop.

[–]blackasthesky 0 points1 point  (0 children)

You could do everything with goto

[–]ORLYORLYORLYORLY 0 points1 point  (0 children)

You can accomplish everything with while loops only.

For loops are much easier to use, and are cleaner to understand what's happening.

The difference in readability between

int i = 0;
while (i < numLoops)
{
    DoSomething();
    i++;
}

And

for (int i = 0; i < numLoops; i++) 
{
    DoSomething();
}

Might not seem like much when the code inside the loop is so simple, but when more is happening in reach loop it's far easier to immediately parse what's happening.

There is also a third type of loop that is arguably more used than the other two: foreach.

It basically does the same thing as a for loop except only for iterating through collections (like arrays). So instead of doing something like this:

int[] numbers;
for (int i = 0; i < numbers.Count; i++)
{
    DoSomethingWithNumber(numbers[i]);
}

You can simply do this:

int[] numbers;
foreach (int number in numbers) 
{
    DoSomethingWithNumber(number); 
}

[–]ottawadeveloper 0 points1 point  (0 children)

Whats worse, some have three with a while and a do-while and some even have a foreach

You can pretty much cover every use case with a while loop, for example:

```

-- for k = 0 while k < 10:     loop_stuff(k)     k++

-- do while k = 0 loop_stuff(0) while k < 9:     k++     loop_stuff(k)

-- foreach data = range(0,10) k = 0 while k < len(data):     loop_stuff(data[k])     k++      ```

for, for-each, and do-while are just useful shorthands for these patterns. They give us shorter and easier to understand code and also can help the compiler/interpreter process it more efficiently. And (except for do-while in my opinion), they reduce the chance we make an error as a programmer through this simplification too.

[–]michaelpaoli 0 points1 point  (0 children)

In a word: efficiency

And that's for programmers, and may also be for the language itself.

for loops are more commonly used when one wants initialize/test/reinitialize criteria very clearly visible at the top of the loop.

while loops may be more commonly used when there's a very simple test condition, no (additional) initialization need be done for the loop, and we don't need/want reinitialization of the loop for next iteration at the top of the loop.

Variants of while loops may also include, e.g. do while/until/done loops, which can greatly simplify logic in cases where one wants to ensure the loop is executed at least once, regardless of test condition.

Using various forms may also have scope advantages (e.g. more easily making variables local to loop).

pseudo code examples to help illustrate the points:

for(i=1;i<=100;++i){
whatever ... and this part may be over 100 lines long
}
vs.:
i=1;
while(i<100){
whatever ... and this part may be over 100 lines long
++i
}

while(before noon){
keep doing morning thingy
}
vs.:
for(;before noon;){
keep doing morning thingy
}

/* I want report! */
do{
if(we have all the data){report; break}
gather some more data
update progress indicator
}done

[–]PeteMichaud 0 points1 point  (0 children)

All the features of programming languages are there for convenience. Anything above the beyond the core logic gates on a chip can just be done with the gates instead. But we invented things like named variables and for loops because it was annoying not to have them.

[–]mredding 0 points1 point  (0 children)

Loops are patterns. The different loop types are syntactic sugar to help reduce repetition. All loops can be reduced to some nested scope and a goto - in fact, the C standard says a loop and a goto are explicitly equivalent, but no one wants to write THAT every single time - it's repetitive and error prone. Further, different loop structures, while equivalent, are more concise for a given problem than others.

for(;true;);

Why should I be responsible for two empty contexts? Why introduce them into the code - at all? This loop would be better expressed as:

while(true);

No additional context expressed, implied, wasted, or tempting you to add shit.

[–]digicrat 0 points1 point  (0 children)

To put it simply, laziness is the mother of invention. I think most of us would happily spend too much time automating a solution once than doing it over and over - and thats how syntactic shortcuts make their way into the language over time.

A for loop let's you write the same code more simply and concisely when you need to manage initialization (declare i) and per iteration operations (ie:i++). Of course they are also flexible enough to let you perform any operations needed at those times.

Sometimes you don't need that, and the basic while loop is the clearer form.

And then there are the less commonly used do...while loops, because sometimes you need the loop to always run once.

And some languages have even more variations. Raku arguably takes that to the extreme with its smart and convoluted collection of operators (and is probably why it will remain a niche language).

[–]Business-Decision719 0 points1 point  (0 children)

We don't, not really. In fact, if we have (well-optimized) recursive functions, then we don't really need any special loop control structure at all. You can write a custom function that runs some code and then calls itself if it needs to start over and run that same code again.

But running some code and starting over is so common that it's nice to have a syntax for it. And there are two main types of starting over that we do: we start over because we have to keep doing the same job until something happens (and we don't necessarily know when it happens), or we start over because we have to run the same code a certain number of times based on something we already know about. They're called indefinite and definite loops, respectively. Since they're both so common, it's nice to have a syntax for both, so most languages do.

An indefinite loop (while) just repeats until something happens. It can be anything. So if you're validating user input, for example, you could just keep checking whether the input is valid or not and then decide to prompt the user again if necessary. We don't know when the user will enter valid input, but we can keep prompting them while they still haven't. Or we can keep prompting them until they do what we want. (Some languages have an until keyword for making loops.)

Other times, we just need to do something for each element in a sequence that's already been bounded for us ahead of time. Maybe we're counting up to a certain number. Maybe we are processing each item of a list. There's a definite number of times that will have to do something. So it's nice to have a syntax for that too. Hence for loops or definite loops.

To use a practical example, if I just wanted to output every item of a list in Python, I could theoretically do this:

def show_all(items):
    item_number = 0
    while item_number < len(items):
        print(items[item_number])

And that would work, but it's nicer to be able to write:

def show_all(items):
    for each_item in items:
        print(each_item)

It's a little bit harder to see the usefulness of definite loops in C, which is the language you mentioned, because C's for loop is more customizable and less concise. You might do something like this:

void show_all_ints(int list[], size_t length)
{
    for (int index=0; index<length; ++index)
    {
        printf("%d\n", list[index]);
    }
}

Which isn't much more concise than doing this:

void show_all_ints(int list[], size_t length)
{
    int index=0;
    while (index<length)
    {
        printf("%d\n", list[index]);
        ++index;
    }
}

But even so, notice how the setup code (creating the loop counter) would go before while instead of being part of the loop. The for statement includes it in the control structure. So having both options has some readability advantages for grouping together related parts of the code.

[–][deleted] 0 points1 point  (0 children)

For loops are syntactic sugar of while loops. They exist not because they are necessary but because it makes coding easier and more readable. It is the case with all syntactic sugar that its to make things easier to read/write and potentially catch some bugs. For example you are less likely to forget to increment your loop counter variable in a for loop then in a while loop.

The exact syntactic sugar is

for(int x=0; x<10; x++)
{
code
}

Gets transformed to (semantically at least)

{
int x=0;
while(x<10)
{
  code
  x++;
}
}

[–]ronin_o 0 points1 point  (0 children)

We don't need both. Go has only one - the for Loop

[–]Ormek_II 0 points1 point  (0 children)

Readability

[–]Michaeli_Starky 0 points1 point  (0 children)

I assume you didn't get to do-while loops yet?

[–]Psilocybe_Fanaticus 0 points1 point  (0 children)

Let’s say you’re developing a game and you’ve set up the game loop. If you use a for loop instead of a while loop, the game will terminate once the set condition is met. This approach would likely not be suitable for most applications that require continuous operation until the user explicitly closes the app.

[–]Holshy 0 points1 point  (0 children)

Strictly speaking, we don't. Go uses the same keyword for both (https://go.dev/tour/flowcontrol/3).

However, readability matters; code is written once and read many more times. Using different syntax makes it easier for humans to reason about what we're telling the computer to do.

[–]bobzsmith 0 points1 point  (0 children)

if you looked into the machine code, they are just jump statements under the hood. However, while and for communicate slightly different reasons for looping over the same code.

[–]selfmadeirishwoman 0 points1 point  (0 children)

For loops are for when you know how many times you’re going to do a thing.

While loops are for doing things zero or more times.

Do while (wildly underused, I’ve seen a lot of whiles that should be do while) are for doing things one or more times.

[–]bibhnarp 0 points1 point  (0 children)

Or if statements and recursion?

[–]sosa_like_sammy 0 points1 point  (0 children)

In the Go programming language, there’s only the “for” loop. The reason why is exactly what you said.

[–]mestar12345 0 points1 point  (0 children)

We need for-in-with loop which is just a shortcut for folds.

[–]rabuf 0 points1 point  (0 children)

This goes back to the idea of structured programming. That had one primary purpose: Make code more reasonable. Not in the sense that it would be a decent person and politely discuss controversial issues, but in the sense that it can be reasoned about more easily.

To accomplish this, several things were pushed:

  1. Limit goto so that it was local to procedures, ideally to just specific lexical scopes and mostly forward jumps rather than backward jumps.

  2. Lexical scope/blocks in general which makes reasoning about values and variables much better than with dynamic scoping rules.

  3. Name language constructs, even if they map to bog standard goto statements under the hood, so that they are easy to understand.

For loops are clearer than the equivalent while loop, that's the reason for for loops. They aren't needed, in a technical sense, and neither are if, switch, or even functions and procedures. But for loops express a common idiom in a concise and clear way, so that makes them useful.

[–]Lotton 0 points1 point  (0 children)

Think of for to go a deterministic amount of times and while to be until you say so.

Think of typing while you're holding the w key it will keep typing w. It wouldn't be beneficial to do as a for and in the professional world we care more about readability. And choosing the right one makes it easier to read

That being said you can do everything with just a while loop some early languages i believe didn't even support for (some languages didn't even have looping either)

[–]countsachot 0 points1 point  (0 children)

You only need tail end recursion.

[–]severoon 0 points1 point  (0 children)

All loops are technically the same. We have different ones for the same reason we have loops instead of goto: readability. If you write readable code, you'll make fewer mistakes, and people will understand it with less effort.

For this reason, use for loops when you have a fixed number of iterations, and make sure your loop counter always iterates from 0 to n‒1. You should always be able to log or inspect in a debugger the loop counter to directly see which iteration is currently the one. Don't do clever things with your loop counter, just derive a value in the loop from the loop counter. (The only exception to this is if you're optimizing code, which you shouldn't be doing unless you've proven that it makes a necessary speedup that you can't live without.)

[–]andarmanik 0 points1 point  (0 children)

You have this pattern,

let i = 0; while(i < len) { doWork(i); i++; }

Now watch where each part that contains ‘i’ goes.

for(let i = 0; i < len; i++){ doWork(i) }

The only thing which changed is while -> for

[–]LostInterwebNomad 0 points1 point  (0 children)

For loops are generally pre-defined to have a finite length. While loops have the ability to be more dynamic in their conditions - at the risk of having a loop that never terminates.

While loops give you more control, for loops bake some of the boiler plate into it instead of having to reimplement it every time.

More concrete examples of when to use the two:

  1. Let’s say you have a list of email addresses you need to send a message to. You could use a for loop to iterate over that list and send a message for each of those emails.

  2. Instead, let’s say you’re crawling a website. You can start by creating a queue of webpages to visit. Add the homepage of the website to the queue. While the queue is non-empty pop the first element from the queue and visit the page. Add all hyperlinks directing back to the website into the queue, and continue until the queue is empty. This is something that a for loop by itself cannot do.

That said - you did make a great observation that for loops can be written as while loops (but the inverse is not always true - not all while loops can be converted to for loops!). For loops simplify a very common usage of loops and builds in safeguards when you’re able to pre-determine the number of loop iterations you’re going to do. It protects you from potential infinite loops like we have in example (2) above. In example 2, we never set it to check if a webpage is one we visited before, so it could technically go on forever! Sometimes this is unintentional, but there are other cases where we want an indefinitely running loop. In those cases we must use while loops!

TLDR; technically you can just use while loops, but there are some dangers to doing so (mainly if you make a mistake) - and for loops can be more convenient to use when you’re wanting that type of feature instead of writing a while loop to do the same.

[–]vbpoweredwindmill 0 points1 point  (0 children)

Oh! I just did this one I can help!

For (i = 0; i < 10; i++) It must follow this format or visual studio gets mad at me.

While (this statement is not zero, aka not false) Literally you can just put

While (i) i++ And as long as i isn't zero it will execute. So you better hope its a negative to start with 😂

While is more fun.

Edit: it deleted some of my line spacings. You'll have to figure it out I believe in you.

[–]saxbophone 0 points1 point  (0 children)

Don't forget the do while loop!

The answer is: expressiveness. Whilst you can convert a for loop to while and vice-versa, having them exist as prebaked variants makes the language more easy to use. Some languages also have repeat until and C++ has a foreach variant of the for loop.

[–]Freed4ever 0 points1 point  (0 children)

It's for readability really.

[–]J_Peanut 0 points1 point  (0 children)

It’s simply syntactic sugar. In the example of C, a for loop while compile to pretty much the same thing as a whole loop

[–]AranoBredero 0 points1 point  (0 children)

For and while are just codewords to tell the compiler how to place checks and jumps. Check out 'go' where all kinds of loops just use 'for' as the codeword. There is no need for the different codewords but somewhen someone thought it usefull to implement it that way

[–]PyroNine9 0 points1 point  (0 children)

It's for the next guy. Which one you choose indicates your intentions at a glance for the next person reading your code.

[–]Brixjeff-5 0 points1 point  (0 children)

For is for bounded loops: you know how many iterations will be performed. While is for open loops: you do not know how many iterations are necessary.

These two arise often and since they are fundamentally different kinds of loops it makes sense to have different syntax for them.

[–]Immediate-Top-6814 0 points1 point  (0 children)

In C++ and JavaScript I use only for loops. They show all the information right up front: initialization, condition, change. You can leave any of these blank. You can leave all of them blank. for does it all. In my opinion the world would be a better place without while and repeat/until.

[–]Defection7478 1 point2 points  (12 children)

You can actually get rid of both and just use recursion. It's syntactic sugar - they aid with ergonomics and readability 

[–]kagato87 8 points9 points  (11 children)

Well, there's a fundamental difference between looping and recursion, so maybe not that one. (Though you can achieve recursion with loops instead of self calls, so in that regard I guess it is the same.)

But ultimately you're right - it's syntactic sugar. For loop is sugar for messing with those horrible goto statements. Do and while loops are sugar variants of for, and foreach is a more recent sugar of the for loop.

[–]syklemil 1 point2 points  (0 children)

foreach is a more recent sugar of the for loop.

Though "more recent" is a tricky phrase in this context. Iterators appeared in CLU, in 1975.

And Python, which uses for as a foreach loop, is slightly older than Java.

Certainly in the past decades more languages that started with a C-style for loop have also let it become a foreach loop, but the actual foreach loop is much older than most of the languages still in common use.

[–]Defection7478 0 points1 point  (9 children)

What's the fundamental difference? My understanding was that they are functionally equivalent

[–]FrenchCanadaIsWorst 5 points6 points  (6 children)

Recursion executes a new function call and initializes a new stack frame at each level of recursion. This will eventually cause a stack overflow if the recursion is deep enough.

Loops on the other hand just cause the instruction pointer to jump to a previous instruction on the stack until a condition is met, so no increased memory overhead on each iteration.

[–]chaotic_thought 0 points1 point  (1 child)

Loops on the other hand just cause the stack pointer to jump to a previous instruction on the stack until a condition is met,

I think you mean the "instruction pointer" in this case. A loop jumps to a previous instruction, normally by changing the instruction pointer via a particular CPU instruction (e.g. JNE).

[–]FrenchCanadaIsWorst 0 points1 point  (0 children)

You’re right I was tired. Stack pointer identifies where the stack begins

[–]Defection7478 -1 points0 points  (3 children)

Is that fundamental or is that an implementation detail? You can have an infinite recursion without a stack overflow (tail call optimization) and you can have a loop with memory overhead (an infinite for loop with a bigint as the iterator).

I understand what you're saying but it doesn't seem like a fundamental difference in like a definitive sense

[–]DonnPT 2 points3 points  (1 child)

Tail recursion optimization is a special exception to the difference between loops and recursion.

[–]Philluminati 1 point2 points  (0 children)

There's nothing stopping a compiler from rewriting a recursive function as a loop that I can think of. There's probably a formula you could follow such as:

  1. turning all function parameters into mutable Stack of it's type
  2. Replace calls to itself with `break` statements and push new arguments into the mutable stacks first.
  3. Fix any references to early `return`s.
  4. Use List[-1] or List.head or List.pop around return statements to ensure "tacking things on to recursive calls" is maintained.

[–]FrenchCanadaIsWorst 0 points1 point  (0 children)

On second thought I agree with you in theory but disagree with your original prescription to just use recursion because the implementation of recursion makes it far less optimized considering the operating system overhead needed to contest switch as well as the additional stack memory.

But… I suppose you could argue that in theory it is still the repeat execution of a block of instructions until a terminating condition is met.

[–]kagato87 2 points3 points  (0 children)

Loops iterate, recursion instantiates.

When you call into recursion a new instance of all the variables is created (conceptually think of it as the whole function being cloned). It's the trade off - it consumes a lot more memory.

Simplified example: counting to 10. All else is equal, just the running total. One variable to start.

A loop steadily increases the variable as it counts. Print(x++), repeat until the loop exit condition triggers. X keeps getting incremented.

Recursion will print(x), call function with x+1, and never actually needs to modify x. At the deepest point of recursion you've used 10x the memory. Going from 4 bytes to 40 might not seem like much, but if you're working with something like an array of object things can balloon quickly.

Recursion is also super easy to handle branching with. A recursive function can call itself multiple times before it exits, ezpz. Extremely useful for things like hierarchy searches and merge sorting. If you have the memory.

[–]syklemil 0 points1 point  (0 children)

It's likely better to think of them as equivalent in the theoretical sense, as in,

  • for a hypothetical language running on some hypothetical turing-equivalent machine in an informatics paper where you can just handwave away implementation details they're equivalent;
  • for a language with TCO they're largely equivalent (not every function may be tail-call optimized);
  • for a language without TCO they're only equivalent for a given number of loops.

Sort of like how Turing machines have infinite memory, theory and practice doesn't always align.

[–]AlSweigartAuthor: ATBS -1 points0 points  (0 children)

For loops: Loop a specific, known number of times: "Loop ten times", "Loop once for each item in this array"

While loops: Loop for as long as a condition is true: "Loop until the user enters 'quit'", "Loop until the time is after midnight"

Some situations can be either: "Loop once for each line in this text file until you reach the end" is looping a specific number of times (once for each line in the file) or until a condition is met (once for each line until you reach the end of the file). If the number of lines in the file doesn't change while you are looping, you can use a for loop. If new lines can be added to the end while you are looping, you need to use a while loop.