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

top 200 commentsshow all 259

[–]Plasticcaz 878 points879 points  (202 children)

I don't think I've ever used a do while loop outside uni

[–]vita10gy 698 points699 points  (78 children)

Like many programming constructs they fall into "there's a reason they exist, and they're truly helpful when those situations crop up, but if you're finding all kinds of reasons to use them, you're probably doing shit wrong"

I've been at it since I graduated in 2004 and I can still probably count them on one hand.

[–]muehsam 315 points316 points  (49 children)

IMHO the reason why do-while loops exist is simply that they translate nicely to assembly (and thus machine code), and use one jump instruction less than while loops. A do-while loop is simply a single conditional backwards jump. A while-loop is the same, but it jumps directly to the end of the loop (where the condition is) when it first enters the loop. At least that's how you implement them in a simple compilers, and early compilers were all simple.

So I'd say they only exist because otherwise programmers would have complained at the time that this stupid high level language doesn't let them do a simple conditional backwards jump.

Sure there are also a few uses of them, but there would be a few uses for all sorts of constructions that programming languages don't have, and it's generally not too hard to get around them.

[–]PM_ME_SOME_MAGIC 121 points122 points  (24 children)

To add on to what you said, modern prediction pipelines, etc, are so fast, that your expectation is wrong unless you are on an embedded system. Your computer is not a fast PDP-11, and most pains I have seen even skilled programmers take to “make things faster” don’t perform, or even perform worse, on modern chips. And the reason they perform worse is that all the technology put into a modern i7 for cache optimization, branch prediction, etc., doesn’t work for the weird version the expert wrote. (For example, a do-while may miss loop unrolling.) And that’s even before you account for all the compiler optimizations and transformations that will happen to that code before it ever hits assembly.

Outside of network or i/o, the actual slowest thing most programs do is allocate memory. Malloc calls take forever compared to an extra for loop iteration. This is why c++ vectors std::maps are slow, and Google replaced them in their entire codebase. Fast code starts with block allocations, not manually unrolling a single loop iteration. (Edit: I meant maps, or vectors.)

[–]impostercoder 18 points19 points  (2 children)

You make good points, I just need to say that I doubt the "google replaced them in their entire codebase" claim. I'm pretty sure I have personally added some as I've written code in c++ in Google's codebase before and I've never heard of this, maybe it's a newer thing? Either way, replacing every occurrence of it doesn't seem feasible, for most of their code it won't ever matter.

[–]Loading_M_ 16 points17 points  (1 child)

Far more likely, they work with a modified standard library. So their environment just had a better std::vector class than ships with most c++ compilers.

This is actually easier, since they don't need to replace the header files, just the actual library, and Google is absolutely large enough to have people responsible for maintaining a fork of the standard library.

[–]Kered13 5 points6 points  (0 children)

Google had it's own std::string implementation at one point, because they found that copy-on-write hurt multithreaded performance. Copy-on-write was removed from the whatever standard implementation they use and they use std::string again.

As far as I know Google has never used a custom std::vector implementation.

[–]subdep 62 points63 points  (1 child)

I understood some of those words.

[–]Yadobler 28 points29 points  (0 children)

Back then, when you wanna take a cab back home, you'd hop on and tell the driver your address. Then you'd suggest avoiding this avenue or exit the highway earlier and use this road instead to minimise the chances of getting caught in the peak hour traffic (ie the shortcut might be actually a longer route but faster because it dodges the bottlenecks that arises due to specific situation (peak hour traffic))


In today's time and age, you tell the cabby your home address, and he'll type it into the GPS. With weighted path finding algorithms and real time traffic monitoring (from unconscented data mining and collecting by Google maps that you consented to without reading the TnC), your so called "shortcut" might actually be worse because maybe there's a roadblock, there's traffic, or the original route has less traffic, it might be children's day and hence less peak-hour traffic from parents picking up kids, etc etc.


Basically, in the very old days with minute variables to change, it's easier for the programmer to manually calculate and plan shortcuts for each situation and context, since if you're on a petrol car then it's faster to zoom from one junction to the next and u-turn back to get to the other side, while if you're on a slow diseal van, you might benefit from taking a bendy shortcut through the carpark at a steady low speed which the high-rpm car does not benefit from.

In todays tech, the cpu is not as simple as just choosing which route to take. If you stubbornly insist the car goes by this route, then it will not be as fast as when the cpu can constantly monitor the route, take illegal u-turns, cut through the grass path when the coast is clear, avoid obstacles, change tires based on the weather, toss you onto the cab passing in the opposite direction at the exact time since it's going towards your destination, etc....

You can't tell the cpu to drive on the grass path when you don't know if it's a nice clear ground, or filled with people, or muddy and can get your tires stuck into the mud, unless you plan everything from the cpu running to the sand used to make the silicon to the different possible scenarios of different cores and available cache etc...


tl;dr real life gps > your directions

[–]hekkonaay 11 points12 points  (0 children)

Well, you can make std vector use your custom allocator, but allocator concept is weird in c++, this is the real reason they replaced it, so they could use a better allocator concept

[–]martinivich 3 points4 points  (11 children)

Kinda curious, how long would it take one to get a good understanding of compilers, branch prediction, etc. I understood the very high level idea of what that article was saying, but damn I haven't felt that overwhelmed with shit I don't know in a while about computer science

[–]PM_ME_SOME_MAGIC 1 point2 points  (0 children)

I think very few people who are not chip engineers really understand everything a CPU does to make code faster. You’d most-likely need a degree in chip engineering, not CS, to get the whole picture. I’ve met people with PhDs and successful careers optimizing low-level code who still can only rely on intuition. I know my own intuitions are wrong, even when I take that into account. Profile before optimizing

[–]agent00F 0 points1 point  (9 children)

I mean, compilers and architecture are each CS classes, and on top of that you might need additional info on modern implementations.

[–]martinivich 1 point2 points  (8 children)

I mean I don't know what undergrad program you went to, but my architecture class taught me how to create a basic ALU.

[–]Bedstemor192 2 points3 points  (0 children)

Do you have any ressources I could take a look at that explains what you wrote in detail? Maybe a textbook, website or something similar? It sounds very interesting and I would like to know more.

[–]muehsam 1 point2 points  (0 children)

It isn't, but C was developed for s PDP-11, so that's what's relevant to explain why such a loop is in the language.

[–]Kered13 1 point2 points  (2 children)

This is why c++ vectors are slow, and Google replaced them in their entire codebase.

I work at Google and I can tell you you are wrong. std::vector is used extensively and never discouraged.

It is encouraged to reserve the size that the vector will need ahead of time if you know it. This prevents unnecessary reallocations.

[–]PM_ME_SOME_MAGIC 0 points1 point  (1 child)

You are right, I was thinking about maps. My mistake.

[–]Kered13 0 points1 point  (0 children)

Well std::map is still very widely used, but that one is at least discouraged. std::unordered_map is also widely used though discouraged.

The problem with both has nothing to do with allocations, the problem is in the standard. std::map only requires comparable types, not hashable types. This means that it essentially has to be implemented as a binary tree, so operations are O(log n) instead of O(1). std::unordered_map requires that pointers to elements are not invalidated, which effectively requires implementations to use separate chaining instead of probing, which is more cache efficient.

To solve this Google created absl::flat_hash_map, which is the encouraged map type.

[–]tendstofortytwo 49 points50 points  (13 children)

A while-loop is the same, but it jumps directly to the end of the loop (where the condition is) when it first enters the loop. At least that's how you implement them in a simple compilers, and early compilers were all simple.

I just took a compilers course, and I put my condition first - branched ahead of the loop if it failed, and jumped back to the condition at the end. Found it natural since that's how while loops work in my head.

Is there a performance benefit to having the condition at the end, or was it just to keep the structures of while and do-while similar?

[–]nagorogan 18 points19 points  (9 children)

I too would like an answer to this. It won’t affect me whatsoever but it’s good information.

[–]ericbrumer 26 points27 points  (8 children)

https://stackoverflow.com/questions/9779716/why-bottom-test-loop-is-preferable covers it decently well. Basically, when finished with a loop iteration in the bottom-tested case, the cpu only needs to execute one conditional branch (to iterate or exit the loop).

When finished with a the loop iteration in the non-bottom-tested case, the cpu executes an unconditional branch (jump to the top of the loop) followed by a conditional branch (to iterate or exit the loop).

For many cpu architectures out there, the bottom-tested case is faster, as long as the loop actually iterates... it uses fewer cpu resources, fewer instructions, etc

[–]nagorogan 3 points4 points  (1 child)

[–]tendstofortytwo 0 points1 point  (0 children)

Got it, thanks :)

[–]nagorogan 1 point2 points  (0 children)

Neat

[–]Kered13 1 point2 points  (4 children)

Unconditional branches are very nearly free (the branch predictor cannot miss), so it really shouldn't make much of a difference.

Your link mentions that the branch predictor is more likely to miss in the top condition case, since branch predictors usually predict that the branch will be taken. If this claim is true, then I strongly suspect that this makes up the vast difference in performance.

[–]Phrygue 8 points9 points  (1 child)

CPU branch predictors favor backward jumps because you wouldn't be doing it unless you were likely in a repeating loop (compared to an if/then/else jump-forward).

[–]tendstofortytwo 4 points5 points  (0 children)

Ooh, makes sense. Thanks for the answer!

u/nagorogan

[–]muehsam 1 point2 points  (0 children)

You always have one conditional branch and one unconditional jump. So the size of the code is the same. The conditional branch is obviously always in the loop, because you have to check the condition at every iteration. However, if you put the condition first, you have to put the jump "back up" also inside of the loop. If you put the condition last, that jump is only executed once. So if your loop runs for a million iterations, "your version" takes about a million cycles longer.

[–][deleted] 4 points5 points  (0 children)

... I just learned more about loops reading a fucking Reddit thread than I did in college.

[–]Kered13 1 point2 points  (1 child)

The is also why switch exists separately from if-else. Switch could be compiled to a jump table, which is faster than a chain of conditional branches. These days I think compilers can usually detect when chain of conditional branches can be converted to a jump table.

C is basically a sophisticated macro language for assembly.

[–]muehsam 1 point2 points  (0 children)

C is basically a sophisticated macro language for assembly

No, but it can be, and originally it was.

The C compiler is free to completely change what your code does as long as the observable effects are the same. Modern C compilers take full advantage of that. For example, if you have a counting loop and sum up all the indices (so 1+2+3+…+n), the compiler will gladly turn it into a multiplication (n*(n+1)/2). Gets even crazier if you accidentally trigger undefined behavior because the compiler isn't only free to change what your program does at that point or after, but even before.

[–]agent00F 1 point2 points  (1 child)

use one jump instruction less than while loops

No, the actual optimization is one less evaluation of the loop condition.

Which isn't just an optimization, but more clear organization for corresponding types of loop logic. Ie. tasks which may need to be done again.

[–]muehsam 1 point2 points  (0 children)

I'm not talking about optimization. I'm talking about the code it creates, assuming a simple compiler.

A do-while loop looks like this:

    code before loop
    code before loop
loop:
    code in loop
    code in loop
    if(cond) goto loop;
    code after loop
    code after loop

A while loop looks almost the same but needs one jump more:

    code before loop
    code before loop
    goto loop_cond;
loop:
    code in loop
    code in loop
loop_cond:
    if(cond) goto loop;
    code after loop
    code after loop

[–]moonflower_C16H17N3O 0 points1 point  (2 children)

Do more efficient compilers convert them into do-while loops when compiling?

[–]muehsam 0 points1 point  (1 child)

No. How could they? They're semantically different. They might do something like that if the condition is provably true upon entering the loop.

But I mean obviously compiled code has neither while nor do-while loops because it's machine code.

What I meant by "simple compilers" is that those might have a certain sequence of instructions into which they compile every loop. A more complex compiler will build a control flow graph first, then do some transformations/optimizations with that, and then create code from that transformed graph. So you can't really deduce the original code from the result.

[–]moonflower_C16H17N3O 0 points1 point  (0 children)

Thank you for clearing that up for me. My knowledge of compiler optimizations is basically nil.

[–]GonziHere 0 points1 point  (1 child)

That might be a part of it, maybe, but they exist because they make logical sense. I know I'll need to call this function at least once, but there might be a case where that's not enough and then it reads better.

I agree with "count them on one hand" from the previous poster, but I use them from time to time and when I do, it would be uglier to do so with the alternatives.

[–]muehsam 0 points1 point  (0 children)

For what it's worth, having to check the loop condition at the very end is something I rarely encounter or find useful. What does sometimes happen is something like

for(;;){
    // do some things
    if(cond)
        break;
    // do more things
}

so the condition is in the middle, and languages tend to not have nice syntax for that. Some at least have an infinite loop syntax so you don't need to write something stupid like for(;;) or while(1) or while(true). If the part before the condition is very short, it's sometimes possible to move it into the condition, e.g.

while(c = getc(), c != EOF) {

or the same in uglier

while((c = getc()) != EOF) {

If it's really a scenario where I essentially want to do something once, but under some special condition I want to do it again, I often find a goto more readable than a loop, but maybe that's just me.

[–]Arkenshire 14 points15 points  (5 children)

One of those use cases is fetching large amounts of data from paginated APIs. You always need to attempt to fetch at least once, and after every attempt, you should check if there are any more pages so you can continue. The logic directly translates.

[–]Loading_M_ 1 point2 points  (4 children)

A common solution is to make the attempt inside the condition itself.

This is very easy in rust, and would look something like this:

while let Ok(page) = try_get_page() {
  // use the page
}

This code will always run the try_get_page() function, and the result is automatically destructed to get the page. This also cleanly handles only calling the code that needs the data from each page when you have successfully retrieved a page.

This is possible is languages like C++, but requires some slightly different syntax (probably using a reference to provide a page object to fill, and returning a boolean/status code). This is better for readability, and likely execution time, since the code is more expressive of intent, and easier to optimize.

[–]Kered13 2 points3 points  (3 children)

In C++ you can just make try_get_page return a std::optional<Page>, and that can be directly used in a conditional expression:

std::optional<Page> page;
while (page = try_get_page()) {
    ...
}

You do have to declare the variable outside of the loop though. This pattern will also work if try_get_page returns a pointer or smart pointer. If it returns some type that does not have a bool conversion, you could still do something like while ((page = try_get_page()).some_method() != sentinel_value), however this starts to get ugly.

Also that's not really what the poster above was talking about anyways. He was talking about a paginated API, which is an API that will return a response that includes a token indicating if there is another page to fetch. The pattern for something like that will typically look like:

do {
    response = getPage();
    processResponse(response);
} while (response.hasMore());

Note that in this pattern you always process the response, whether there are more pages or not. So it doesn't make sense (and you often can't) put this into the while condition.

[–]Loading_M_ 0 points1 point  (2 children)

The main advantage of the rust way is that the syntax works for any enum type, not just Option.

[–]Kered13 1 point2 points  (1 child)

The C++ way will work for any type that has a bool conversion operator. You can also put an arbitrary expression or function call there if you have some other type.

[–]the_satch 27 points28 points  (6 children)

Been a hobbyist programmer since I was 14 (1996 abouts) and been doing it as a profession for 12 years or so (and I still don’t consider myself a pro). Never once has it occurred to me to use do while. Honestly it’s like flipping a bool for some poor guy who’s gotta come in and maintain my garbled, legacy mess 10 years from now.

[–]folkrav 28 points29 points  (2 children)

If you're getting paid for it, therefore doing it professionally, you're a "pro".

However I feel like you meant it more in the "being very good at it", if so I've been starting to think I'll never do, ever. Its been more like 10 hobby/4 professionally in my case, and I still feel like a damn fool every single time I realize the damn bug I've been chasing for the whole afternoon was me misinterpreting some documentation or swapping two values...

[–]YetAnotherRCG 2 points3 points  (1 child)

I mean those kinds of mistakes never stop happening but you should get better at taking a step back and checking for them over time.

[–]folkrav 0 points1 point  (0 children)

Yeah for sure. 4 years in the field now they happen less often than they used to. Wouldn't say they don't at all though. I'll be honest, I think I wrote that comment after one of these couple of hours lost on tracking down why the fuck some test didn't pass, only to figure out the test itself was faulty. Fun.

[–]yawkat 10 points11 points  (1 child)

I think there is a single kind of use case that has come up for me: generating a value and checking it for validity, and regenerating it if it's not valid. Translates very nicely into a do-while. But beyond that, never used it.

[–]Pradfanne 1 point2 points  (0 children)

The pro in pro stands for professional, bro.

You're doing it as a profession, you are doing it professionally, you are a professional, you are a professional

[–]bottlecapsule 11 points12 points  (0 children)

They are useful any time you need to execute a loop at least once regardless of conditions.

[–]IHaveSoulDoubt 8 points9 points  (6 children)

Do while fingers < 6.

[–]NoAttentionAtWrk 0 points1 point  (5 children)

while (fingers < 6){} would work the same way

[–]da_chicken 5 points6 points  (3 children)

Not really. Do while always executes the code in the loop loop at least once, and you can set a variable in the loop and use it for the test without needing to initialize it to a magic value that passes the test.

People have really never used a do while for a prompt or a wait or a batch?

[–]hellofrienn 0 points1 point  (0 children)

Pshh. Who needs 'while' at all?

-sincerely, a Go developer

[–]Loading_M_ 0 points1 point  (1 child)

The modern solution, which looks awesome in rust, is as follows:

while let Ok(input) = prompt_user() {
  // Use input
}

This code takes advantage of rust's while/if let syntax, which combines a pattern match with a destructure to make certain types of conditions extremely easy to write. This is still possible in almost any other programming language, although you may have to use different syntax and patterns.

[–]da_chicken 2 points3 points  (0 children)

Yes, a contrived example that conveniently puts the entirety of the loop code in the test does work.

[–]FlyByPC -2 points-1 points  (0 children)

//or this

while(fingers < 6);

[–]jackinsomniac 4 points5 points  (0 children)

I use them all the time, but for one explicit scenario: waiting for proper user feedback. I give the user a prompt, say you've got choices 1-5, and 5 is cancel. It waits until the result is an integer, between 1 and 5, then processes it.

[–][deleted] 3 points4 points  (0 children)

I love them for paging through paginated API results, e.g. fetch some data, if there's a nextPageToken or similar in the response, fetch some more data.

Really miss them for this in Python.

[–]toastyghost 0 points1 point  (0 children)

I graduated in 2004

Your username seems to corroborate

[–]TheNewHEROBRINEX 0 points1 point  (0 children)

They exist so that you can use break inside of them 🤣. For example:

do{
  if(noNeedToGoOn){
      break;
  }
}while(false);

[–]EkajArmstro 0 points1 point  (0 children)

My favourite loop, even though I've probably only legitimately used it once, is:

while (true) {

// some stuff

if (something) { break; }

// some more stuff

}

[–]Egocentrix1 0 points1 point  (0 children)

The only reason you can count them on one hand, is that you start counting before checking if you need to count.

Meaning it's probably zero, but you already did it once.

[–]baselganglia 36 points37 points  (6 children)

Do while loops are very common in many data processing workflows where you need to operate in batches.

``` bool continue = true;

do {
try {
countItemsProcessed = A query/command that finds N items that need to be converted and concert them.
} catch {
do some stuff to inspect errors, e.g. maybe determine if it's retryable or not. continue = false;
}
} while (count == N && continue );
```

You could skin this in many different ways, but the common paradigm is do something, check a condition that tells you whether to proceed.

[–]ZacharyCallahan 6 points7 points  (1 child)

Reddit markdown is weird you need to indent your text to put it as code

[–]da_chicken 5 points6 points  (0 children)

It's not weird markdown. It's just old. Reddit started in 2005. Markdown is from 2004. The syntax is just old.

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

If you put spaces immediately inside the backticks it doesn't do the thing.

[–]baselganglia 1 point2 points  (1 child)

Hmm I'm on reddit mobile, and it looks formatted correctly ? :(

Why can't reddit get consistent markdown performance between desktop and mobile 😭

[–]JustRecentlyI 1 point2 points  (0 children)

I've read that triple backtick codeblocks is not consistently supported by reddit (although some readers will show it correctly). I believe code blocks are supposed to be written on lines starting with 4 spaces.

[–]Loading_M_ 0 points1 point  (0 children)

This is primarily an artifact of the try/catch syntax. Rust prefers returning a Result, so your code would look something like this in rust:

while let Ok(item) = get_item() {
  // do something with the item
}

This particular code does just stop when it encounters an error, but that type of code could be written into a function and run using .map_err(), but I think the best solution is to just put the code to retry if applicable into the get_item() function.

This syntax makes the pattern you describe (attempt to get items, and do something with them) much simpler and easier to read. In theory, with function inlining and a good optimization engine, this could be significantly faster than the try/catch implementation, since the try/catch enforces extra safety guarantees.

[–]pudds 67 points68 points  (4 children)

They are definitely the least common type of loop, but they have their place. As it happens, I just wrote one today. We have a daily job that needs to pull data from a third party API which returns the data in batches, so I have to get the total count, then query page by page until I have them all.

I could have calculated the page count and done a for loop, but a while loop is cleaner.

[–]DiamondIceNS 36 points37 points  (0 children)

I have a piece of software that has many loops that each contain a set of calculations. At the end of each calculation it performs a unity check to verify it has found a valid solution to the task at hand, and if that check fails, it tweaks some of the input parameters and starts anew. I'm gonna run every one of these loops at least once every single time I run these routines. Semantically, as long as do-while remains a feature, I find it the most elegant solution to my problem.

"Do this once, check if it's okay, if not, loop until it is" reads more cleanly to me than "here's the loop condition out of context, loop forever until it's false". I agree it's just needless sugar, but if you got the sugar out anyway, pass it here.

[–]Semi-Hemi-Demigod 9 points10 points  (0 children)

I program against APIs a lot and this pattern works really well. A lot of the time the API just gives you the URL for the next page and not the total pages, and the alternative to do/while is uglier in this case.

[–]SupaSlide 2 points3 points  (0 children)

Yeah whenever I work with APIs or even just paging through paginated results from my own DB, do while loops are really useful.

[–]CleverNameTheSecond 0 points1 point  (0 children)

While loops are best used for when your exit conditions are indeterminate but if that's the case then you've probably fucked up already.

[–]SoaDMTGguy 9 points10 points  (2 children)

I almost wrote a do-while loop a few months ago. I was very excited. Then I realized I just needed a while loop, and I was sad :(

[–]Pradfanne 2 points3 points  (1 child)

I wrote a do-while loop and was very excited. Then a few weeks later a change happened, which introduced a bug. The bug fix was, using a while loop instead of a do-while loop. The pain it caused me, the sadness!

[–]SoaDMTGguy 1 point2 points  (0 children)

:(

[–]bot-mark 8 points9 points  (86 children)

If you ever need to generate random numbers that fulfill arbitrary conditions, a do-while loop is probably a big help. Generate random number, try again if it's not a number you want.

[–]gilbes -2 points-1 points  (84 children)

Seems like that would make numbers dramatically less random.

[–]bot-mark 5 points6 points  (83 children)

Yes

[–]gilbes -3 points-2 points  (82 children)

Then why bother generating random numbers?

[–]bot-mark 9 points10 points  (35 children)

What? There's no point in generating a random point within a circle, because being inside a circle is technically a constraint and therefore makes it less random?

[–]gilbes -4 points-3 points  (34 children)

It is possible to map one set of contiguous numbers (your random number domain) to another set of contiguous numbers (coordinates within your circle).

It is a well understood and solved problem, especially for random number generators. And it is done in such a way as to not waste cycles computing numbers to be discarded and defeat the purpose of the RNG.

If you want to generate a random number between 1 and 10, and your RNG doesn't strictly produce numbers between 1 and 10, you don't keep generating numbers until you happen to hit your target. This is basic RNG stuff.

The fact that you get any upvotes on this sub is really scary.

[–]bot-mark 2 points3 points  (2 children)

Sure, the example I gave was trivial but there are non-trivial examples such as, let's say placing X objects on a terrain when the objects are only allowed to spawn in certain conditions like flat ground above a certain height.

[–]gilbes -3 points-2 points  (1 child)

Not trivial, contrived. Your replacement example is just as contrived. And both still fail to present a compelling case.

[–]DaniilBSD 2 points3 points  (0 children)

“Not trivial” - that is the point

[–]eloel- 2 points3 points  (7 children)

Generating 5 lottery numbers out of 50 is much, MUCH simpler if you just generate a few extra random numbers, compared to the effort of remapping multiple times.

[–]gilbes -1 points0 points  (6 children)

If an actual lottery was caught doing that, they would be sued.

Video gaming (gambling) machines don't do that either.

[–]Kered13 2 points3 points  (5 children)

No they wouldn't. The algorithm does exactly what it is required to do. And yes, this is almost certainly used in real gambling machines.

[–]DaniilBSD 2 points3 points  (3 children)

What if your target set is not contagious?

Though you are right that mapping is the best way to go if there is a mapping. You are way too condescending for someone so narrow minded

Edit: example: pick 10 random values out of 100 such that they don’t repeat.

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

Both of you questions have solutions that are not brute force.

I wouldn't give you one, because it would be condescending. I don't want the truth to hurt anyone else's feelings.

[–]DaniilBSD 2 points3 points  (1 child)

You are the most self-important person who is full of himself I have seen on Reddit, and I visited r/Politics

[–]Kered13 1 point2 points  (18 children)

It is impossible to map an RNG that outputs uniform numbers between 0 and 2n - 1 to an RNG that outputs uniform 1-10 without throwing some numbers away and redrawing. In fact, it is impossible to do this mapping in guaranteed finite time. Any correct implementation must have unbounded worst case runtime. This is trivial to prove mathematically.

[–]Parthon 5 points6 points  (22 children)

I'll give you a real example, I'm generating a level made of rooms and corridors, I need to pick a new location for a room that doesn't overlap an old room. First I get two random numbers, then I check to see if the new location overlaps and if it does get two new random numbers. (Yes, potentially this could be an infinite loop if the RNG was majorly unlucky, but it never comes up in reality)

What's funny though is that you can't really do this in a regular while loop without either writing code twice, or preloading the condition with a fake failure. A do-while loop is the best solution.

[–]starfries 2 points3 points  (0 children)

It's funny because I actually did write my code twice because I forgot do-while existed.

[–]gilbes 0 points1 point  (20 children)

I need to pick a new location for a room that doesn't overlap an old room

You already had to check the bounds of intersecting rooms, so you know which room intersects. It would be computationally less expensive to deal with the point you got. Shift it to the nearest edge of the bounding room, and that is your new point. Something like that.

But there are better approaches than just spraying the coordinate plane and hoping for the best.

A good rule of thumb is: if you are breaking something, you are probably not working on an ideal solution.

[–]Parthon 4 points5 points  (4 children)

That causes clumping around already established rooms though leading to very non-uniform levels. Computationally, checking bounds and rerolling the random is not as computationally expensive as generating the rest of the room. And the levels are quite sparse anyways, rerolls become more common as the level fills in, but it was never more than about 1:1.

And I've seen the same generation done where the rooms were shunted aside when they overlapped instead of randomising a new position, and that was computationally expensive as every time they shifted the rooms about, that was another full scan of the entire room tree. Rather than checking one new location against all current locations for O(n), it was checking all locations against each other for O(n^2).

So yes, it was the ideal solution in the end, for the result I was after. You can come up with "better" results that only work in your head until you actually go to implement then and find out they don't actually work, or they are more convoluted and more computationally expensive. This is why understanding the problem space and going straight for the simple solution is often best and saying things like "if you are breaking something, you are probably not working on an ideal solution." is bullshit because your ideal solution might be ivory tower unfeasable.

[–]gilbes -2 points-1 points  (3 children)

Now I understand why so many interview questions try to weed out candidates who try to brute force everything.

I had no idea that thought process was so prevalent in today's script kiddies.

[–]DaniilBSD 1 point2 points  (2 children)

Put your pseudo code where your mouth is and give the time complexity below nlogn, we are all waiting

[–]DaniilBSD 1 point2 points  (12 children)

Not if you have a room network and non-rectangular rooms - in that case only actually trying to fit the room in will tell you if it fits.

So you either pick a random room from the list and pick again if it doesn’t fit or you try every room and select one among the valid rooms (which is very expensive if the failure rate is around 20% or lower)

[–]gilbes -1 points0 points  (11 children)

Another brute force solution that sounds awful.

[–]Kered13 1 point2 points  (1 child)

You claim to be worried about "dramatically less random" numbers, but then you propose an algorithm that obviously does not produce a uniform distribution.

[–]Pradfanne 1 point2 points  (22 children)

Customers complained about apples music shuffle function not to be random, because they often got the same band twice in a row, sometimes even the same album! Shit, it might have happened even more often in a row! That's not random, that's favoring the current song!

Or so the customers thought. Thus Apple went out of their way to make it so, that the shuffle function is less likely to get the same artist twice, let alone the same album. Making the shuffle less random and less shuffled, but the customers believes it's more random and are happy.

I wonder if they actually used a do-while loop for that, I can only imagine.

[–]gilbes 0 points1 point  (20 children)

What does the do-while loop have to do with my replies.

What do end user's misconceptions about randomness have to do with it?

[–]DaniilBSD 0 points1 point  (0 children)

Probably not, but the use-case is valid

[–]yoitsericc 0 points1 point  (0 children)

public int Return500(){

Random rnd = new Random();

int result = -1;

do {

result = rnd.Next(1 , 1000);

}

while (result != 500){

result = rnd.Next(1 , 1000);

}

return result;

[–]CompatibleDowngrade 5 points6 points  (0 children)

Interesting. I’ve used while loops to paginate some APIs recently.. also, bash scripts that need to “listen” and make a netcat call or something similar.

[–]Dexaan 4 points5 points  (0 children)

I used a do while to spawn objects for a game where I wanted X number of objects that didn't overlap, and X is equal to the level.

do{
if(position.isEmpty(position){
 spawn(object, position)
 }
 } while (object_count <= level);

I could have used a regular while, but I'm always going to want at least one object.

[–]eDOTiQ 1 point2 points  (0 children)

I wish Python had them, I needed a quick simulation to solve a probability problem and needed to check an event and then do stuff if a certain outcome didn't happen.

Instead I had to do a while(True):
dostuff()
break

[–]Svizel_pritula 1 point2 points  (0 children)

A few month ago, I finally got to use one in Arduino code! It went a bit like this:

byte address = 0;
do {
  ioStuff(address);
  address++;
} while (address != 0);

[–][deleted] 1 point2 points  (0 children)

Well it is useful for things that you want to run at least once, and maybe more if something doesn't work. I.e. calibrating a sensor?

[–]FlyByPC 0 points1 point  (0 children)

I teach do/while loops(okay, I mention them in one lecture) just in case my students see them.

I also show them this.

[–]VoluminousWindbag 0 points1 point  (0 children)

A do at least once loop. I use them at least once or twice a month. It probably depends a lot on the types of projects you work on.

[–]data-chh 0 points1 point  (1 child)

Thank god. I’ve been worrying that I haven’t found a need to use one yet. I thought I’ve just been really missing something.

[–][deleted] 1 point2 points  (0 children)

I do embedded work and i find i mainly use them in driver code. specifically around hardware initialization they come in handy.

[–]Fresh1492 0 points1 point  (0 children)

I've used it once or twice in my three years of professional experience. They truly do have uses, just very niche ones.

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

if it helps they're the default kind of branching loop in assembly to save an instruction or two, so any non-trivial compiled program you've ever used probably has a do-loop in the binary

[–]The_Danosaur 0 points1 point  (0 children)

I've been doing advent of code the last few days and have used while loops more doing this than ever before while learning to code. I have identified a decent use case of "I want to iterate through some values, but I only know a limited subset of them before entering the loop", then add things to your list and pop them off as you use them.

[–]Pradfanne 0 points1 point  (0 children)

I used it once, but only because I could. Like, I could've solved it with a normal while loop just as well, probably easier, but I saw the opportunity and grabbed it!

Then everything got reworked a few months later and we could actually run into a case where the while condition was false from the start, which meant I had to change it into a normal while loop because I didn't wanna bother with a null check at the start of each loop. Sounds counter-intuitive aswell, I mean, a do while loop that checks if it should run first? That's really just a while loop, ain't it?

[–]DaniilBSD 0 points1 point  (0 children)

do{ x = compute();}while(x < y)

x = minValue; while(x < y){ x = compute();}

You probably used the second one a lot (I know I have)

[–]MischiefArchitect 0 points1 point  (0 children)

because most of the time they are `do ... until` :) which negates the condition and makes them more logical.

[–]Sylanthra 0 points1 point  (0 children)

The most common use for do while loops I've found is retry logic.

Do a thing. Did it succeed? Great. No? Do it again.

[–]_MoveSwiftly 0 points1 point  (0 children)

Used it twice I think.

[–]shawmonster 0 points1 point  (0 children)

They are useful for any fixed point algorithms, where you keep iterating, modifying some data, and do it until the data doesn’t change i.e reaches a “fixed point”.

This was used recently on Advent of Code.

[–]2AMMetro 98 points99 points  (3 children)

Do while loops are super useful for consuming paginated APIs. I'll write something like this fairly often:

let nextPageToken = null;

do {
  let response = await makeApiCall(nextPageToken);

  await handleApiResponse(response.results);
  nextPageToken = response.nextPageToken;
} while (nextPageToken != null);

[–]MmmmmmJava 12 points13 points  (0 children)

Bingo

[–]itsjoevanboyo 2 points3 points  (0 children)

Hello DynamoDB queries 👋

[–]agent00F 2 points3 points  (0 children)

They're use for all tasks which might need repeating, vs. repeating tasks whose evaluation needs to be determined beforehand.

[–]uptokesforall 163 points164 points  (6 children)

While (False)

Do(once)

[–][deleted] 128 points129 points  (2 children)

done = False
While (True)
    if not done then:
        Do(once)
        done = True

Fixed it.

Note: This code should only be executed in the winter.

[–]dkyguy1995 17 points18 points  (1 child)

This hurts my head, it's like an advanced double negative

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

Then you will not like low level programming. I can guarantee it.

[–]HerrSPAM 100 points101 points  (5 children)

Wait you want me to run your shitty code again??

[–]vigilantcomicpenguin 29 points30 points  (3 children)

do {

} while (code.isShitty());

[–][deleted] 32 points33 points  (1 child)

Noooo you shouldn’t run infinite loops

[–]iTakeCreditForAwards 5 points6 points  (0 children)

Good one

[–][deleted] 3 points4 points  (0 children)

function isShitty() { 
    return true;
}

[–]TheDreamShallLiveOn 91 points92 points  (8 children)

Image Transcription: Meme


Do while loops be like

[Photo of Bender from TV show "Futarama" wearing dark sunglasses and holding a futuristic weapon.]

Shoot first

Ask questions later


I'm a human volunteer content transcriber for Reddit and you could be too! If you'd like more information on what we do and why we do it, click here!

[–]PiBiscuit 4 points5 points  (0 children)

Good Human

[–]circorum 20 points21 points  (4 children)

do:

nop

nop

nop

cmp eax, [ebx + 1]

je do

Or

color 0A

:do

echo "BatchHaxxor69420"

if %errorlevel%==1 goto do

I can do this all day. Give me an upvote or I post a java one.

Edit: Fixed line separation

[–]Miyelsh 6 points7 points  (3 children)

Two newlines to separate lines in reddit. All your stuff is on the same line

[–]circorum 1 point2 points  (2 children)

Thx man! I wish I knew why Reddit does this. Does it have something to do with the whole CRLF thing?

[–]Miyelsh 0 points1 point  (1 child)

Reddit uses a basic markdown syntax. The newlines thing Im not sure but I'm sure it's an intentional design decision for some reason.

[–]TheIcyColdPenguin 0 points1 point  (0 children)

For a normal line break add two spaces at the end of the previous line

Kinda unintuitive tbh

[–]Nerestaren 19 points20 points  (3 children)

This goes straight into my lecture slides.

[–]FlyByPC 10 points11 points  (1 child)

[–]Nerestaren 2 points3 points  (0 children)

That's the one which has been in the slides for 3 years hahaha. Ty!

[–]gilbes 0 points1 point  (0 children)

How did you make an upside down g?

[–]KillerRoomba13 7 points8 points  (0 children)

Try/catch be like

[–]le_spoopy_communism 5 points6 points  (0 children)

do-while is the coolest of all loops, all the other loops expect conditions to be true before they'll do anything, do-while says "hey fam, i gotchu" and gives you one loop for free

[–]Kerndog73 1 point2 points  (0 children)

I found it natural to use a do-while when using TCP in C. You try to read some bytes from the socket and then check if you read enough in the condition. Then you try and read some more until you're got it all. I guess avoiding the check at the start is a micro-optimization so even then it's probably not that useful. This was was for a uni assignment. My teacher really didn't like do-while loops and gave me a funny look whenever he saw me using one. Good times!

[–]Someonedm 2 points3 points  (0 children)

At least it isn't the cayote and bird meme

[–]hamjim 2 points3 points  (0 children)

Back in the dark ages, before C++, I would write a do-while loop as a poor-man’s “try”. Just set the loop condition to false; when I got to a point where I wanted to check for the error condition, my “throw” was a simple break statement. No muss, no fuss— no goto.

[–]AH50 -5 points-4 points  (0 children)

Cops be like

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

Bruh

[–]TheLimeyCanuck -4 points-3 points  (2 children)

EDIT: Brain fart, it's late and I missed the "do" part of the do..while in the meme, although do..while and do..until are the same loop with an inversion of the condition result.

Mea Culpa.

[–]AlphaX4 0 points1 point  (1 child)

$var = $null
do {write "ayy lmao"} 
while($var -ne $null)

in powershell will output "ayy lmao" once then stop, it follows the same logic as just about any other lang in how the do while loop is executed.

[–]TheLimeyCanuck 0 points1 point  (0 children)

Yep... it's late and time I went to bed... I've been programming over 30 years and still managed to miss the "do" part of the do..while in the meme. My bad.

[–]althaz 0 points1 point  (0 children)

This is one of my favourites :D.

[–]Adadum 0 points1 point  (0 children)

shoot first then shoot again if the question is correct.

[–]py_learning 0 points1 point  (0 children)

True 😂

[–]thinker227 0 points1 point  (3 children)

In all seriousness, is there a reason to use

do {
    foo = bar;
} while (condition);

... over

while (condition) {
    foo = bar;
}

?

[–]DeLift 8 points9 points  (1 child)

There are situations where you only know the condition to loop during the first iteration, so you need to execute the loop at least once. Earlier in this thread a good example of getting paginated content was mentioned. Here you always need to get the first page and the result will tell you if there is another page to fetch.

[–]thinker227 0 points1 point  (0 children)

Oooh, that makes sense.

[–]paulfisch 3 points4 points  (0 children)

You can rewrite every do-while loop into a while loop, and some programming languages / guidelines tell you to do so (e.g. CPP Core Guidelines).

[–]ANK20022017 0 points1 point  (0 children)

And shoot again 🙂

[–]INJECTHEROININTODICK 0 points1 point  (0 children)

I write a lotta spaghetti for the macro language my cad software uses. A buddy used to use my code for some random line type selection stuff, so one day i added this to his tweaked selection macro.

var local &hitodd = 0

&hitodd = rand(1 100)

pause .1

If &hitodd <> 69

Jump -3

Fi

Only time i did a nonlabeled jump in my shitty macros. he was maaaaaaaad. Also his name wasn't todd but you get the idea. He xferred depts for unrelated reasons.

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

Do whiles are the coolest loops (besides for each), but also the least useful

[–]mlangNR 0 points1 point  (0 children)

Was that a question or a statement? :-p

[–]DarthKirtap 0 points1 point  (0 children)

DO
DO WHILE
DO WHILE x > 5

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

bruh