lua-users home
lua-l archive

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


OK, but keep your hands off of == !

Question: suppose you have a type with an equivalence relationship less
specific than identity. Can you use such an object as a table key? If so,
how? Do you think that Lua should try to find a canonicalise tagmethod as
well for such cases? (I'm just asking... *g*)

It's not 100% clear to me that it's appropriate to redefine < as a partial
ordering, but that's a question of style. One might want operators
available to express partial ordering (<· ·> ·=· suggest themselves) but I
guess that's inappropriate in the Lua context.

What I do (for what it's worth) is define my own pseudotagmethods. If you
define LE, for example, as a table whose keys are tags (or in 4.1 I guess
that would be types) and whose values are functions, and then set its
"function" ("call") tagmethod in the obvious way (see below), it becomes a
pseudotagmethod. LT, GE, EQV, and friends, can be regular functions which
call LE with the formulas you've indicated, or they can also be
pseudotagmethods which is a bit quicker but a bit more work. One nice thing
about tables with functional values is that you can use the index tag
method to establish a default. So you could define LE as a table with the
following tagmethods (in 4.0):

-- warning: there may be typos in this code. But the concepts work, honest

do -- pseudotagmethod LE
  local LEtag = newtag()
  settagmethod(LEtag, "index", function(t, k) return function(a, b) return
a <= b end end)
     -- default is <=
  settagmethod(LEtag, "function", function(t, a, b) return t[tag[a]](a, b)
end)
     -- look it up in the table, and use the default if it's not there
  LE = settag({}, LEtag)
end

This is obviously not as fast as it would be if it were built into the
language (and it requires functional instead of operator notation), but
it's a very general solution and it's surprisingly quick. I doubt whether
it is much slower than having Lua internally check for two different tag
methods and then call one or the other of them.

You can then define a pseudotagmethod by simply assigning into LE:
LE[setTag] =
  function(a, b)
     -- might want to verify that b is a set :-)
     for k, _ in a do
        if not %b[k] then return nil end
     end
     return "leq"
  end

I used to redefine settagmethod to handle pseudotagmethods, in case they
someday got built in to the language, but since settagmethod is about to
disappear, there's not much point. 4.1 makes this sort of thing somewhat
easier, but different, and possibly not quite as fast since afaics you need
an explicit test for non-existence of the pseudotagmethod, rather than the
rapid test built-in to the "index" tagmethod.

R.


Oxfam works with others to find lasting solutions to poverty and suffering.

Oxfam GB is a member of Oxfam International, a company limited by guarantee and registered in England No. 612172.
Registered office: 274 Banbury Road, Oxford OX2 7DZ.
Registered charity No. 202918.

Visit the web site at http://www.oxfam.org.uk