[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Random thought: lazy interning
- From: Rici Lake <lua@...>
- Date: Fri, 1 Jul 2005 23:46:52 -0500
Suppose that I have an immutable userdata type which I would like to be 
able to intern, but which I don't always want to intern. Something like 
bignums, perhaps: I'd like to intern them for efficiency, but I don't 
want to intern intermediate results which are going to disappear right 
away. In particular, if I'm going to use the objects as table keys, I 
really need to intern them so that the table lookup will work.
What would be necessary for Lua to help me do this? It occurs to me 
that it wouldn't require much. If I'm willing to handle the interning, 
in some manner (perhaps by constructing a canonical representation as a 
Lua string), then I only need to be "informed" when Lua is about to use 
the userdata as a table key. (I could handle equality myself in an __eq 
metamethod, possibly by interning both comparands and then doing object 
equality.)
For example: the settable operation currently calls the table's 
__newindex metamethod if the key is not present. But it could also call 
the *key*'s __newkey metamethod (if the key were a userdata and had a 
metatable with __newkey....)
So the settable loop might look something like:
function set(table, key, value)
  if rawget(table, key) ~= nil then
    return rawset(table, key, value)
  elseif type(key) == "userdata" then
    local func = getmeta(key, "__newkey")
    if func then
      local newkey = func(key)
      if newkey ~= key then
        if rawget(table, newkey) then
          return rawset(table, newkey, value)
      end
      key = newkey
    end
  end
  -- Now continue with the current algorithm:
  return internedset(table, key, value)
end
where internedset is the current algorithm:
function internedset(table, key, value)
  local meta = getmeta(table, "__newindex")
  if meta == nil then
    return rawset(table, key, value)
  elseif type(meta) == "table" then
    return internedset(meta, key, value)
  else
    return meta(table, key, value)
  end
end
---
I don't think this is much overhead. Is there anyone other than me who 
thinks it might be useful?
R.