lua-users home
lua-l archive

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




On Thu, Jul 21, 2022 at 12:27 AM Egor Skriptunoff <egor.skriptunoff@gmail.com> wrote:
On Wed, Jul 20, 2022 at 8:50 PM Gé Weijers wrote:
local last_key = -1

local meta = {
    __index = function(meta, key)
        if key > last_key then
            last_key = key
            return "a"
        else
            return "bb"
        end
    end,
}

local t = setmetatable({}, meta)

print(table.concat(t, "", 1, 0x1 << 30))

Never do this in a production code.

You could do it this way:

local N <const> = 0x1 << 30

local index_count = 0

local meta = {
    __index = function(meta, key)
        index_count = index_count + 1
        if index_count <= N then
            return "a"
        else
            return "bb"
        end
    end,
}

local t = setmetatable({}, meta)

print(table.concat(t, "", 1, N))

The order of evaluation is a red herring here, the issue is that you can't create an implementation of table.concat that does not 'misbehave' by allocating much more memory than is needed to store the result in all possible cases. It cannot calculate the required output buffer size unless it stores all the intermediate results generated by calls to __index , or alternatively by calling __index more than once for each key. Storing the intermediate results requires way more memory than the actual results in this example, and calling __index twice for each key changes the results and the calculated length will be wrong anyway.

And yes, you probably should not write the __index metamethod to return different results for the same key in production code.

--