Discussion:
Modifying a table while iterating over it?
Cory Bloyd
2005-09-22 15:39:29 UTC
Permalink
What happens when you modify a table while iterating over it?

I would expect the following iteration to proceed unaffected by the
modifications, but I'm not certain...



for key, value in pairs(someTable) do

if someArbitraryCondition() then

someTable[key] = nil

end

end



I would expect the following code to behave unpredictably regarding
whether or not the new items appear in the iteration.



for key, value in pairs(someTable) do

if someArbitraryCondition() then

someTable[newKey()] = newValue()

end

end



Can anyone confirm or deny my suspicions?
Luiz Henrique de Figueiredo
2005-09-22 16:57:13 UTC
Permalink
Post by Cory Bloyd
What happens when you modify a table while iterating over it?
It's ok to set existing fields to nil but not ok to create new keys.
--lhf
Aaron Brown
2005-09-22 16:56:31 UTC
Permalink
Post by Cory Bloyd
What happens when you modify a table while iterating over
it?
pairs() is implemented with next(). The reference manual
says:

# The behavior of next is undefined if, during the
# traversal, you assign any value to a non-existent field in
# the table.

Assigning values to already existing keys is fine.
--
Aaron
Mark Hamburg
2005-09-22 16:58:00 UTC
Permalink
Post by Cory Bloyd
What happens when you modify a table while iterating over it?
I would expect the following iteration to proceed unaffected by the
modifications, but I¹m not certain...
for key, value in pairs(someTable) do
if someArbitraryCondition() then
someTable[key] = nil
end
end
This, I believe, is supposed to work but we ran into cases where we
suspected we were having issues if we did enough extra work. Unfortunately,
I don't think we ever had a simple example that was entirely reproducible.
The work around is to set the entries to be nil'd to some sentinel value and
then make another pass that clears those entries to nil and does nothing
else. But that being said, I'm pretty sure this is supposed to work as long
as you don't increase the set of keys in the table. If the table is weak in
some way, I guess it's possible that the GC could do some work that would
foul the iteration.
Post by Cory Bloyd
I would expect the following code to behave unpredictably regarding whether or
not the new items appear in the iteration.
for key, value in pairs(someTable) do
if someArbitraryCondition() then
someTable[newKey()] = newValue()
end
end
That's definitely a no-no if you want predictable iteration over even the
old keys let alone the new ones.

Mark
Philippe Lhoste
2005-09-23 07:09:41 UTC
Permalink
Post by Cory Bloyd
for key, value in pairs(someTable) do
if someArbitraryCondition() then
someTable[newKey()] = newValue()
end
end
If you are not short in memory, you can iterate on someTable and copy
existing keys and creating new keys in a new table. Then replace
someTable with newTable and you are safe.
--
Philippe Lhoste
-- (near) Paris -- France
-- http://Phi.Lho.free.fr
-- -- -- -- -- -- -- -- -- -- -- -- -- --
Loading...