2016-11-03 1 views
1

J'ai besoin d'aide avec les méta-tables Lua, notamment avec AutomagicTables (http://lua-users.org/wiki/AutomagicTables). La possibilité d'assigner juste aux tables indéfinies est très gentille, et je voudrais garder cette fonctionnalité. Ma version a été placée dans une seule fonction:Tables Lua avec valeurs par défaut et création automatique de tables

require("dataentry") -- Contains my age function 
function AutomagicTable() 
-- Create a new data table 
-- from 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 

Ce que je veux passer une table de valeurs par défaut à utiliser lorsqu'un champ n'est pas défini - comme décrit dans le chapitre 13 PIL (https://www.lua.org/pil/13.4.3.html). Cela permettrait des champs calculés et de recherche dans mon strucutre de données. Voici la syntaxe que je veux utiliser:

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

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) 

Notez la référence au champ de date de naissance de la table en cours (voir ci-dessous) dans cet âge de code() échoue table [ « date de naissance »] est nul. Si vous exécutez ce code où il n'y a pas de valeurs par défaut, Automagic renvoie une table pour les valeurs manquantes.

Je peux attribuer les valeurs par défaut suivant l'exemple dans PIL Chapitre 13, mais la syntaxe est en désordre et une fois appliqué, je lâche la fonctionnalité AutomagicTable (comme je l'ai attribué un autre métatable):

-- Make a metatables 
t_defaults = {} 
t_defaults.__index = function (table, key) 
local def = { 
    Age = age(table["DOB"]), 
    Sex = "Female" 
    } 
return def[key] 
end 

-- Set new metatable - but now we can't make anymore Automagic tables 
setmetatable(t.ID12345, t_defaults) 
setmetatable(t.ID12346, t_defaults) 

-- This will work 
print("ID12345",t.ID12345.Sex,t.ID12345.DOB,t.ID12345.Age) 
print("ID12346",t.ID12346.Sex,t.ID12346.DOB,t.ID12346.Age) 

-- This assignment fails 
t.ID12347.DOB = "12/12/1945" 

Malheureusement, je n » Je comprends parfaitement le code AutomagicTables et j'ai du mal à ajouter les fonctionnalités requises dans le code AutomagicTable.

Toute aide reçue avec gratitude.

Gavin

Répondre

0

Je pense que vous n'avez pas besoin automagique pleine profondeur ici.
Seuls les utilisateurs (c'est-à-dire les objets au niveau de profondeur 1) doivent être créés automatiquement.
Ainsi, la logique plus simple pourrait être utilisé:

local function age(DOB_str) 
    local m, d, y = (DOB_str or ""):match"^(%d+)/(%d+)/(%d+)$" 
    if m then 
     local t = {month = tonumber(m), day = tonumber(d), year = tonumber(y)} 
     local now = os.date"*t" 
     local now_year = now.year 
     now = os.time{year = now_year, month = now.month, day = now.day} 
     local lower_bound = math.max(0, now_year - t.year - 1) 
     local completed_years = -1 + lower_bound 
     t.year = t.year + lower_bound 
     repeat 
     completed_years = completed_years + 1 
     t.year = t.year + 1 
     until os.difftime(now, os.time(t)) < 0 
     return completed_years 
    end 
end 

-- Class "User" 
local user_default_fields = {Sex = "Female"} 
local user_mt = {__index = 
    function (tab, key) 
     if key == "Age" then -- this field is calculatable 
     return age(tab.DOB) 
     else     -- other fields are constants 
     return user_default_fields[key] 
     end 
    end 
} 

-- The table containing all users with auto-creation 
local users = setmetatable({}, {__index = 
    function (tab, key) 
     local new_user = setmetatable({}, user_mt) 
     tab[key] = new_user 
     return new_user 
    end 
}) 


-- usage 
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) 
+0

Un grand merci. Votre automagic à un seul niveau est beaucoup plus facile à comprendre. g – Gavin