[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Awkward enough to comment: __call(t, ...) and self
- From: Andrew Starks <andrew.starks@...>
- Date: Tue, 15 Apr 2014 16:25:15 -0500
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