lua-users home
lua-l archive

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


On Sun, Oct 30, 2011 at 7:36 PM, Mark Hamburg <mark@grubmah.com> wrote:
> If one is going to play those sort of games, I would think -- not enough coffee yet to write -- that one could define functions to let one do the following:

Slightly different notation, same idea:

t = this.Expand {
   x = 1.0,
   t = {
      c = this.y
   },
   y = this.x;
   z = this.t.c
}

That is, 'this' is a general reference to the table  The basic trick
is to define reference objects which basically are a chain of field
references.

-- expand.lua
local xmt = {}
this = setmetatable({},xmt)

local function is_fieldref (v)
   return getmetatable(v) == xmt
end

local expand_fieldref, Expand

function xmt.__index (self,key)
   if self == this then
      if key == 'Expand' then return Expand end
      self = setmetatable({},xmt)
   end
   self[#self+1] = key
   return self
end

function expand_fieldref (root,keys)
   local v = root
   for _,k in ipairs(keys) do
      v = v[k]
   end
   if is_fieldref(v) then
      v = expand_fieldref (root,v)
   end
   return v
end

function Expand (t,root)
   root = root or t
   for k,v in pairs(t) do
      if type(v) == 'table' then
         if is_fieldref(v) then
            t[k] = expand_fieldref(root,v)
         else
            Expand(v,root)
         end
      end
   end
   return t
end

(I put 'Expand' into 'this' just to keep things tidy)

The next step would be having references like this.x + 1, which is
perfectly possible (builds up little expression trees which are
evaluated later) but somewhat tedious to code. There are also some
gotchas with relational operators and function applications.

steve d.