Hack: Function overloading in Lua

Short backstory: Start of second semester of Computer Science. I liked function overloading in Java, so I decided to write it in lua.

[lua]–getparams by Deco.

local function getparams(f)
local co = coroutine.create(f)
local params = {}
debug.sethook(co, function()
local i, k = 1, debug.getlocal(co, 2, 1)
while k do
if k ~= “(*temporary)” then
table.insert(params, k)
end
i = i+1
k = debug.getlocal(co, 2, i)
end
error(“end”)
end, “c”)
local res, err = coroutine.resume(co)
if res then
error(“The function provided defies the laws of the universe.”, 2)
elseif string.sub(tostring(err), -7) ~= “end” then
error("The function failed with the error: "…tostring(err), 2)
end
return params
end

local _C = {}
function setMeta(v)
setmetatable(v, {
__index = function(t,k)
return function(…)
if _C[t] and _C[t][k] and _C[t][k][#{…}] then
return _C[t][k]#{…}
end
end
end,

	__newindex = function(t,k,v)
		if type(v) == "function" and #getparams(v) then
			_C[t] = _C[t] or {}
			_C[t][k] = _C[t][k] or {}
			_C[t][k][#getparams(v)] = v
			return;
		end
		
		if type(v) == "table" then
			setMeta(v)
		end
		
		return rawset(t,k,v)
	end,
})

end

local scanned = {}

local function scanTable(tbl)
for k , v in pairs(tbl) do
if type(v) == “table” and not scanned[v] then
scanned[v] = true

		setmetatable(v, {
			__index = function(t,k) 
				return function(...)
					if _C[t] and _C[t][k] and _C[t][k][#{...}] then
						return _C[t][k][#{...}](...)
					end
				end
			end,
			
			__newindex = function(t,k,v)
				if type(v) == "function" and #getparams(v) then
					_C[t] = _C[t] or {}
					_C[t][k] = _C[t][k] or {}
					_C[t][k][#getparams(v)] = v
					return;
				end
				
				if type(v) == "table" then
					setMeta(v)
				end
				
				return rawset(t,k,v)
			end,
		})
		scanTable(v)
	end
	
	--[[if type(v) == "function" and getparams(v) then
		_C[tbl] = _C[tbl] or {}
		_C[tbl][k][#getparams(v)] = v
		tbl[k] = nil
	end]]
end

end

scanTable(_G)
[/lua]

Usage:

Overloading can only be done on the number of parameters in a function. This hack automatically overloads every global function created after it (I was going to overload previous funcs, but that got messy). Simply define your function as normal, multiple times with different numbers of parameters. If you create multiple functions with one number of parameters, it will get overwritten; though preventing that would be trivial.

[lua]-- EXAMPLE CODE –

– In normal lua, this would throw a nil error.
print("-- TEST BEGINNING–")
function a(b) print(b) end
function a(b,c) print(b … c) end
function a(b,c,d) print(b … c … d) end
function a(b,c,d,e) print(b … c … d … e) end
function a(b,c,d,e,f) print(b … c … d … e … f) end

a(“1”)
a(“1”, “2”)
a(“1”, “2”, “3”)
a(“1”, “2”, “3”, “4”)
a(“1”, “2”, “3”, “4”, “5”)

lib = {}

function lib.pow() print(“No args”) end
function lib.pow(a) print(“One arg”) end
function lib.pow(a,r) print(“POWER!”) end

lib.pow()
lib.pow(“ar”)
lib.pow(“e” , “r”)[/lua]

Outputs:


-- TEST BEGINNING--
1
12
123
1234
12345
No args
One arg
POWER!

Practical uses: None that I can think of. However, as both a POC and also incase anyone really loves Java and wants to use this; they’ll likely feel at home. Enjoy. (Also, it should work in most versions of Lua)

I know a lot of you (garry) think I’m an utter dick. But still, have fun -Flap

Wonderful job! King’d.

Looking at the way it works, I guess thats not working for local functions?

[editline]27th January 2012[/editline]

Looking at the way it works, I guess thats not working for local functions?

Also, aren’t coroutines broken?

Unfortunately not. It’s possible to hack into local tables, and functions but it is an awful lot of effort and not really worth it for a POC. As far as I know coroutines aren’t broken except when you pass objects into them.

I can’t test this in GMod because of something garry did that I’m not going to post publicly.

imo it’s pretty pointless since Lua doesn’t use specific data types for arguments. Or just using … if a different amount of arguments are needed at different times.

Will be useful in the cases where you have a different number of arguments, though.

That still requires the (ugly) if-elses to sort it all out.

That is true, but there are not many cases in Lua where you need to overload functions. Good job though.

I would argue that the cases don’t exist, because it wasn’t a feature previously. Sure, you don’t have to use “++” for things, but I would sure as hell use it if it existed in lua.

Now you’ve made me curious.

Ah, nevermind I know.

-snip

This is art.