lua-users home
lua-l archive

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


On Mar 21, 2010, at 10:29 AM, Christopher Eykamp wrote:

> 
> On 3/20/2010 10:44 PM, Mark Hamburg wrote:
>> See the specification for the __mul operator in the Lua spec (section 2.8).
>> 
>> The implementation of the * operator looks in the metatable for a __mul entry. It does not perform a message send. It does not index the object. Once it finds the entry, it passes it the two operands. In other words, it does more or less exactly this:
>> 
>> 	local temp = bot:getLoc()
>> 	newpt = getmetatable(temp).__mul(temp, 2)
>>   
> 
> With the exception of storing the intermediate in temp, isn't that pretty much the same as:
> 
> newpt = getmetatable(bot:getLoc()).__mul(bot:getLoc(), 2)
> 
> This works, but the * operator does not, so they are not doing quite exactly the same thing :-)
> 
> BTW, I cannot test using temp as an intermediate as shortly after I posted, my graphics card blew up, and my dev machine is now out of service until I get it fixed :-(
> 
> Thanks for your help,

Here is my minimal example of using * and the __mul metamethod:

> obj = setmetatable( { }, { __mul = function( x, y ) print( x, y ); return y end } )
> print( obj * 2 )
table: 0x100108880	2
2

I haven't looked at how Lunar builds objects. Maybe it sticks the methods in the metatable and has the metatable point back to itself via the __index entry. Barring that, in your original message which stated that this works:

	bot:getLoc():__mul(2)

I would make no assumptions about operator * working since the message send in the above looks for __mul in a different location from operator *. This would result in the "attempt to perform arithmetic on a userdata value" error you reported.

I would definitely not expect the following to work:

	getmetatable(bot:getLoc()):__mul(2)

Because this will pass the metatable as the first argument to the __mul function if it finds it which would be why it complains about receiving a table instead of a point.

On the other hand, if the following does work (note the use of . rather than : and getting the first parameter right):

	getmetatable(bot:getLoc()).__mul(bot:getLoc(), 2)

Then I would expect the system to be able to find the __mul entry when performing an operator*.  The one tricky bit here v operator * is that you invoke bot:getLoc() twice and you don't pass the expected first parameter to the __mul metamethod.

So, I believe I can entirely explain your initial report based purely on the diagnosis that __mul has been created as a method on the object rather than as an entry in the metatable. Your report that the last construct actually works would suggest that something more subtle was going on in bot:getLoc().

Mark