Lua表格默认值和自动表格创建

我需要 Lua 元表的帮助,特别是自动表格(http://lua-users.org/wiki/AutomagicTables)。直接对未定义的表格赋值非常好用,我希望保留这个功能。我的版本被放在一个单独的功能中:

require("dataentry") -- 包含我的年龄函数
defunction AutomagicTable()
-- 创建一个新的数据表
-- 来自https://lua-users.org/wiki/AutomagicTables
local auto, assign

function auto(tab, key)
return setmetatable({}, {
__index = auto,
__newindex = assign,
parent = tab,
key = key
})
end

local meta = {__index = auto}

function assign(tab, key, val)
if val ~= nil then
local oldmt = getmetatable(tab)
oldmt.parent[oldmt.key] = tab
setmetatable(tab, meta)
tab[key] = val
else
return nil
end
end

return setmetatable({}, meta)
end

我想要传递一个默认值表格,用于当字段未定义时使用 - 如PIL第13章中所述(https://www.lua.org/pil/13.4.3.html)。这将允许在我的数据结构中进行计算和查找字段。以下是我想使用的语法:

t_defaults = {
 Age = age(table["DOB"]),
 Sex = "女性",
}

t = AutomagicTable(t_defaults)

t.ID12345.DOB = "7/2/1965"
t.ID12346.DOB = "1/2/1945"

print("ID12345",t.ID12345.Sex,t.ID12345.DOB,t.ID12345.Age)
print("ID12346",t.ID12346.Sex,t.ID12346.DOB,t.ID12346.Age)

请注意,在此代码中,当前表的DOB字段的引用(参见下文),age()因table \ ["DOB"]为nil而失败。如果在没有默认值的情况下运行此代码,则Automagic将为缺少的值返回表格。

我可以按照PIL第13章中的示例分配默认值,但是语法混乱,一旦应用就会失去AutomagicTable功能(因为我已经分配了不同的元表):

-- 制作元表
t_defaults = {}
t_defaults.__index = functiontablekeylocal def = {
 Age = age(table["DOB"]),
 Sex = "女性"
 }
return def [key]
end

-- 设置新元表 - 但现在我们无法制作新的自动表
setmetatable(t.ID12345,t_defaults)
setmetatable(t.ID12346,t_defaults)

-- 这将起作用
print("ID12345",t.ID12345.Sex,t.ID12345.DOB,t.ID12345.Age)
print("ID12346",t.ID12346.Sex,t.ID12346.DOB,t.ID12346.Age)

-- 这个赋值失败了
t.ID12347.DOB = "12/12/1945"

不幸的是,我并不完全理解AutomagicTables代码,并且正在努力在AutomagicTable代码中添加所需的功能。

感谢任何帮助。

Gavin

点赞
用户1847592
用户1847592

我认为你不需要全深度自动创建。

只有用户(即深度为1的对象)应该被自动创建。

因此,可以使用更简单的逻辑:

local function age(DOB_str)
   --计算年龄的代码,略
end

-- 用户类("User")
local user_default_fields = {Sex = "Female"} --默认字段
local user_mt = {__index =
   function (tab, key)
      if key == "Age" then --这个字段是可计算的
         return age(tab.DOB)
      else                  --其他的字段是常数
         return user_default_fields[key]
      end
   end
}

-- 包含所有用户的表,会自动创建
local users = setmetatable({}, {__index =
   function (tab, key)
      local new_user = setmetatable({}, user_mt)
      tab[key] = new_user
      return new_user
   end
})

-- 使用示例
users.ID12345.DOB = "12/31/1965"
users.ID12346.DOB = "1/2/1945"

print("ID12345", users.ID12345.Sex, users.ID12345.DOB, users.ID12345.Age)
print("ID12346", users.ID12346.Sex, users.ID12346.DOB, users.ID12346.Age)
2016-11-04 12:36:04