luarobloxluau

How to make multi-argument choose function in LuaU?


I want to make function which returns multiple variants "how to use function": var.get(a:number): any next is var.get(a:string,b:number): any next is var.get(): any.

I know by Roblox Lua (LuaU) it's possible and it returns as pages like I did upper. How can I make same? (please provide code) I'm sure it should be one function but how it returns multiple variants of how to use it?

I tried:

local var={}
function var.get(a:number):any
  -- some code here
end
function var.get():any
  -- some code here
end

But it didn't worked.


Solution

  • As @Kylaaa said, there is no function overloading in Lua out of the box. But Lua is flexible, and function overloading can be emulated, using already mentioned variadic functions and the fact that, in Lua, functons are first-class objects.

    local function overloaded (signatures)
        local concat = table.concat
    
        -- Serialise signatures beforehand to compare them as strings at call time:
        local serialised_signatures, fallback = {}, nil
        for signature, implementation in pairs (signatures) do
            if type (signature) == 'number' or signature == 'void' then
                -- syntactic sugar for an empty signature:
                signature = ''
            elseif type (signature) == 'table' then
                -- long signatures:
                signature = concat (signature, ', ')
            elseif signature == '...' then
                -- fallback: any unrecognised signature:
                fallback = implementation
            end -- otherwise, it is a signature with one argument, which remains a string.
            serialised_signatures [signature] = implementation
        end
                
        -- Get the serialised signature of a function call at runtime:
        local function arg_types (...)
            local types = {}
            for i, arg in ipairs {...} do
                types [i] = type (arg)
            end
            return concat (types, ', ') -- to make comparing easier.
        end
        
        return function (...)
            local called_with_args = arg_types (...)
            for signature, implementation in pairs (serialised_signatures) do
                if called_with_args == signature then
                    return implementation (...)
                end
            end
            -- fallback:
            return fallback (...)
        end
    end
    
    local get = overloaded {
        -- no arguments. [{}], or [''], or void index will have the same effect:
        function ()
            return 'If you want to get something, give something'
        end,
        -- one argument, number:
        number = function (number)
            return 'You have given the number ' .. number
        end,
        -- one argument, string, but passed as a list:
        [{ 'string' }] = function (string)
            return 'You have given the string "' .. string .. '"'
        end,
        -- several arguments:
        [{ 'number', 'number' }] = function (no1, no2)
            return 'You have given two numbers: ' .. no1 .. ' and ' .. no2
        end,
        -- any other signature:
        ['...'] = function (...)
            return 'The supplied arguments were: ' .. table.concat ({...}, ', ')
        end
    }
    
    print ('get () = ' .. get ())
    print ('get (42) = ' .. get (42))
    print ("get 'fourty-two' = " .. get 'fourty-two')
    print ('get (4, 2) = ' .. get (4, 2))
    print ("get (1, 'some string') = " .. get (1, 'some string'))