lua-users home
lua-l archive

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


> What I'd like to see is tables storing (internally & invisibly) an offset
to
> the first non-nil key. That way starting 'next()' from scratch each time
> will not be prohibitive.

That won't help as much as you think, though. It will solve that particular
problem, but it means that a[k] = nil could take an arbitrary amount of
time (in order to scan the table to update the pointer).

Short of adding zaptable() as an API (which would be easy and maybe a good
idea), I think the best way of solving this particular problem is to use a
proxy table:

This version uses a highly questionable interface in which proxy[nil]
gets/sets
the proxied table. This allows you to not use reserved table keys for
zapping
and iterating, although the code includes those keys. You could delete the
else
clauses from both the __index and __newindex methods and just use the
reserved
keys, or vice versa.

(untested code, sorry)

function ZappableTable(init)
  local self = {}
  local meta = {}
  init = init or {}
  function meta:__index(key)
    if key == nil then return init
    else return init[key]
    end
  end
  function meta:__newindex(key, val)
    if key ~= nil then init[key] = val
    else init = val or {}
    end
  end
  -- change these names if not appropriate for your application
  -- or if you don't like seeing __ all over the place.
  -- They are unnecessary if you use the highly questionable
  -- "nil key" interface
  function self:__zap(new)
    init = new or {}
  end
  function self:__next(key)
    return next(init, key)
  end
  -- This assumes you will not zap during an iteration
  function self:__pairs()
    return next, init
  end
  return setmetatable(init, meta)
end

-- functions to exploit the "nil" pseudokey:

function Zap(ztable, new)
  ztable[nil] = new
end

function ZapPairs(ztable)
  return next, ztable[nil]
end

function ZapNext(ztable, key)
  return next(ztable[nil], key)
end