lua-users home
lua-l archive

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

On 2012-06-27 11:16, Dirk Laurie wrote:
The manual says:

table.concat (table [, sep [, i [, j]]])
Given an array where all elements are strings or numbers, returns
      table[i]..sep..table[i+1] ··· sep..table[j].
It says nothing about what happens with elements of other types.
Can one make them work with the aid of metamethods?  Let's try.

         function Concat(x,y) return tostring(x)..tostring(y) end
         debug.setmetatable(false,{__concat = Concat})
     stdin:1: invalid value (boolean) at index 1 in table for 'concat'

So the standard implementation does not use metamethods.  A glance
at `ltablib.c` confirms that `addfield` is used, a function with no
other task in the 5.2.1 source code.

It is not hard to patch `ltablib.c` to use `lua_concat` instead.
If no metatables are supplied, the behaviour of `table.concat` is
still the same, except that the error message changes to

     attempt to concatenate a boolean value

However, assigning just this one metamethod:

         getmetatable"".__concat = Concat

makes `table.concat` work for anything, because `sep` (even when
defaulting to "") causes the metamethod to be invoked except when
Lua "knows what to do".  And the debug library is not used.

I append my proof-of-concept code (I do not have the temerity to upload
it to the Wiki LuaPowerPatches page) as a patch to only `ltablib.c`.

Should this be default behaviour?  Now that the table library respects
__len, it is maybe not too far-fetched to suggest that it might also
respect __concat.
Hi Dirk
Another recent suggestion was to let table.concat call tostring() for non-string array entries, which in turn may invoke __tostring meta method. Which is a concept my feeble mind can easily grasp. What does the __concat concept offer that can not be done with __tostring on non-string entries? (Sorry, I don't have time right now to play around with your patch.) Can it make table.concat return something else than a string? If yes, would it not be kind of surprise to feeble minded code readers? Perhaps your case would be better served by a new function, something like table.aggregate(table), calling metamethod __aggregate, to warn readers that something interesting is going on?