ID:1711853
 
Keywords: bug, for, list, loop, member
Not a bug
BYOND Version:504
Operating System:Windows 7 Ultimate 64-bit
Web Browser:Chrome 38.0.2125.111
Applies to:DM Language
Status: Not a bug

This is not a bug. It may be an incorrect use of syntax or a limitation in the software. For further discussion on the matter, please consult the BYOND forums.
Descriptive Problem Summary:
If you add new members to a list in the middle of the for list loop, these new members won't be part of the current for proc.

Numbered Steps to Reproduce Problem:
copy paste the code below, notice how instead of having an infinite loop, you'll only loop once.

Code Snippet (if applicable) to Reproduce Problem:
/mob/verb/stuff()
var/list/L = list()
var/obj/O = new(src)
L += O
for(var/obj/P in L)
var/obj/N = new(src)
L += N


Expected Results:
I expect the for loop to run through the new members added in the middle of the process

Actual Results:
They are being ignored, the for loop will finish without looping through the new members.

Does the problem occur:
Every time? Or how often? always
In other games? no game-specific
In other user accounts?not related
On other computers?not related

When does the problem NOT occur?
In older versions of byond, I can't say which one exactly, but we do have chunks of code that use this system, currently they are now bugged due to this bug.

Did the problem NOT occur in any earlier versions? If so, what was the last version that worked? (Visit http://www.byond.com/download/build to download old versions for testing.)

Workarounds:
for(i=0;i<list.len;i++)
var/object = list[i]

using this for loop works, but extremly laggy due to byond using linked lists (at least laggy with lists of a lot of members)
If you iterate over the list using a for-each loop, you won't be able to add new elements like that.

That's just how it works, in mostly every language.

It's not a bug. Your workaround is the valid way of doing it.
read the issue before commenting
I did. That's how I know it's not a bug.
Just popping in to say that you're free to discuss the merits of the bug report, but resorting to saying "just stop posting" and "you're giving me a brain tumor" is not constructive. Please keep it civil.
Okay.

Please stop commenting, as what you think it's informative insight, it's actually clueless and with lack of information. With all my respect, I humble ask you to stop commenting, as it bloats the issue report page and might hide future insightful comments that will come in the near future. Oh, and don't worry about any brain tumor, I already made an appointment with the doctor.
When you use a for-each loop, a copy of the list is created, that is why when you alter the list, it doesn't affect the loop.

http://www.byond.com/forum/?post=179171#comment1067929
Lummox JR:
In a for(item in list) loop, a copy is indeed made before the loop begins

get over yourself pls
it worked before naruto boy, maybe if you READ THE ISSUE REPORT YOU WOULD KNOW. A post made 12 years ago doesn't really change the fact that it worked a few months ago.

also admin he's insulting me please delete his post and make a comment referring only to his post please

Also also! Stop commenting! I have no idea how to ask it anymore.
I just want to apologise on behalf of tg for arans behaviour
Nadrew resolved issue (Not a bug)
can I get an explanation of why it worked previously at least
Your code changed?

If it didn't work 12 years ago, and doesn't work now, there's no way to know unless you feel like finding a version where it actually worked.
In response to Aranclanos
Aranclanos wrote:
can I get an explanation of why it worked previously at least

All I can suggest is that you may have seen some code appear to do what you expected, but it actually didn't. Either that, or you were using a more "standard" for loop with an index var, like my example below. The language has been this way, making a copy of the list before the for-in loop, since I first started using it. IIRC it's even written in the Blue Book.

Note that I'm not sure most languages work this way; that's a bit of an exaggeration. I haven't found any info one way or the other on JavaScript's behavior for instance, so there I avoid situations where the looped list can be altered. And inasmuch as C++ has this kind of concept with the standard template libraries, it's definitely not doing a copy. In Dart, which we use for the webclient, lists are not copied before a for-in loop and there is an error thrown if the list gets altered.

So why does BYOND do it? Simplicity. There aren't many cases with a simple for-in loop where you'd want to be able to handle mutation on the fly, when you could be surer of the results with a classic indexed loop. There are many more cases where you just want to loop through the list, and don't care if it changes. Internally, BYOND also tends to keep a lot of view(), range(), etc. results in the same list var that it frequently overwrites, so making a copy of the list is just good sense considering how often those are used in loops. All of this is done for the sake of making things easier on the programmer in the majority of cases.

Code that would allow the list to mutate while you loop through it would look like this:

for(var/i=1, i<=mylist.len; ++i)
var/item = mylist[i]
...

If new items are added to the list during that loop, they'll be handled; unlike a for-in construct, this doesn't make a copy of the list. You can even remove an item (decrement i if index < i; continue if you removed the current item) or insert an item (increment i if the insertion index <= i).