"Overloaded" function definition support

When designing systems, especially custom Luau Objects using OOP principles or multi-purpose functions, it can be very difficult to implement one function with multiple purposes or uses.

It can also be incredibly inefficient and bloaty to constantly check types and values of arguments to try and account for different types of values being passed.

This post suggests the ability to “overload” types and functions that are being redefined via the use of type or function keywords.

Mock-up example:

local function +lerp<T>(a: T, b: T, c: number): T
    return a:Lerp(b, c) -- 'T' requires key/method 'Lerp'
end

--option 1
function +lerp<T:number>(a: T, b: T, c: number): T -- specification for when 'T' is 'number'
    return a + (b - a) * c
end
--option 2
function +lerp(a: number, b: number, c: number): number -- overload when a and b is 'number'
    return a + (b - a) * c
end

function +Quaternion.new(): Quaternion
    return Quaternion.identity
end
function +Quaternion.new(w: number, x: number, y: number, z: number): Quaternion
    -- build quaternion from components
end
function +Quaternion.new(axis: Vector3, angle: number): Quaternion
    -- build quaternion from axis angle
end
function +Quaternion.new(cf: CFrame): Quaternion
    -- build quaternion from cframe information
end

function +QuaternionClass.ToCFrame(self: Quaternion): CFrame
-- generate CFrame from quaternion
end
function +QuaternionClass.ToCFrame(self: Quaternion, position: Vector3): CFrame
  -- generate CFrame from quaternion, with added position value
end
-- ToCFrame(self: Quaternion, position: Vector3?) but optimized when not using position argument

-- if Quaternion supports :Lerp()
lerp(quatA, quatB, 0.5) -- valid

-- otherwise (i.e. it is named Slerp())
-- option 1
function +lerp<T:Quaternion>(a: T, b: T, c: number): T
    return a:Slerp(b, c)
end
-- option 2
function +lerp(a: Quaternion, b: Quaternion, c: number): Quaternion
    return a:Slerp(b, c)
end

This will work will in tandem with a LuauDoc feature I also proposed, allowing users to document overloaded functions easily.

The good thing is that Luau already does support overloaded functions. All functions created in C/C++ for example have the potiential for overloading when binding it to a Lua function. CFrame.new is a great example. Therefore, the implementation would be extend the function overloading ability to native Luau functions as well, which should now be possible due to Luau argument typing.

Some issues/questions may be apparent, but here is my suggestion on how to solve them:

  1. Two overloads represent an ambiguous case

    The ambiguous overloads should create a warning and the latest one will be used due to order of execution.

  2. A function call is ambiguous due to loose types

    Create a warning and call the first available overload unless the types are specified.

  3. Functions get overloaded in another script via injected exploit

    Add the ability to freeze a function to prevent further modification (like table.freeze), or make functions that are in frozen tables unable to be overloaded.
    Functions that don’t have any overload should be frozen automatically.
    There may also be the option to allow overloading only within the same ModuleScript or script/scope.

  4. Changes in Function object’s behavior

    Functions are already first-class objects due to Lua’s nature, and overloads would be additions to the object’s internal structure, similar to how a table’s contents can be modified yet the reference still holds when the table is resized.

  5. Typing an overloaded function

    Typing will just union all function prototypes of all overloads.
    e.g. the quaternion.new() can represented as
    ()->Quaternion & (number,number,number,number)->Quaternion & (Vector3,number)->Quaternion & (CFrame)->Quaternion
    Calling the function with the right parameters will automatically derive which overload to use.

Implementation does not have to match the mock-up, it is only there to demonstrate use cases

7 Likes

Would love this, super helpful. I don’t want to have to incorporate if statements for handling my code differently, it’s much easier to just have overloads and overloads on Roblox would encourage younger developers to learn the mechanism which can be directly ported to other key languages such as C++.

This alongside a real case/switch system would be awesome.

1 Like

yes please

C functions have overloads the same way Luau functions do - by checking argument types using type/typeof and select('#'.
Overloaded function type can be created using &.

We have no plans for adding syntax for function overloads written out separately with dynamic dispatch between them.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.