As a Roblox developer, it is currently too hard to utilize method functions in callbacks, and its expensive.
If Roblox is able to address this issue, it would improve my development experience because it would allow me to write much more readable code, and utilize method calls in callbacks more performantly.
Demonstration of the problem:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Services = ReplicatedStorage:WaitForChild("Services")
local CollectionService = require(Services:WaitForChild("CollectionService"))
local collector = workspace:WaitForChild("Collector")
collector.Touched:Connect(function(touchedPart)
CollectionService:Collect(touchedPart)
end)
One partial solution:
collector.Touched:Connect(CollectionService.Collect)
This fixes all of the issues, but unfortunately, this conflicts with many people’s programming styles, and, its impossible to do this for Roblox objects, such as Instances, or vectors, and conflicts with most custom class implementations in lua due to unavoidable reliance on self
.
Conclusion
Being able to make method calls more directly would resolve a lot of the issues above. Additionally, it would be able to greatly benefit performance in cases where its not possible to do a regular method call on something.
One possible solution
A possible solution could be to allow for this expression syntax, as an operator:
local methodFunction = object:MethodName
Caveats tl;dr: Likely requires a new datatype which shortcuts a method call (e.g. method
like vector
), otherwise it would create ambiguity in its behaviour that is incompatible with existing code (e.g. (a:b)()
vs a:b()
having different call stacks)
This should be compatible with luau’s method optimizations to some extent at least, and has the flexibility to allow for some optimizations that aren’t currently possible, so I explored it a bit with a friend.
Some caveats
- This would likely need to return a new datatype or function, meaning
object:MethodName == object.MethodName
could be false. However, in all situations this would apply, this is already the case. - This creates ambiguity for method calls (E.g.
object:MethodName()
becomes ambiguous… Isobject:MethodName()
equivalent to how it currently is, or does it behave as(object:MethodName)()
? One way eliminates ambiguity, the other way ensures consistently (but might have a performance cost). The two would have to behave indistinguishably if separate from eachother. - If a new function gets returned which invokes the method call, should it appear in the call stack? To preserve the example behaviour this would have to be the case, but this requires the previous caveat to separate the behaviour of both.
- If a new function does not get returned, a new datatype would likely need to be used which “shortcuts” a method call. (E.g. a
method
type, likevector
)
It’s also good to note that the exact example behaviour this replaces isn’t at all important to preserve such as in the third caveat (and may actually not offer any benefit to preserve anyways), which would simultaneously solve the second caveat (but would require a new data type)