nested metatables (again...)

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

nested metatables (again...)

Marc Balmer
I have C API question:

In a first metatable I set the __index field to a function that checks if the key is a number.  If it is, it returns some data value, nil otherwise.  Now I want to nest a second metatable, that has a table of functions at the __index field.

I don't seem to get that to work. The functions in the second metatable are never called. I am probably setting the metatable on the wrong field of the first metatable.  So on which field of the first metatable do I set the second metatable, on the metatable itseld, the __index field or the (C) function returning either a value or nil?

Do some C examples of such nesting exist anywhere?

Thanks,
Marc


Reply | Threaded
Open this post in threaded view
|

Re: nested metatables (again...)

Daurnimator
On 26 December 2015 at 21:20, Marc Balmer <[hidden email]> wrote:

> I have C API question:
>
> In a first metatable I set the __index field to a function that checks if the key is a number.  If it is, it returns some data value, nil otherwise.  Now I want to nest a second metatable, that has a table of functions at the __index field.
>
> I don't seem to get that to work. The functions in the second metatable are never called. I am probably setting the metatable on the wrong field of the first metatable.  So on which field of the first metatable do I set the second metatable, on the metatable itseld, the __index field or the (C) function returning either a value or nil?
>
> Do some C examples of such nesting exist anywhere?
>
> Thanks,
> Marc
>
>

What do you mean "second metatable"?
You cannot have two __index metamethods for a single object.
You *could* "chain" them though

via either just using a function:
setmetatable({}, {__index=function(t,k) local v = foo[k]; if v == nil
then v = bar[k] end return v end})

Or via a second table (with it's own metatable):
local foo = {}
local bar = {}
setmetatable(foo, {__index=bar})
setmetatable({}, {__index=foo})

Both should be straightforward to create via the C api.

Reply | Threaded
Open this post in threaded view
|

Re: nested metatables (again...)

Paco Zamora-Martínez
In reply to this post by Marc Balmer
If I had understood correctly the question, the problem you have is that Lua allow nesting metatables when the __index metamethods are tables. In your case, because the first metatable has a __index function, you cannot chain a second one by returning "nil" in your function. I think you need something like this to make work your approach (written in Lua instead of C, but you can translate it):

-- a table with functions (which would be your list
-- of functions at your second __index metamethod)
local index_table = { foo = function(self,...) do something end }

-- the metatable for your objects
local mt = {
  __index = function(t, k)
      if type(k) == "number" then return some value end
      return rawget(t,k) or index_table[k]
  end
}

local new_obj = setmetatable({}, mt)


On 26 December 2015 at 11:20, Marc Balmer <[hidden email]> wrote:
I have C API question:

In a first metatable I set the __index field to a function that checks if the key is a number.  If it is, it returns some data value, nil otherwise.  Now I want to nest a second metatable, that has a table of functions at the __index field.

I don't seem to get that to work. The functions in the second metatable are never called. I am probably setting the metatable on the wrong field of the first metatable.  So on which field of the first metatable do I set the second metatable, on the metatable itseld, the __index field or the (C) function returning either a value or nil?

Do some C examples of such nesting exist anywhere?

Thanks,
Marc