2016-11-03 5 views
1

AutomagicTables (http://lua-users.org/wiki/AutomagicTables)와 함께 Lua 메타 테이블에 대한 도움이 필요합니다. 정의되지 않은 테이블에 할당하는 기능은 매우 훌륭하므로이 기능을 유지하고 싶습니다. 내 버전은 하나의 함수에 배치되었습니다 필드가 정의되어 있지 않은 경우기본값 및 자동 테이블 생성이있는 Lua 테이블

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 

내가 원하는 것은 디폴트의 테이블을 전달하는 것입니다 사용할 수 - PIL 13 장 (https://www.lua.org/pil/13.4.3.html)에 설명 된대로. 이것은 내 데이터 strucutre에서 계산 및 조회 필드를 허용합니다. 무기 호입니다 테이블 [ "DOB"]로 실패 코드 연령()에

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) 

참고 현재 테이블의 DOB 필드에 대한 참조 (아래 참조) : 다음은 내가 사용하고자하는 구문입니다. 이 코드를 기본값이없는 곳에 실행하면 Automagic은 누락 된 값에 대한 테이블을 반환합니다.

내가 PIL 13 장에서 다음 예제 기본값을 할당 할 수 있지만 구문이 지저분하고 한 번 (나는 다른 메타 테이블을 할당로) 나는 AutomagicTable 기능을 느슨하게 적용 : '

-- 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" 

불행하게도 내가 돈 AutomagicTables 코드를 완전히 이해하고 있으며 AutomagicTable 코드 내에 필요한 기능을 추가하는 데 어려움을 겪고 있습니다.

감사받은 어떤 도움.

개빈

답변

0

여기서는 완전한 자동 엔진이 필요하지 않다고 생각합니다.
사용자 (즉, 깊이 수준 1의 개체) 만 자동으로 만들어야합니다.
그래서 더 간단한 로직을 사용할 수 있습니다 :

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

많은 감사합니다. 당신의 단일 레벨 자동화는 훨씬 이해하기 쉽습니다. 지 – Gavin