lua-users home
lua-l archive

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


"John Belmonte" <jvb@prairienet.org> writes:

> Jay Carlson wrote:
>
> > Look, I haven't made up my mind yet about unified methods.  They
> > offer a lot of nice features that seem useful in day-to-day
> > programming.  But it's a significant enough change that I need to
> > think about it, a lot---because it *is* an interesting and thoughtful
> > proposal.
>
> Actually unified methods doesn't offer many features at all.  It's just
> taking Lua's internal tag method system an exposing it as tables (this is
> why Edgar was shocked by your comment about everything-as-tables).  Lua's
> tag method interface is spotty and hard to follow, so unified methods just
> make you think you're getting a whole lot more.  It's an illusion.

Although this post has been overtaken by events, I thought it might be cool
to do this in base Lua 4.0.  Another hour of my life wasted by tag
methods---help help it's SO MUCH FUN TO WRITE THIS STUFF

Jay

---------------------

dofile("tag.lua")

hellotag = Tag.new()

function hellotag.gettable(table, index)
  return "Hello from "..tostring(index)
end

print("hellotag.gettable", hellotag.gettable)

-- had to rename this event from "function" to "func"...
function hellotag.func(...)
  print("hello, world!")
end

hello = {}
hellotag:applyTo(hello)

hello()
print("hello.Jay", hello.Jay)

-- You can get a Tag from any value you're got lying around:

hellotag2 = Tag.fromValue(hello)
print("hellotag == hellotag2", hellotag == hellotag2)

-- Or for existing types:

numtag = Tag.fromValue(1)
numtag2 = Tag.fromValue(2)
print("numtag == numtag2", numtag == numtag2)

----------------------------------------------------------------------

-- tag.lua

if Tag then return end

local Public, Private = {}, {}
Tag = Public

Private.tagtag = newtag()

Private.tagnum_to_Tag = {}

function Public.new()
  local tagnum = newtag()
  local t = {tag=tagnum}
  settag(t, %Private.tagtag)
  %Private.tagnum_to_Tag[tagnum]=t
  return t
end

function Private.makeOld(tagnum)
  local t = {tag=tagnum}
  settag(t, %Private.tagtag)
  %Private.tagnum_to_Tag[tagnum]=t
  return t
end

function Public.fromTagNumber(n)
  local tag = %Private.tagnum_to_Tag[n]
  if not tag then
    tag = %Private.makeOld(n)
  end
  return tag
end

function Public.fromValue(v)
  local tagnum = tag(v)
  return %Public.fromTagNumber(tagnum)
end

Private.event_set = {
  add="add", sub="sub", mul="mul", div="div", pow="pow",
  umm="umm",
  lt="lt",
  concat="concat",
  index="index",
  getglobal="getglobal", setglobal="setglobal",
  gettable="gettable", settable="settable",
  func="function" -- because you can't say foo.function = bar
}

function Private:applyTo_method(v)
  settag(v, self.tag)
end

Private.method_table = {applyTo=Private.applyTo_method}

function Private.gettable_handler(table, index)
  local method = %Private.method_table[index]
  if method then return method end
  local event = %Private.event_set[index]
  if event then
    return gettagmethod(rawget(table, "tag"), event)
  else
    return rawget(table, index)
  end
end

function Private.settable_handler(table, index, value)
  local event = %Private.event_set[index]
  if event then
    settagmethod(rawget(table, "tag"), event, value)
  else
    rawset(table, index, value)
  end
end

settagmethod(Private.tagtag, "gettable", Private.gettable_handler)
settagmethod(Private.tagtag, "settable", Private.settable_handler)

function Public:copyMethodsFrom(tag)
  for i,v in %Private.event_set do
    settagmethod(self.tag, v, tag[v])
  end
end