In VO, a define is a global constant value. That means that a define in in included library is available in all dependent applications (if the define has not the
define MyDefine := 123
In Vulcan.NET, defines are like in other languages, simple replaced by the compiler or preprocessor, and they are written in a different manner:
#define MyDefine 123
That means that all defines that are to be used in more than one source code file had to be placed in include files and to be included in every source code file that used it.
In X#, the authors recognized the advantage of the VO style define, and included them again, but keeped also the Vulcan.NET style too. So in X# you can use both:
define MyVODefine := 123 // VO style, globally visible #define MyVulcanDefine 123 // Vulcan style, replaced by the compiler
Please note that in the current X# version (22.214.171.124 aka Bandol GA) the #ifdef/#ifndef statement does not sees the VO style define, but only the #define, so you have to work eventually with include files.
Why X# has been returned to the VO style has been explained by Robert v.d.Hulst:
For me the most important reason to switch back from #define to DEFINE is the way it was implemented and the consequences of this implementation. In Vulcan the preprocessor (and the X# preprocessor as well) do a “dumb” Search and Replace for defines and this has unwanted side effects. Consider the following code:
#define DELETE 1 Function Delete(nRec as LONG) AS LOGIC
If the preprocessor compatibility command line option (/vo8) is switched on, then this will be preprocessor to:
FUNCTION 1(nRec as LONG) AS LOGIC
Please note how the name of the function was replaced by the value of the define. This causes many cryptic error messages, making it very difficult for new users to get started. Without /vo8 this would only happen if the function name was written in ALL CAPITAL letters.
The way VO does it (and the way the DEFINE In X# is implemented) this is not handled by te preprocessor. In a later compiler phase the “binder” will lookup names and will find the value and substitute the name in the parse tree with the values. The DEFINE itself is stored as a global const value inside the same class where GLOBALs and FUNCTIONs are stored. This does not have this side effect.