lua-users home
lua-l archive

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


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