tarantool / tarantool

Get your data in RAM. Get compute close to data. Enjoy the performance.
https://www.tarantool.io
Other
3.37k stars 378 forks source link

Errorable patched_pairs #9884

Open d-enk opened 4 months ago

d-enk commented 4 months ago
local class = setmetatable({}, {
    __index = function(_, key)
        error(("unknown: '%s'"):format(key), 2)
    end,
})

class.__index = class

local obj = setmetatable({ A = 2 }, class)

assert(pcall(function()
    return obj.A
end))

assert(not pcall(function()
    _ = obj.B
end))

for k, v in require("internal.pairs").builtin_pairs(obj) do
    print(k, v)
end
-- A 2

for k, v in pairs(obj) do
    print(k, v)
end
-- LuajitError: builtin/internal.pairs.lua:9: unknown: '__name'

I understand that can just use a proxy like

local obj = setmetatable({ A = 2 }, { __index = class })

but this is not always convenient

https://github.com/tarantool/tarantool/blob/31c2ddb310ef65d6aea1f1565c4482b222fa9acf/src/lua/pairs.lua#L7-L12

what about use link comparing instead .__name == "box_cfg" something like

local patched_pairs = function(iterable)
    if iterable == box.cfg and type(iterable) == "table" then
        iterable = getmetatable(iterable).__index
    end

    return M.builtin_pairs(iterable)
end
Totktonada commented 4 months ago

I guess we can compare a metatable itself, see #9747.

d-enk commented 4 months ago

My example avoids call getmetatable for a non box.cfg, maybe that makes sense.

UPD: ok, pairs(table.copy(box.cfg)) will not work