I'm trying to figure it out myself, so let me see if I've got it right. If not, please steer me in the right direction.
In its simplest form, this is the basic structure of a module:
Code: Select all
DeclareModule myModule
;this is called the module declaration
EndDeclareModule
Module myModule
;this is called the module space
EndModule
At this point, they do absolutely nothing, so let's begin by adding a simple variable:
Code: Select all
DeclareModule myModule
EndDeclareModule
Module myModule
Define a.i = 1
EndModule
The module now contains an integer variable,
a, assigned with a value of 1. Since it is defined within the module space, it is a
private variable, accessible only within the module. To add a public variable, it has to be defined in the module declaration, like this:
Code: Select all
DeclareModule myModule
Define a.i = 1
EndDeclareModule
Module myModule
EndModule
The integer variable
a is now a
public variable that is accessible inside and outside the module. Similarly, constants and procedures can also be private or public, depending on where they are declared. It should be noted that public variables can still be manipulated within the module:
Code: Select all
DeclareModule myModule
Define a.i = 1
EndDeclareModule
Module myModule
a = 2
EndModule
As mentioned earlier, constants can also be defined within the module, either as private or public ones, depending on where they are defined:
Code: Select all
DeclareModule myModule
#constant1 = 100
Define a.i = 1
EndDeclareModule
Module myModule
#constant2 = 200
a = 2
EndModule
Here,
constant1 is a public constant, while
constant2 is a private constant. Procedures, on the other hand, should always be created within the module, but to declare them as public, an additional declaration is required:
Code: Select all
DeclareModule myModule
#constant1 = 100
Define a.i = 1
EndDeclareModule
Module myModule
#constant2 = 200
a = 2
Procedure test(param)
ProcedureReturn param + #constant1
EndProcedure
EndModule
At this point, the procedure
test() is a private procedure, accessible only within the module space. To make it a public procedure, accessible from outside the module, it has to also be declared in the module declaration:
Code: Select all
DeclareModule myModule
#constant1 = 100
Define a.i = 1
Declare test(param)
EndDeclareModule
Module myModule
#constant2 = 200
a = 2
Procedure test(param)
ProcedureReturn param + #constant1
EndProcedure
EndModule
The procedure
test()is now a public procedure, accessible from both inside and outside the module. Another procedure is added here to demonstrate this:
Code: Select all
DeclareModule myModule
#constant1 = 100
Define a.i = 1
Declare test(param)
EndDeclareModule
Module myModule
#constant2 = 200
a = 2
Procedure test(param)
ProcedureReturn param + #constant2
EndProcedure
Procedure test2(param)
ProcedureReturn test(param) + #constant1
EndProcedure
EndModule
Here, a new private procedure,
test2(), calls the public procedure
test(), making use of both private as public constants as well. Note that the procedure
test2() is private only because it has not been declared in the module declaration, and can be made public by simply doing so.
Now, to use the module. As mentioned earlier, only public constants, variables and procedures are accessible from outside the module. This can be done in two ways. The first method is to use the full name of the module, in this case
myModule, followed by two colons
(::), and then the name of the public constant, variable or procedure:
Code: Select all
Debug myModule::#constant1 ;returns 100
Debug myModule::a ;returns 2
Debug myModule::test(22) ;returns 222
The second method is by using the keyword
UseModule followed by the module name,
myModule. After that, the public constants, variables and procedures can be used directly without any prefixes:
Code: Select all
UseModule myModule
Debug #constant1 ;returns 100
Debug a ;returns 2
Debug test(22) ;returns 222
The keyword
UseModule essentially merges the module namespace with the global namespace. It works in a similar way as the
With/EndWith function, but without the need for the backslash
(\) or
EndWith. To stop this namespace merger, simply call
UnuseModule, followed by the module name:
Code: Select all
UseModule myModule
Debug #constant1
Debug a
Debug test(22)
UnuseModule myModule
This stops the namespace merger, and any further calls to the module must be done either with the full module name with double colons, or by calling the
UseModule function with the module name again. One important point regarding namespaces: when using the
UseModule function, the global namespace cannot contain same-named constants, variables or procedures. The following code syntax is legal:
Code: Select all
#constant1 = "Hello"
Define a.f = 1.23
Procedure.s test()
ProcedureReturn #constant1 + " World!"
EndProcedure
Debug myModule::#constant1 ;returns 100
Debug myModule::a ;returns 2
Debug myModule::test(22) ;returns 222
Debug #constant1 ;returns "Hello"
Debug a ;returns 1.23
Debug test() ;returns "Hello World!"
This code syntax is not legal, and will raise an
"...already declared in global scope" error:
Code: Select all
#constant1 = "Hello"
Define a.f = 1.23
Procedure test()
Debug #constant1 + " World!"
EndProcedure
UseModule myModule ;raises error
Debug #constant1
Debug a
Debug test(22)
UnuseModule myModule
However, if no name conflicts are expected, the
UseModule function is very useful, and can save a lot of typing. Simply place it at the beginning of the program code, just after the module declaration:
Code: Select all
DeclareModule myModule
#constant1 = 100
Define a.i = 1
Declare test(param)
EndDeclareModulee
UseModule myModule
;the rest of the program code
;UnuseModule not required...
It should also be noted that, unlike procedures, the global contents in the module space are executed even if the module is not called. To illustrate:
Code: Select all
Procedure someProcedure()
Debug "I will not be executed..."
EndProcedure
Clearly, even if the above procedure was placed at the beginning of the program code, the debug statement would not be executed unless the procedure is called.
Code: Select all
DeclareModule someModule
EndDeclareModule
Module someModule
Procedure test(param)
Debug "I will not be executed..."
EndProcedure
Debug "I will be executed..."
EndModule
On the other hand, if the above module was placed at the beginning of the program code, although the first debug statement would not be executed, the second one would.
So, that's PureBasic's new module function in a nutshell. Its main advantage over DLLs, procedures and include files is its unique namespace feature. Having a totally separate namespace allows modules to have constants, variables and procedures that would not run the risk of name conflicts, while still being able to share and expose selected elements, and have its code accessible from within the IDE.
Here's the complete working code for this little tutorial:
Code: Select all
DeclareModule myModule
#constant1 = 100
Define a.i = 1
Declare test(param)
EndDeclareModule
Module myModule
#constant2 = 200
a = 2
Debug "This line will be executed..."
Procedure test(param)
ProcedureReturn param + #constant2
EndProcedure
Procedure test2(param)
ProcedureReturn test(param) + #constant1
EndProcedure
EndModule
;----------------------------------------
;UseModule works here before same-named
;constants, variables and procedures are
;declared in the global namespace
;----------------------------------------
UseModule myModule
Debug #constant1 ;returns 100
Debug a ;returns 2
Debug test(22) ;returns 222
UnuseModule myModule
;----------------------------------------
#constant1 = "Hello"
Define a.f = 1.23
Procedure.s test()
ProcedureReturn #constant1 + " World!"
EndProcedure
Debug myModule::#constant1 ;returns 100
Debug myModule::a ;returns 2
Debug myModule::test(22) ;returns 222
Debug #constant1 ;returns "Hello"
Debug a ;returns 1.23
Debug test() ;returns "Hello World!"
;----------------------------------------
;UseModule fails here because same-named
;constants, variables and procedures have
;been declared in the global namespace
;and are conflicting with the module's
;constants, variables and procedures.
;----------------------------------------
; UseModule myModule
; Debug #constant1
; Debug a
; Debug test(22)
; UnuseModule myModule
;----------------------------------------
Feedback and corrections are appreciated.
