lua-users home
lua-l archive

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


Hi,

Am 22.12.2010 20:28, schrieb Peter Cawley:
On Wed, Dec 22, 2010 at 7:26 PM, Ronald Lamprecht
<R.Lamprecht@t-online.de>  wrote:
Hi,

Am 22.12.2010 18:20, schrieb Peter Cawley:

On Wed, Dec 22, 2010 at 5:14 PM, Ronald Lamprecht
<R.Lamprecht@t-online.de>    wrote:

What is the favorite design of a dynamic method dispatcher, that allows
an
object to process arbitrary method calls on demand?

Due to the manual chapter 2.5.8 (funciton calls) a method call
v:name(...)
is syntactic sugar vor v.name(v,...). This allows you to implement a
static
method dispatcher by storing the various static method functions in the
metatable at their given method names.

But a dynamic method dispatcher is a single function that needs the
method
name as arguement when being called. It is easy to return the unique
dispatcher function on every call of v.name . But the method name can not
be
stored in the metatable of v because such method calls can be recursiv
and
the arguements of the first call are evaluated between evaluation of
v.name
and its related function call execution.

The most perfect solution would be if v:name(...) would be syntactic
sugar
vor v.name(v, name, ...). But I guess this would cause major trouble and
incompatibilities.

For a major Lua project (Enigma) I implemented a LIFO stack for the
called
method names. This works perfect in praxis as long as no one intervens
the
stack by executing v.name, storing its return value and calling it
multiple
times.

What alternativ implementation patterns are known and which are
recommended?

Use closures to remember the name of the method?

local v = {}
local make_dispatcher = setmetatable({}, {__mode = "k", __index =
function(t, k)
   t[k] = function(self, ...)
     return dispatch(self, k, ...)
   end
   return t[k]
end
})
setmetatable(v, {__index = function(t, k)
   return make_dispatcher[k]
end})

I did not mention that the objects are C++ objects that are accessible as
Lua userdata. Even the dispatcher is a C function.

Closures can just as easily be made in C:

int dispatcher(lua_State *L)
{
     /* Method name at lua_upvalueindex(1)
      Arguments at 1 through N */
}

int index_metamethod(lua_State *L)
{
     lua_pushcclosure(L, dispatcher, 1);
     return 1;
}

Thanks - this is a perfect solution :-)

Greets,

Ronald