3

Just as a random experiment I'm considering adding a __concat() metamethod to the number metatable (usually a new metatable as numbers don't seem to have metatables by default?).

The idea is that I could do something like 3..5 and get back 3, 4, 5.

I could then have a function foo(tbl, ...) that does something with multiple indexes on a table and call it like foo(tbl, 3..5).

Am I barking mad or does this seem like a viable thing to do?

Rough draft of code (not tested yet):

-- get existing metatable if there is one
local m = getmetatable( 0 ) or {};

-- define our concat method
m.__concat = function( left, right )
    -- note: lua may pre-coerce numbers to strings?
    -- http://lua-users.org/lists/lua-l/2006-12/msg00482.html
    local l, r = tonumber(left), tonumber(right);

    if not l or not r then -- string concat
        return tostring(left)..tostring(right);

    else -- create number range
        if l > r then l, r = r, l end; -- smallest num first?
        local t = {};
        for i = l, r do t[#t+1] = i end;
        return (table.unpack or unpack)(t);

    end
end

-- set the metatable
setmetatable( 0, m );

Additional question: Is there any way for me to populate a ... value by value (to remove the need for a table & unpack in the example above)?

cabbageforall
  • 620
  • 1
  • 5
  • 12
  • 1
    In Lua numbers are always coercible to a string, so evaluation of expression `3 .. 5` would never involve a metamethod `__concat`, `3 .. 5` will always be equal to string `35`. – Egor Skriptunoff Aug 23 '15 at 23:21
  • 1
    @EgorSkriptunoff unless you define `LUA_NOCVTN2S` when you compile lua. – daurnimator Aug 24 '15 at 00:31

1 Answers1

3

Your idea can be implemented using __call metamethod:

local mt = debug.getmetatable(0) or {}
mt.__call = function(a,b)  -- a, b - positive integer numbers
   return (('0'):rep(a-1)..('1'):rep(b-a+1)):match(('()1'):rep(b-a+1))
end
debug.setmetatable(0, mt)

-- Example:
print((3)(5))  -->  3  4  5
Egor Skriptunoff
  • 23,359
  • 2
  • 34
  • 64