Module Scope
"Scope" refers to the ability of a variable or named module to be seen by calling code. For example, two modules may both declare a variable named "X". X will have a unique value in each module and will refer to a different memory address. Each version of X is local to the scope of the module where it is declared.
A module may declare and use submodules. For example, the Graphics submodule of a typical script application. Those submodules (child modules) will also be able to see and use the variables of the main module (parent module). The parent is within the scope of the child.
However, variables declared in the child modules are not within the scope of the parent and cannot be used by the parent unless directly referenced with a scope resolution operator "\" or "." (ChildInstance\Variable or ChildInstance.Variable where ChildInstance is a variable holding the child object - you can only scope into objects, not modules.
Use care! Early coders often write Child\Variable where Child is the name of the module, and that is bad code. The compiler turns it into Child()\Variable, thereby launching a new instance of Child (which may live forever or be a memory leak) and then returning the initial value of Variable from that instance.
If a module has two submodules, and each of those has a variable, "X", the parent cannot simply refer to X, but must identify the submodule in which to find a particular version of X. Typically, this is done by storing a reference to the instance when launching the child module:
If SomeCondition; [ { Launch an instance of Child and get a reference to it } Handle = Child(); ]
You may now refer to variables in that instance of Child using Handle\Variable. If Child also launches submodules, the same rules and techniques apply.
If a module needs to access variables or functions of a separate module, it is possible to do this by fully describing the scope of the variable or function being called. (This assumes that the variable or module has not been declared as "Protected".) For example, many of the functions described in the Function Reference will include the name of the library module of which they are a member, and provide an example of how they should be called:
\AlarmManager.Ack(AlarmName, EventTime, Operator);
The following terms are used when describing scope:
Scope Resolution Operators
There are two scope resolution operators: the dot (.) and the backslash (\). The dot operator was added with VTScada version 11.2 and should be used when the intent is to reference a value only within the identified reference scope. If no value is found in that scope, Invalid will be returned. This differs from the backslash operator, which will look for a variable with the matching name in all ancestors if none is found in the reference scope.
There is also a Scope() function, which takes an object reference, a member name (variable or submodule to be found in the object reference), and a Boolean that controls whether the search will be limited to the named reference or if it should search up the scope tree for a match.
The dot operator is equivalent to the function call LocalScope(A, "B"). The backslash operator is equivalent to the function call Scope(A, "B").
Scope Operators and Late Binding
The scope operators may also be used to accomplish a feature called "late binding". A variable is a name referring to the memory location where a value is stored.
It is worth noting the difference between referring to a variable as \VarName versus VarName (without the scope resolution operator). \VarName is late binding while VarName is early / static binding. The former will compile even if there is no VarName in the compile-time static scope. (And, since the example shows the backslash operator rather than the dot operator, will always evaluate to the nearest VarName variable in the run-time scope tree). The latter will only compile if there is a VarName in the compile-time static scope (and will only resolve to that static variable at run-time even if another VarName variable is added dynamically in a nearer scope).
The process of "binding" is how the name and the storage location in memory are associated. Late binding (also referred to as "dynamic binding") links a variable or object at run time. In early binding, variable references in code are linked to memory addresses / offsets at compile time.
When a scope resolution operator is placed before a variable or module name used in an executable statement, such as in:
\VarName { or .VarName }
it is considered the equivalent of writing:
Self()\VarName
but it uses less RAM. Early binding is typically more efficient than late binding because it reduces the amount of time required to set or retrieve a value, whereas late binding consumes more memory, and is slower than a direct variable reference. However, in some instances it is useful to reference modules and variables that are not in scope at compile time, and therefore you must use late binding after they have a chance to start.
Note that if VarName is a protected variable, then Self()\VarName will be Invalid while \VarName will correctly scope to the variable.
Always use VarName if it works, which it should the vast majority of the time. You should only need to use \VarName if "VarName" is something in Code, provided by VTScada.