lua-users home
lua-l archive

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


> On Feb 20, 2017, at 11:39 PM, Dirk Laurie <dirk.laurie@gmail.com> wrote:
> 
> 2017-02-21 9:26 GMT+02:00 Tim Hill <drtimhill@gmail.com>:
> 
>> If I understand the OP correctly, he is saying that __add() will
>> accept a callable, so why not __call()? I haven’t tested this but
>> *if* he is correct, then that appears to differ from the Lua reference
>> 2.4 that says "Note that queries for metamethods are always raw;
>> the access to a metamethod does not invoke other metamethods.”
>> So either he is wrong, the Lua ref manual is wrong, or the Lua code
>> is wrong (I’m not taking bets here!).
> 
> A fourth possibility is that you do not understand what the manual
> means by "the access to a metamethod does not invoke other
> metamethods.”
> 
> I take it to mean that if a metatable itself has metamethods, they (and
> in particular another level of _index) will not be invoked when
> determining whether a particular metamethod is available.
> 

A fifth possibility is I quoted the wrong part of the ref manual. Perhaps (also in 2.4): "For instance, when a non-numeric value is the operand of an addition, Lua checks for a function in the field "__add" of the value's metatable. If it finds one, Lua calls this function to perform the addition.”

Ignoring the phrase “for instance” here, this _appears_ to suggest that a metamethod is assumed to be a function, not a callable. (I cannot find anything in the ref manual that specifies what Lua does should the value not be a function or a callable.) In addition, the fact that __index and __newindex are called out as special cases that can be “either a function or a table” suggests that in the non-special cases the metamethod is assumed to be a function.

As the OP noted, this code does indeed appear to work:

mmt = { __call = function(t, a, b) return a.x + b.x end }
tadd = setmetatable({}, mmt)
mt = { __add = tadd }
t1 = setmetatable({ x = 10 }, mt)
t2 = setmetatable({ x = 20 }, mt)

print(tadd(t1, t2))
print(t1 + t2)


My understanding is the OP noted that __call, unlike __add, does *not* accept a callable, but the ref manual doesn’t explain this.

—Tim