lua-users home
lua-l archive

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


On Thu, Jul 24, 2008 at 5:47 PM, Luís Eduardo Jason Santos
<jasonsantos@gmail.com> wrote:
> Hi,
>
> Have anyone tried to determine, through a metatable, whether a given table
> key was called as a property or called as a method?
>
> Something like:
>
> t = setmetatable({}, my_mt)
> print(t.a)   -- one behaviour
> print(t.a()) -- another behaviour

The value returned from a table lookup doesn't depend on how you're
going to use it.  Really, how could it?  Your two code snippets are
morally equivalent to:

do local _temp = t.a; print(_temp); end
do local _temp = t.a; print(_temp()); end

By the time you reach the call to _temp(), the value of _temp has
already been set.

> I have tried some ways, but all I could muster was this little abomination:
>
> my_mt = {
>    __lastkey = nil,
>    __index = function(o, key)
>       getmetatable(o).__lastkey = key   -- o.__lastkey would probably be
> better, but still bad
>       return o
>    end;
>    __call = function(o, ...)
>       return myfunctions[getmetatable(o).__lastkey](...)
>    end;
>    __tostring = function(o)
>       return myfields[getmetatable(o).__lastkey]
>    end;
> }
>
> I know this smells really bad, but is there any good way of doing this?

Note this really doesn't work beyond your one example.  Your solution
breaks even when trying something as simple as print(t.a, t.b).  Of
course it doesn't work at all if you want to do anything with the
looked-up value other than printing it.

If the value of t.a is a table or userdata, you could arrange for its
__call metamethod to have the alternate behavior you want, but this is
probably a bad idea.  You'd be fighting against the way Lua
expressions work.  Depending on the context of what "t.a" is supposed
to mean, the resulting behavior of
foo = t.a
bar = foo()
is probably too surprising to make for a good interface.

Greg F