lua-users home
lua-l archive

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


Yes, I'm wondering why this was the case.

I faced this problem designing one piece of code where a nested __index function, in the fashion I was thinking, can solve it. I know that it is possible to obtain the desired behavior just making the metatable __index function in the constructor of the instance and taking the instance object as upvalue of the __index function, but this solution doesn't fit with the rest of my code :(

So, I realize that it is not possible to do as I want, and the question of "why" comes to my head, it seems a simple feature. But as you said, probably is a mix of different things like between performance, design, etc. and simple features can become monsters when considering the whole picture ;-)

Thinking about the problem, comes to my head the reason for the lack of operator [] in Lua strings. IMO, it is related with the same problem I'm facing here.

2014-10-20 18:25 GMT+02:00 Andrew Starks <andrew.starks@trms.com>:


On Mon, Oct 20, 2014 at 6:27 AM, Paco Zamora Martínez <pakozm@gmail.com> wrote:
Thanks Dirk, but rawget(self,self.v) didn't solve the problem because "self" is not the table "o", so, field v doesn't exist in self table. The key is correct, "baz", but the given self table is not table "o" instance.

The problem here is that __index function is not getting "o" table while __index table functions are... I'm curious about if that is an intentional behavior and why. IMHO, it is surprising that both approaches are not producing the same result.

2014-10-20 12:26 GMT+02:00 Dirk Laurie <dirk.laurie@gmail.com>:
2014-10-20 11:42 GMT+02:00 Paco Zamora Martínez <pakozm@gmail.com>:

> local metainstance = {
>   __index = {
>     foo = function(self) return self.v end,
>   },
> }
> setmetatable(metainstance.__index, {
>       __index = {
> bar = 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,
> })
> local class = {
>   new = function(v) local t = {v=v} setmetatable(t, metainstance) return t
> end,
> }
> local o = class.new(5)
> print( o:foo() )
> print( o:bar() )
> print( o:baz() )
>
> The output of this code is:
>
> 5
> 5
> lua: min.lua:24: attempt to call method 'baz' (a nil value)
> stack traceback:
> min.lua:24: in main chunk
> [C]: in ?
>
> because the nested __index function receives as argument a table which is
> not the caller o table, and the rawget(self,v) function returns nil

o:baz() ->
o.baz(o) ->
o["baz"](o) ->
getmetatable(o).__index"baz"(o) ->
rawget(o,nil) ->
nil

Maybe make that rawget(self,self.v)?



--


I believe that the reasoning includes a mix of performance, avoiding reference loops and design.

It maybe helpful to view the table variation as a shortcut that is suitable for the most simple use cases. It may also be helpful to consider that Lua doesn't have a formal object model as much as it has mechanisms to implement object models. That is to say, if Lua had feelings: It might be sympathetic to your requirements but it doesn't view them as uniquely relevant.

Besides the speed of a raw lookup, there is the consequence of making long chains of table lookups too easy. Stack traces in Ruby are illustrative of this consequence (although I admit that I know next to nothing about Ruby).

By the way you asked your question, I didn't get the sense that you were seeking alternative approaches, so much as wondering why this was the case. Is that correct?

-Andrew




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