lua-users home
lua-l archive

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


You make the point:

"the arguments of the `__index` call might not be the top level object depending on how deep the chain is"

Which rules define the top level object?

In the example send by Daurnimator, the __index in the first level is receiving the caller object. So, in case of a second level of indirection, it will receive the previous level metatable? So, given whatever a object, its metatable b, and metatable of metatable c, the __index of b will receive a, and the __index of c will receive b as argument.


2014-10-20 20:24 GMT+02:00 Philipp Janda <siffiejoe@gmx.net>:
Am 20.10.2014 um 11:42 schröbte Paco Zamora Martínez:
Dear Lua community,

Hi!


In order to make it clearer, I have written two minimal examples where this
behavior is present:

*setmetatable(getmetatable(metainstance.__index).__index, {*
*       __index = {*
* baz = function(self) return self.v end,*
*       },*
*})*

*setmetatable(getmetatable(metainstance.__index).__index, {*
*       __index = function(self,key)*
* if key == "baz" then return rawget(self,v) end*
*       end,*
*})*

Those two are not equivalent! The second one should be something like

    setmetatable(getmetatable(metainstance.__index).__index, {
      __index = function(self,key)
        if key == "baz" then
          return function(self)
            return rawget(self,"v")
          end
        end
      end,
    })

and then you get your expected output of:

> 5
> 5
> 5

A method call using `:` consists of two operations: The fetching of the function and the function call. The `self` argument of the function call will always be the top level object, but the arguments of the `__index` call might not be the top level object depending on how deep the chain is.
So when you try to combine fetching and calling, you can end up with the wrong `self`.

Philipp







--
Pako ZM :)
http://cafre.dsic.upv.es:8080/~pako/