lua-users home
lua-l archive

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

Personally, I don't think you can justify the increased complexity (and reduced performance) of having the VM check for a __tonumber metamethod every time a number is needed. However, adding the capability for use by tonumber() explicitly could be warranted.

Matthew P. Del Buono
Sent from my Verizon Wireless BlackBerry

-----Original Message-----
From: Doug Rogers <>

Date: Thu, 05 Feb 2009 10:13:55 
To: Lua list<>
Subject: __tonumber metamethod (was Re: Exposure of nil to end-users)

Michal Kolodziejczyk wrote:
> I am also missing __tonumber metamethod...

It seems like this could be a useful feature, but if it were to behave 
like __tostring it would be of limited value - limited to programmers 
calling tonumber() explicitly.

Note that although the __tostring metamethod exists, it is *not* used by 
the VM when it decides that it needs a string value. It is used only by 
the Lua base library function tostring(). And the only time tostring() 
is called (other than when the developer puts tostring() in his Lua 
code) is in the base library implementation of print().

The VM supports coercion to number and string to a limited extent, but 
only between those two types because it is simple and relatively fast to 
do so.

If you were to do a similar thing for tonumber(), it would never get 
used by the Lua internals. Attached is a two-line patch to lbaselib.c 
that makes tonumber() behave just like tostring(), honoring a __tonumber 
metamethod (without the optional numeric base). This allows the following:

   print(t, tonumber(t))    -- table: 0x807e060	nil
   mt.__tostring = table.concat
   mt.__tonumber = function (self) return self[1] or 0 end
   setmetatable(t, mt)
   print(t, tonumber(t))    --	0
   t[2]=" is perfect"
   print(t, tonumber(t))    -- 6 is perfect	6
   print(tonumber(t) + 8)   -- 14

But this is of limited value since, unlike tostring(), there is no place 
that Lua uses tonumber() itself. Still, it might be of value when the 
programmer uses tonumber() explicitly.

For example, I think you're looking for this sort of use case (error 
messages truncated):

   for k = t, 10 do print(k) end
   --  stdin:1: 'for' initial value must be a number
   print(t + 8)
   --  stdin:1: attempt to perform arithmetic on global 't'

Adding support for that kind of thing would have to be done in a way 
that resolves the ambiguities that will arise between them and the 
operator metamethods (perhaps by a precedence rule, reducing further the 
simplicity that is Lua).

For example, the easiest way to provide such support would be to modify 
luaV_tonumber() so that it calls the __tonumber metamethod if it exists 
(relying on the string table's __tonumber metamethod to achieve its 
current behavior). This would allow each of the erroneous examples above 
to work (untested).

Developers would then have to decide whether their objects should define 
__tonumber or the operator metamethods, since the former would cause the 
latter to be performed as normal lua_Number operations. I can think of 
examples where a developer would choose the former (defining 
__tonumber), say for a bank account object whose balance would be 
returned. But for most use cases I would imagine a developer choosing to 
redefine the binary operators instead.

Other ways are more complicated. If you have an idea, give it a spin.

Personally, I don't think it is worth the complexity. __tostring is 
useful for print() and possibly for serialization of objects, but I 
don't see the same usefulness for __tonumber.


The information contained in this email transmission may contain proprietary and business 
sensitive information.  If you are not the intended recipient, you are hereby notified that 
any review, dissemination, distribution or duplication of this communication is strictly 
prohibited.  Unauthorized interception of this e-mail is a violation of law.  If you are not 
the intended recipient, please contact the sender by reply email and immediately destroy all 
copies of the original message.

Any technical data and/or information provided with or in this email may be subject to U.S. 
export controls law.  Export, diversion or disclosure contrary to U.S. law is prohibited.  
Such technical data or information is not to be exported from the U.S. or given to any foreign
person in the U.S. without prior written authorization of Elbit Systems of America and the 
appropriate U.S. Government agency.