MAXScript FAQ > What is Scope of variables? |
The following chapters provide detailed explanation of variable scope:
Variables - Assignment and Scope
Accessing Locals and Other Items in a Rollout from External Code
Changes to Undeclared Implicit Global Variables
Definition Constructs Can Include Global Variable Declarations At Top Level
You could imagine the scopes as an onion with nested "layers". When a local variable is created at a certain level, it is visible only at this level and all scopes nested inside of it.
In the special case of MacroScripts, Rollouts and Utilities, a local variable defined in the outer-most scope is visible to any code inside of the macroScript, rollout or utility but not visible to any other macroScript, rollout or utility. This can be seen as a kind of "private global" variable which is just how it works and not a technical name for a new kind of scope. For more info, see Local variables as private global variables
In addition, a variable can be only accessed if it has been already defined. This means that the order of functions and rollout definitions does matter as you cannot access a function or rollout which is defined later in the source code. This case can be solved by pre-defining the variable used to store the function or rollout in the same or higher scope before the actual function or rollout definition.
For example, if you have multiple rollout definitions in a Utility and want to access a user interface element of the second rollout from inside the first rollout, you will have to pre-define the variable storing the second rollout before the first one.
If you would not pre-define the variable and try to access a UI control from the second rollout, MAXScript would show you an error because when evaluating the first rollout it has no knowledge of the second one - it has not been evaluated yet!
If you have declared the variable name of the second rollout as local in the beginning of the Utility, it will first be set to the value "undefined", but will be seen as defined by any code that references it. In other words, MAXScript will find the name of the variable, ignore the fact there is still no rollout value inside and keep going with the evaluation. Once it finds the definition of the second rollout, it will "fill in" the rollout information and when you actually try to use code in the first rollout referencing the second one, everything will be ok.
Local variables let you encapsulate values for "local use" without interfering with other parts of the script, or even worse, with other scripts. Imagine if every single script out there would use only global variables. If a user would write a script that uses the variable "i" in a loop and another users would write another that uses "i" for an index to a vertex somewhere, chances are these two scripts would have troubles running in the same scene unless the programmers have taken extra care to explicitly declare and initialize every variable before using it. All in one, it would be a real pain!
Luckily, MAXScript will keep the variables inside the respective scopes and the one script will never access variables from the other one unless you want it to by using explicit global definitions.
By default, any variable used without declaration inside of a scope becomes local for that scope so you usually don't really have to explicitly write "local" in front of every variable. While it would be a good programming practice to declare variables explicitly, MAXScript does not force you to do this most of the time. See Implicit Variable Declaration for more info.
You would define global variables in all those cases where multiple scripts have to access the same value, or share a value. Any MAXScript code could read that value. So you could have a macroScript storing some preferences in a variable, a Utility using these preferences, and both do not have to know about each-other, except for the name of the common global variables.
In some cases, you want to declare a local variable explicitly if a variable with the same name already exists in a higher scope, but you really want to use the same name in a nested scope. If you don't declare the variable as explicitly local, the value of the outer one would be accessed instead, which could lead to logical problems...