[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Lua 5.1.1 and the __concat metamethod
- From: "Paul.Winwood" <paul.winwood@...>
- Date: Tue, 26 Dec 2006 10:08:36 +0000
Timon Christl wrote:
Use the Source, Luke! When looking into the Lua source code, you can
find these lines in luaV_concat(), which is the function that
implements the concat operator:
if (!tostring(L, top-2) || !tostring(L, top-1)) {
if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
I had already fixed the problem in my local copy of Lua 5.1.1; here is
the patch. I was more interested if this was a bug (because the code
implemented is different to the manual) or a defect in the manual (the
add metamethod describes how concat works).
284c283,284
< if (!tostring(L, top-2) || !tostring(L, top-1)) {
---
> if (!(ttisnumber(top-2) || ttisstring(top-2)) ||
> !(ttisnumber(top-1) || ttisstring(top-1))) {
287c287,288
< } else if (tsvalue(top-1)->len > 0) { /* if len=0, do nothing */
---
> } else if (tostring(L, top-2), tostring(L, top-1),
> tsvalue(top-1)->len > 0) { /* if len=0, do nothing */
This first tries to convert at least one of the two topmost stack
values into a string, and only if this fails it will try to call the
metamethod of one of the two values. tostring() is a macro that
evaluates to true in one of two cases: when the value really is a
string, or when a call to luaV_tostring() returns true. And this
function is where the problem lies. If it is called with a number
value as argument, it will silently replace the value with a value of
type string that contains the string representation of the number.
This behaviour is indeed documented, but only for the C API function
lua_tostring(), not in the section about metamethods.
I would not really call this a bug. But I think it is a weakness in
the design of how Lua's metamethods work, and definitely a case of
incomplete documentation.
Workaround: You might try to parse the string in your concat
implementation to see if it can be converted back to a number. Yes
this means two unnecessary conversions, but this shouldn't be a speed
problem. Or, you shouldn't be using a scripting language for this if
it is.
Not really useful to me as a workaround, there is no way of determining
if a string or a number was being concatenated, or if I have to check to
see if a string parameter looks like a number or not.
Another possibility would be to replace the concat operator with a
function. It would not be as pretty, but it would work, since
arguments for functions do not suffer from the same problem. So
instead of x=n..ud you would write something like x=myconcat(n,ud).
And theoretically it should save a few CPU cycles :-)
One of the criticisms raised on this list with wxLua (I am one of the
original authors) was that the wxLua interface was insufficiently
Lua-like, so in the new interface I have been working on I have been
attempting to make it more so. Adding a myconcat function seems like a
regression to me.