How does Lua know what variable I'm referring to?

Hi. So i was experimenting with a leaderstats system that doesn’t involve manually scripting it. The script simply replicates a leaderstats folder into the player, from Server Storage.


local players = game:GetService("Players")
local serverStorage = game:GetService("ServerStorage")

local leaderstats = serverStorage.leaderstats

		local leaderstats = leaderstats:Clone(); leaderstats.Parent = player

Very simple script, but I’m curious how this syntax actually works. I have a variable named “leaderstats” outside of the scope of the event/function, so how does Lua know I want to refer to that leaderstats variable outside of the function, rather than the new leaderstats variable created inside of the function?

FYI, yes i tested this script. It works flawlessly, which is why I wanted to ask this because I was actually expecting some sort of error.


Basic overview:
Basically outside the functions, the code thinks “Oh, this is a Variable”, But within the function, there is a new local Variable under that same name, so then, the code will then think, “Oh, this is a new Variable” but only within the scope of the function as local Variables are different from global Variables

GlobalVar = "Hi" -- GLobal Variable, can be use throughout the Script
local LocalVar = 12412 -- Local Variable, can only be used within the place its created (to put it simply)

It would be a lot different if you did this:

local st = "hi" -- technically a "Global" Variable

function ex()
    st = "Hello" -- Changes Variable Globally

However, this is what its doing:

local st = "hi"

function ex()
   local st = 123456 -- a new local Variable, Different Value, only usable within the scope of the function

print(st) -- works as if nothing happened

However, the code will remain the same outside as the local Variable cant be used there

Luau Syntax
This might not help, but it is basically syntax


Well, here’s what Lua knows: Scope | Roblox Creator Documentation, plus the Lua 5.1 reference manual. EDIT: The chapter.

Why it knows that? Because the designers of Lua designed it that way. It could know different things, pretty much any coherent idea of what it might mean is possible to implement in a language. For example it might treat the innermost leaderstats as if it’s known at the time when the expression to the right of = is evaluated. This is only relevant when the variable itself occurs in that expression. There is only one possible value for a newly declared and as-of-yet-unassigned variable, namely nil. So there is no possible statement like local a = a:Clone() that could ever be useful (it would always error, and any valid expression could just use the nil literal instead) . So the meaning that the Lua designers chose is probably better :stuck_out_tongue: Can you think of other things such a statement might mean?

How it knows it? Oooo boi I can recommend a uni textbook on compilers if you want a satisfying answer to that :face_holding_back_tears: The short version is symbol tables. Simplified, just a list of what variables are available during any point of the program. If a symbol is not defined in the current scope, check the next scope out and the next, until you reach the global scope. It’s more complicated because Lua has closures and upvalues and stuff. The long answer is chapter 8 of Crafting a Compiler, Block-Structured Languages and Scopes. There are probably shorter / more accessible explanations online.

at the start, there’s only the global leaderstats so the interpreter “uses” that, after it, you made a local variable with the same now, now the interpreter will “use” that variable instead.