lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


on 12/1/04 3:17 PM, Tiago Dionizio at tngd81@gmail.com wrote:

> 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."

Note that I am not calling lua_tostring on the key. In the example I cited,
the keys are already strings.

> 
> 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."

The fields I'm assigning to existed at the point of assignment. This isn't a
weak table. They cease to exist after the assignment but that isn't what the
manual is warning about.

> 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

I think you just defined pairs since I believe that

    function( t, key )
        key = next( t, key )
        return key, t[ key ]
    end

Is equivalent to next. ("next returns the next index of the table and the
value associated with the index.")

Furthermore, in Lua 5.1 if you take your loop and insert a call to
collectgarbage after the assignment, the loop will error out.

Mark