• Subject: Re: Iteration problems: Not a weak table issue
• From: Tiago Dionizio <tngd81@...>
• Date: Wed, 1 Dec 2004 23:17:24 +0000

```On Wed, 01 Dec 2004 14:40:13 -0800, Mark Hamburg <mhamburg@adobe.com> wrote:
> Consider the following code snippet:
>
> t = { a = 1, b = 2, c = 3, d = 4, e = 5 }
>
> for k, v in pairs( t ) do
>     t[ k ] = nil
>     collectgarbage()
>     print( k, v )
> end
>
> It generates:
>
> a    1
> error: invalid key for `next'
>
> On the other hand, the following code:
>
> t = { a = 1, b = 2, c = 3, d = 4, e = 5 }
>
> for k, v in pairs( t ) do
>     collectgarbage()
>     print( k, v )
>     t[ k ] = nil
> end
>
> Produces:
>
> a    1
> c    3
> b    2
> e    5
> d    4
>
> I thought it was legal to assign nil to existing keys inside a loop. Are
> there further caveats that need to be observed in Lua 5.1?

>From the lua 5.0 manual:

C API,
"While traversing a table, do not call lua_tostring directly on a key,
unless you know that the key is actually a string. Recall that
lua_tostring changes the value at the given index; this confuses the
next call to lua_next."

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

I can only assume that changing keys of a table (in general) isn't a
safe operation when iterating it using the lua_next function.

A solution to iterate weak tables like in the example you provide this
should work:

\$ lua
Lua 5.0.2  Copyright (C) 1994-2003 Tecgraf, PUC-Rio
> function fst(t) return (function(t, key) key = next(t, key) return key, t[key] end), t, nil end
> t = { a = 1, b = 2, c = 3, d = 4, e = 5 }
> for k, v in fst(t) do t[k] = nil print(k, v) end
a       1
c       3
b       2
e       5
d       4
>

Tiago

```