lua-users home
lua-l archive

Re: table.concat and metamethods

[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})
 t={true,false}
 print(t[1]..','..t[2])
 true,false
 print(table.concat(t),'))
 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?
Egil

AltStyle によって変換されたページ (->オリジナル) /