lua-users home
lua-l archive

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


In Penlight's `operator.lua` we see:

```
--- concatenate two values (either strings or `__concat` defined) **..**
-- @param a value
-- @param b value
function  operator.concat(a,b)
    return a..b
end
```

With LUA_NOCVTN2S disabled, this means that a metamethod must be
added, or user code must tostring numbers in the function arguments,
or, somewhere in ye_olde_shim_file.lua:

```
do local type, tostring = type, tostring
local n2s = pcall(function () return 1 .. "2" end)

if not n2s then
  local mt = debug.getmetatable(0) or {}
  mt.__concat = function(a,b)
    if type(a) == 'number' then
      return tostring(a) .. b
    else
      return a .. tostring(b)
    end
  end
  debug.setmetatable(0, mt)
end
```
Perfomance Question:
I'm not *that* concerned about concatenation performance, but I am
curious to know if the presence of a metatable slows Lua down for all
numbers, or not. I figured that someone here might know that off of
the top of their head and save me some bench marking time effort, in
the case that it does not.


Failures:

My first attempt, which i suspected was wrong, was `return tostring(a)
.. b`. This did not work in the case where you had something like
`'foo' .. 42`, where it would blow the stack.

my next attempt was `return tostring(a) .. (type(b) == 'number' and
tostring(b) or b)` but this was wrong for the opposite case (although
it would not fail). The above works in all cases that I can find,
including this one:

```
print(12 .. 345)
--> "12345"
```
When I saw this, I remembered that `a` is converted and then a second
__concat event is raised on b, and so that's why it works. If someone
has a simpler or faster version (other than making type and tostring
local values, which I've done), I'd love to hear it.

Observation in the context of N2S, not normal Lua:

I have read and I believe that I have a reasonable grasp on why
`tostring`  is not called, when no `__concat` method is found: It
doesn't make sense for an event to have a fallback to an unrelated
event, if it isn't found.

As I see it, concatenation works on strings. Its event method is
available for abuse by userland metatables, or perhaps to format an
object's string representation differently, by other value types, if
they define it. Otherwise, the value is converted to a string and then
concatenated.

Now, I know that I'm talking out of both ends, not wanting coercion in
one spot and wanting it in the other. The problem is that numbers
don't have a metatable, unless you mess with debug.setmetatable. So
making them concat correctly requires you to wrap it in `tostring`,
whereas you wouldn't have to, if it were a table.

Here, I that I wish that concat would use tostring on all non-string
value types that do not have metamethods, instead of erroring. At the
same time, dropping support for `__concat` would seem reasonable.





-Andrew