lua-users home
lua-l archive

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


Hi, I've not used Lua for some time (due to bad health, workload and other problems).

tl:dr
-----
if I call f.abc() where .abc does not exist,
create an f.abc subtable in the __index metamethod
and assign a __call metamethod to f.abc,
is the f.abc() call guaranteed to work?


In detail (see attached code)
-----------------------------
In restructuring an ancient program of mine, I'd like:

  f.abc(...)

where 'abc' does not exist,
to have the effect of calling:

  g("abc", ...)

I did my homework and found a solution (see attached simplified code).

Basically, I create the f.abc subtable in the __index metamethod for f
(nothing strange here) then, while still in the __index metamethod, I attach to the newly created f.abc a metatable with a __call metamethod.

Note that all this happens in the middle of a pending call of a non-existing f.abc() 'function', which is akin to changing the engine of a running car.

It seems to work fine (I tried it in Lua 5.4.0) confirming my impression that Lua very often effortlessly does 'the right thing', but I'm not entirely sure it is 'legal'.

So I have two questions:

1) Can I rely on it even in the future, on other platforms, etc.?
2) Is there a simpler way?

--
  Enrico
--this is the function that should be called
function g(k, ...)
    --[function body here]
    print(k, ...)
end

-- pseudo-function table
f = {}

setmetatable(f, {
    --f.k is called, but it does not exist
    __index = function(t, k)
        --create k subtable
        t.k = {}
        --make it callable
        setmetatable(t.k, {
            __call = function(f, ...) 
                        g(k, ...)
                     end}
            )
            --the pending f.k()  __call fires
            return t.k
            end, --(__index of f)
    }
)

--test:
f.abc("Lua", "is very well designed")
---> abc     Lua     is very well designed