lua-users home
lua-l archive

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


On Tue, Apr 15, 2014 at 4:07 PM, Andrew Starks <andrew.starks@trms.com> wrote:
> I've run into this frequently enough to remember that I've run into it
> before, but not frequently enough to relegate it to an automatic
> pattern...
>
> The scenario is that I have an object that has defined methods in a
> template (table). Typically, I'd define the index so that it pointed
> to a table of methods:
>
> setmetatable(obj, {__index = My_Class_Table})
>
> However, I'm dealing with something along the lines of xpath and would
> like to allow the user to "walk" any index path and as a final action,
> call the remote method, which is the last element. This requires a
> more sophisticated __index metamethod that returns a table if there is
> nothing found in the class table. This table is adorned with a the
> same metatable as the object itself, where, when called, stashes the
> command away and walks backwards to the main object..... you know...
> code is better:
>
> ```lua
> local Template = {}
> local path_mt = {}
>
> local function path_walk (self, command, ...)
>   if rawget(self, "__parent") == nil then
>     return self:handlers(command, ...)
>   else
>     return path_walk(self.__parent, command, self.name, ...)
>   end
> end
>
>
> --> *****Subject of this email: (t, self)***** <--
>
> local function path_call (t, self, ...)
>   if self.__parent then
>     return path_walk(self.__parent, self.name, ... )
>   else
>     error("Attempt to call remote object '%s' without a command
> specified." % {self.name})
>   end
> end
>
> local function path_index(self, i)
>   if Template[i] then
>     return Template[i]
>   else
>     self.path[i] = setmetatable({name = i, __parent = self, path = {}}, path_mt)
>     return self.path[i]
>   end
> end
>
>
> path_mt.__index = path_index
> path_mt.__call = path_call
>
>
>
> function Template:method_a (args)
>   --stuff
> end
> function Template:method_b(args)
>   --more stuff
> end
>
> local make_new_object = function(args)
>    local self = {}
>
>    ---do stuff to initialize self.
>
>   setmetatable(self, path_mt)
>   return self
>
> end
> ```
>
> I don't have any ideas here or suggestions or criticisms or
> proposals... The issue is that when I'm calling native methods, I'm
> using the "object:method(arguments)" syntax and this does not work
> well when mixed with the way that call works.
>
> I think I prefer the "consistency" of always including the table as
> the first argument ("t") in the __call metamethod, where consistency
> is defined as "relative to the other metamethods." Also, I rarely mix
> the colon syntax and what I've got going on here.
>
> But, when I can't figure out why I'm getting two copies of self: one
> foisted upon me by Lua and one because I called the function with a
> colon, I can't help but feel like I created a clash between two
> different ways to use Lua that should not be mixed.
>
> I throw this out there, in case anyone else had an insight or a
> comment on this... anti-pattern?
>
> Thanks for the therapy. :)
>
>
> -Andrew


I take most of this back.... Upon further inspection, "t" is the
current table being called  and when called with a colon, I'm getting
the parent table. This is actually pretty awesome and useful.

Sorry for the noise. Maybe someone, someday will be a bit confused,
will happen upon this and be somewhat enlightened by it.

The parent post contained errors in path_call. The fixed version is:

```lua

local function path_call (self, parent, ...)
  if rawget(self, "__parent") then
    --check for colon syntax and adjust as required.
    if self.__parent == parent then
      return path_walk(self.__parent, self.name, ... )
    else
      return path_walk(self.__parent, self.name, parent, ...)
    end
  else
    error("Attempt to call remote object '%s' without a command
specified." % {self.name})
  end
end

```

--Andrew