Scope is a block of code in which variables are declared.
repeat until loops,
if then, and
do end chunks all create a new variable scope.
Variables can be declared in two ways: local (with the
local keyword), and global. Global variables are always in scope: no matter where you declare them, they are always accessible.
When myFunction was called, myVariable was set to 64. Since this variable is globally scoped, it could be accessed outside the function. This is why the output was "myVariable is 64". Take a look at this example using the
local keyword to change the scope of a variable.
That was outputted because myVariable was confined to myFunction's environment or its scope. Therefore, it was not able to access the value outside of that function.
do end block creates a new scope. This can be useful to create a new block of local variables, without overriding the non-local variables. If you have a long script with a lot of variables, this can be useful. Remember that you can also create local functions using this.
Notice here that the "Pear" variable isn't changed to its "original" non-local value, because we didn't use the local statement in the do block.
In the last example you may have noticed that I said "the variable was also accessible by descendant environments". This concept is called lexical scoping.
This is a simple example with two conditionals. If you recall, conditionals also have their own environment. Here is a snippet to prove this:
Its nil because variable b was confined to the scope of the second conditional. Lexical scoping will allow one to do this:
Even though the second conditional has its own environment, because of lexical scoping,
a was inherited. Variables that are lexically scoped are called upvalues.
You can also define a local variable in a scope without assigning any value to it, but making it possible to read that variable on the current "scope level". You can do this by using the "local" keyword and then the variable name behind it. An example:
This code would return nil if the table "t" does not have a table "Hi" in it, and otherwise will return the last index found which contains the "Hi" value.
Were "local foundAt" not used, then foundAt would be globally scoped, making it accessible elsewhere, and making whereIsHi overwrite any variables with the name foundAt from outer scopes.