[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: rethinking method calls with __mcall metamethod rather than __index/__call
- From: David Manura <dm.lua@...>
- Date: Sat, 13 Jun 2009 19:09:17 -0400
On Sat, Jun 13, 2009 at 5:04 PM, Mark Hamburg wrote:
> It also allows for mixing efficient method inheritance
> with property accessors because __mcall could lead to a table of methods
> while __index could lead to a function that did the property accessor logic.
Which according to [1], I gather you mean
mt.__mcall = methods -- remains fast
function mt.__index(t, k) -- slower
local p = properties[k]
if p then return p(t, k) end
error("Unknown property: " .. tostring(k))
end
> The semantics of __mcall would be something like the following (which
> essentially corresponds to the self opcode):
>
> function mcallprep( t, k )
> local mt = getmetatable( t )
> local mcall = mt and mt.__mcall
> if mcall then
> if type( mcall ) == 'table' then
> return mcall[ k ], t
> else
> local f, o = mcall( t, k )
> return f, o
> end
> end
> return t[ k ], t -- Uses standard lookup
> end
The "set" example above, in which __mcall will be a table, can be well
represented that way:
-- Simple Set ADT
local mt = {}
local methods = {}
function methods:union(set2)
for k in pairs(set2) do self[k] = true end
end
mt.__mcall = methods
function set(t)
local self = setmetatable({}, mt)
for _,v in ipairs(t) do self[v] = true end
return self
end
-- note: optionally share mt and methods in same table,
-- which as a side-effect exposes __mcall as a method.
However, the proxy example, in which __mcall will be a function,
involves a temporary closure again, and we prefer to be able to omit
the "o" value above too:
-- Proxy
local mt = {}
function mt:__mcall(k)
local priv = self[1]
return priv:[k] -- note: omit ",o"
end
function mt:__index(k)
local priv = self[1]
return priv[k]
end
function proxy(o)
return setmetatable({o}, mt)
end
The awkwardness lies in that "local f, o = mcall( t, k )" deconstructs
the method in terms of a function and its first argument, but the
proxy doesn't necessary have access to the original f, which as you
noted is no longer loose.
> Finally, one could argue that adding this feature essentially necessitates
> method currying...
i.e. [2]
Also, in [3] you wrote:
> Finally, it would be good to have a fast way to test for method
> support. These changes would essentially force the use of obj:msg
> for any object using the new __self metamethod, but since that
> actually constructs a closure, it's overkill if all we want is a boolean.
True, but in similar fashion neither do we have an efficient way to
test for operator support (e.g. call operator) [4]. Indexing was an
incomplete solution for that anyway. We might write obj:__call or
obj:["()"] to obtain a closure (or nil) for the call operation.
[1] http://lua-users.org/lists/lua-l/2006-04/msg00527.html
[2] http://lua-users.org/wiki/MethodCurry
[3] http://lua-users.org/lists/lua-l/2009-01/msg00612.html
[4] http://lua-users.org/lists/lua-l/2009-05/msg00479.html