lua-users home
lua-l archive

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


Hi,

> What if you want
> to iterate through both the real and inherited keys in Child without
> regard to if they were in Child or Parent (or a parent of Parent, etc.)?
>
> Does anyone have an elegant way to deal with this?

Elegant I don't know, but the following works:

--8<--snip--snip--8<--snip--snip--8<--

function rnext(state, key)
    local table = state.table
    local value

    repeat
        key, value = next(table, key)

        if not key then
            local mt = getmetatable(table)
            local mi = mt and mt.__index
            if not mi or type(mi) ~= "table" then
                return nil, nil
            end
            state.table = mi
            table = mi
        end
    until key and not state.keys[key]

    state.keys[key] = true
    return key, value
end

function rpairs(table)
    return rnext, {table = table, keys = {}}, nil
end

-- test it!
local a = {x=1, y=2, z=5}
local b = {}
local c = {x=6, z=7, w=15}
setmetatable(b, {__index=a})
setmetatable(c, {__index=b})

for k, v in rpairs(c) do
    print(k, v)
end

--8<--snip--snip--8<--snip--snip--8<--

Note that this only works if __index is an actual table, not a function.  If
something similar must work for __index functions as well, then I think we
really _do_ need an additional __next metafunction that enumerates all
key/value pairs that can be accessed through this function.  (Wait, that
needs a state, so maybe __pairs is indeed better.)  How could rpairs be
implemented in this case?

Bye,
Wim