Introduction to Variable Scope
Written by rdc
Scope refers to the visibility of a variable, where you can access a variable within a program. Before you can understand the different levels of scope, you need to understand the structure of a program in FreeBasic.
Program Structure
A complete program is composed of one or more .bas files, called modules. Each module can contain both module level code, and code contained within subroutines and functions. Module level code is code that is not contained within a subroutine or function. The following snippet illustrates the various parts of a module.
Local Variables
If you define a variable at the module level (and not using Shared), the variable is said to have local module level scope. It is visible to the module level code, but not to any subroutine or function within the module. In the example above the module variable aInt is only visible to the module level code.
Variables defined within a subroutine or function are local to the subroutine or function and are not visible to module level code or any other subroutine or function.
Variables Defined Within Control Structures
Variables that are defined within If, For-Next, While-Wend and Do-Loop constructs are local to the control structure block code. That is, they are not visible outside the bounds of the begin and end of the control block, just like a variable declared within a subroutine or function.
Shared Variables
In the example, if you wanted aInt to be visible within the subroutine or function, you would need to declare the variable as Shared and then not declare a variable with the same name within any subroutine, function or control block. Shared variables are visible to module level code, subroutine or function level code and within control structure blocks.
Scope Conflicts
In the code snippet above, if aInt were declared as Shared, and each subroutine and function declared aInt, there would be a scope conflict, since there is one variable name used for different levels of scope.
The compiler resolves this by taking the current scope into account and mapping the variable within that scope. Since subroutines and functions have a lower level of scope than the module, aInt would refer to the variable declared within the sub or func, and not the one declared at the module level, even though it is declared as a shared variable.
Multiple Modules
Scope is limited to a single module, that is a single .bas file. However, it is sometimes necessary to extend the scope from one module to another. You would use the Common statement when you declare a variable that needs to be shared among modules.
Each module must have the same Common declaration in order for the compiler to match up the common variables. If you declare a variable in module1 as Common aInt as Integer then module2 must also have Common aInt as Integer. Without the common declaration aInt would not be visible within module2.
You can add the Shared attribute to Common, that is Common Shared to not only extend scope to multiple modules, but to extend scope within a module. Common Shared operates the same as Shared within a single module. As with Common, you need to have matching declarations in each module that needs access to the variable.
You can create a temporary scope block by using the Scope, End Scope keywords. The scope block is very useful when creating multi-line macros where you may need to create some temporary working variables but do not want to introduce name conflicts in the program. The following snippet illustrates how to create a scope block.
The scope of any variable created within a scope block is limited to the block itself. However, the scope block inherits the visibility of the surrounding scope so that variables created at the same scope as the scope block are visible within the block.
For example, if you have aInt which is at module level scope, and the scope block is at module level scope, then aInt would be visible inside the scope block. Unless of course there is a scope conflict, in which case the variable inside the scope block would override the variable with the same name outside the scope block.
Not only does scope set the visibility of a variable, it also determines the lifetime of a variable. A variable goes through several stages in its lifetime; creation, initialization, access and destruction. When this occurs depends on the scope of a variable, that is, where the variable has been defined within the program.
Module Level Variables
Module level variables exist for the life of a program, since they are declared within the main body of the program. Module level code is the main executing code of the program, and terminates when the program ends.
Subroutine and Function Level Variables
Variables declared within a subroutine and function exist as long as the program is within the body of the subroutine and function. On entering the sub/func, the variable is created, initialized and can be accessed within the sub/func. Once the subroutine or function exits, the variable is destroyed.
Static Variables
One exception to the declared sub/func variable is the Static variable. Static variables maintain their value between calls to the subroutine or function and so have a module level lifespan.
Control Block Variables
Variables declared within a control block, such as a For-Next, exist as long as the control block is executing. Upon leaving the control block, the variables are destroyed.
Scope...End Scope Variables
Variables declared within a scope block exist as long as the the scope block exists. Once the program leaves the scope block, any variables created within the scope block are destroyed.
Variable Scope
Scope refers to the visibility of a variable, where you can access a variable within a program. Before you can understand the different levels of scope, you need to understand the structure of a program in FreeBasic.
Program Structure
A complete program is composed of one or more .bas files, called modules. Each module can contain both module level code, and code contained within subroutines and functions. Module level code is code that is not contained within a subroutine or function. The following snippet illustrates the various parts of a module.
Dim aInt As Integer 'Variable declared at module level
Sub DoSomething
Dim aInt As Integer 'Variable declared at sub level
... 'This code is local to sub
End Sub
Function DoSomethingElse() As Integer
Dim aInt As Integer 'Variable declared at func level
... 'This code is local to func
End Function
'Module level code
aInt = 5
DoSomething
aInt = DoSomethingElse()
Sub DoSomething
Dim aInt As Integer 'Variable declared at sub level
... 'This code is local to sub
End Sub
Function DoSomethingElse() As Integer
Dim aInt As Integer 'Variable declared at func level
... 'This code is local to func
End Function
'Module level code
aInt = 5
DoSomething
aInt = DoSomethingElse()
Local Variables
If you define a variable at the module level (and not using Shared), the variable is said to have local module level scope. It is visible to the module level code, but not to any subroutine or function within the module. In the example above the module variable aInt is only visible to the module level code.
Variables defined within a subroutine or function are local to the subroutine or function and are not visible to module level code or any other subroutine or function.
Variables Defined Within Control Structures
Variables that are defined within If, For-Next, While-Wend and Do-Loop constructs are local to the control structure block code. That is, they are not visible outside the bounds of the begin and end of the control block, just like a variable declared within a subroutine or function.
Shared Variables
In the example, if you wanted aInt to be visible within the subroutine or function, you would need to declare the variable as Shared and then not declare a variable with the same name within any subroutine, function or control block. Shared variables are visible to module level code, subroutine or function level code and within control structure blocks.
Scope Conflicts
In the code snippet above, if aInt were declared as Shared, and each subroutine and function declared aInt, there would be a scope conflict, since there is one variable name used for different levels of scope.
The compiler resolves this by taking the current scope into account and mapping the variable within that scope. Since subroutines and functions have a lower level of scope than the module, aInt would refer to the variable declared within the sub or func, and not the one declared at the module level, even though it is declared as a shared variable.
Multiple Modules
Scope is limited to a single module, that is a single .bas file. However, it is sometimes necessary to extend the scope from one module to another. You would use the Common statement when you declare a variable that needs to be shared among modules.
Each module must have the same Common declaration in order for the compiler to match up the common variables. If you declare a variable in module1 as Common aInt as Integer then module2 must also have Common aInt as Integer. Without the common declaration aInt would not be visible within module2.
You can add the Shared attribute to Common, that is Common Shared to not only extend scope to multiple modules, but to extend scope within a module. Common Shared operates the same as Shared within a single module. As with Common, you need to have matching declarations in each module that needs access to the variable.
Scope...End Scope
You can create a temporary scope block by using the Scope, End Scope keywords. The scope block is very useful when creating multi-line macros where you may need to create some temporary working variables but do not want to introduce name conflicts in the program. The following snippet illustrates how to create a scope block.
Scope
Dim tmp As Integer
... 'Some code
End Scope
Dim tmp As Integer
... 'Some code
End Scope
The scope of any variable created within a scope block is limited to the block itself. However, the scope block inherits the visibility of the surrounding scope so that variables created at the same scope as the scope block are visible within the block.
For example, if you have aInt which is at module level scope, and the scope block is at module level scope, then aInt would be visible inside the scope block. Unless of course there is a scope conflict, in which case the variable inside the scope block would override the variable with the same name outside the scope block.
Variable Lifetime
Not only does scope set the visibility of a variable, it also determines the lifetime of a variable. A variable goes through several stages in its lifetime; creation, initialization, access and destruction. When this occurs depends on the scope of a variable, that is, where the variable has been defined within the program.
Module Level Variables
Module level variables exist for the life of a program, since they are declared within the main body of the program. Module level code is the main executing code of the program, and terminates when the program ends.
Subroutine and Function Level Variables
Variables declared within a subroutine and function exist as long as the program is within the body of the subroutine and function. On entering the sub/func, the variable is created, initialized and can be accessed within the sub/func. Once the subroutine or function exits, the variable is destroyed.
Static Variables
One exception to the declared sub/func variable is the Static variable. Static variables maintain their value between calls to the subroutine or function and so have a module level lifespan.
Control Block Variables
Variables declared within a control block, such as a For-Next, exist as long as the control block is executing. Upon leaving the control block, the variables are destroyed.
Scope...End Scope Variables
Variables declared within a scope block exist as long as the the scope block exists. Once the program leaves the scope block, any variables created within the scope block are destroyed.