
-- t = proxytable({a=1}, {m_name=2}, function)
function table.proxytable(t, handler, onRead, onWrite)
	handler = handler or {}
	local wrap = functools.partial(convertkv2proxy, handler, onRead, onWrite, t)
	local mt = {
		__index = function(_, k)
			local v = t[k]
			if onRead then onRead(t, k, v) end
			if v == nil then return handler[k] end
			return convert2proxy(handler, onRead, onWrite, v)
		end,
		__newindex = function(_, k, v)
			-- unfold proxy by auto
			if table.isproxy(v) then
				error("do not save proxy in proxy, you could do this when get raw table")
			end
			t[k] = v
			if onWrite then onWrite(t, k, v) end
		end,
		__call = function()
			return t
		end,
		__pairs = function(_)
			local it, tb, init = pairs(t)
			return itertools.iter(it, tb, init, wrap)
		end,
		__ipairs = function(_)
			local it, tb, init = ipairs(t)
			return itertools.iter(it, tb, init, wrap)
		end,
		__next = function(_, k)
			return wrap(next(t, k))
		end,
	}
	return setmetatable({__proxy=true, __raw=t}, mt)
end