Overloaded Functions |
|
function overloaded() local fns = {} local mt = {} local function oerror() return error("Invalid argument types to overloaded function") end function mt:__call(...) local argv = {...} local default = self.default local signature = {} for i,arg in ipairs {...} do signature[i] = type(arg) end signature = table.concat(signature, ",") return (fns[signature] or self.default)(...) end function mt:__index(key) local signature = {} local function __newindex(self, key, value) print(key, type(key), value, type(value)) signature[#signature+1] = key fns[table.concat(signature, ",")] = value print("bind", table.concat(signature, ", ")) end local function __index(self, key) print("I", key, type(key)) signature[#signature+1] = key return setmetatable({}, { __index = __index, __newindex = __newindex }) end return __index(self, key) end function mt:__newindex(key, value) fns[key] = value end return setmetatable({ default = oerror }, mt) end
You can use this like so:
foo = overloaded() -- if passed a number, return its square function foo.number(n) return n^2 end -- if passed a string, convert it to a number and call the numeric version function foo.string(s) return foo(tonumber(s)) end -- if passed a string _and_ a number, act like string.rep foo.string.number = string.rep -- if given anything else, act like print foo.default = print --- begin test code --- foo(6) => 36 foo("4") => 16 foo("not a valid number") => error (attempt to perform arithmetic on a nil value) foo("foo", 4) => foofoofoofoo foo(true, false, {}) => true false table: 0x12345678