LuaU Language: Implement scoping operator for variables similar to what C++ does

Problem

As a Roblox developer, it is currently too hard to come up with descriptive variable names without introducing code smells when local variables shadow top level or script level variables.

Use Case

Consider the following code snippet (In C++)

int someVar = 42;

void someFunction(void)
{
	int someVar = 24;
	::someVar = someVar;
}

In this particular case, someVar is a top level variable which is shadowed by a variable of the same name inside the function. However, the top level variable can still be accessed from inside the function by using the scope operator :: in C++. From what I have been able to determine, you cannot do that with LUA.

I posed this question to the assistant and to ChatGPT and both say to use _G.variableName which is a global variable, not a script top level variable. Attempting similar code in LUA causes Studio to flag a syntax error. Since one of the concepts of object oriented programming is data encapsulation, one use for this is to implement properties at the script level.

The following LUA module script demonstrates this using the C++ scope operator (which does not work).

local someVar = 42

local function someFunction(someVar: number)
	::someVar = math.clamp(someVar, 0, 99)
end

local module = {}

module.someFunction = someFunction

return module

Conclusion

If Roblox is able to address this issue, it would improve my development experience because because then I can reuse top level (script level) variable names inside functions and still be able to access the top level variables themselves within said functions.

7 Likes

Global state itself is considered a code-smell. It fragmentates the flow of logic and opens up a bunch of data-races and other nasty bugs.


There’s also a LocalShadow lint (disabled by default on Roblox), which warns when you are overriding another’s namespace. This way, you can reformat names, so they don’t clash while reaping the benefits of static analysis.

2 Likes

Usually for cases like this I just add “new” in front of the function argument’s name:

local character

player.CharacterAdded:Connect(function(newCharacter: Model)
	character = newCharacter
end)

Which would result in something like this for your example:

local someVar = 42

local function someFunction(newVar: number)
	someVar = math.clamp(newVar, 0, 99)
end