Language Elements and Reference:xpplrm

Symbolic constants and pseudofunctions Foundation

Symbolic constants and pseudofunctions are important tools in programming and contribute to readability and organization of source code. The #define directive is used for this purpose and can be described in its generic form as follows:

#define     <CONSTANT>                        <Value> 

#define     <PSEUDOFUNCTION>([Parameter])     <Expression> 

#define instructs the preprocessor to translate a symbolic constant or pseudofunction to a valid value. Symbolic constants are often defined for numeric codes which always have the same meaning in a specific context. The keys of the keyboard or the buttons of the mouse, for example, are numerically coded and there is a symbolic constant for each key that allows the programmer to write code that is readable and prevents the programmer from having to review the meaning of numeric codes:

#define  xbeK_RETURN  13 
#define  xbeK_ESC     27 

IF LastAppEvent() == xbeK_RETURN 
   ? "Program is continued" 
ELSEIF LastAppEvent() == xbeK_ESC 
   ? "Program was terminated" 
ENDIF 

After a keypress, the function LastAppEvent() returns the key value of the last key pressed. Instead of writing the specific numeric codes into the program, the symbolic constants xbeK_ESC and xbeK_RETURN are used. The preprocessor converts these symbolic constants to the numeric codes for the Esc and Return keys. To the compiler the example looks like this:

IF LastAppEvent() == 13 
   ? "Program is continued" 
ELSEIF LastAppEvent() == 27 
   ? "Program was terminated" 
ENDIF 

The example also illustrates a convention for defining #define constants. They generally begin with a prefix (such as "xbeK_" for "xbase event Key"). The prefix identifies the context in which the constant is used.

Defining pseudofunctions requires the use of parentheses () and allows parameters to be specified. Pseudofunctions appear in the program just like a function call. However, rather than being declared using FUNCTION, they are translated by the preprocessor into an expression:

#define ISARRAY( param )         ( Valtype(param)=="A" ) 
#define ISCHARACTER( param )     ( Valtype(param)=="C" ) 
#define ISDATE( param )          ( Valtype(param)=="D" ) 

PROCEDURE Main( xValue ) 

   DO CASE 
   CASE ISARRAY( xValue ) 
      ? "Parameter xValue has the data type 'array'" 
   CASE ISCHARACTER( xValue ) 
      ? "Parameter xValue has the data type 'character'" 
   CASE ISDATE( xValue ) 
      ? "Parameter xValue has the data type 'date'" 
   ENDCASE 

RETURN 

In this example, three pseudofunctions are defined which test the data type of a parameter. The source code is considerably easier to read with the pseudofunction names, because the names describe the purpose of the functions. The example code looks entirely different to the compiler:

PROCEDURE Main( xValue ) 

   DO CASE 
   CASE ( Valtype(xValue)=="A" ) 
      ? "Parameter xValue has the data type 'array'" 
   CASE ( Valtype(xValue)=="C" ) 
      ? "Parameter xValue has the data type 'character'" 
   CASE ( Valtype(xValue)=="D" ) 
      ? "Parameter xValue has the data type 'date'" 
   ENDCASE 

RETURN 

When pseudofunctions are translated into extensive sections of source code, it increases the storage requirement of the program itself because the preprocessor inserts the translated code into the source files each time the pseudofunction is used. For this reason, a pseudofunction defined using #define should always be weighed against a similar function declared using FUNCTION and written as a function. An actual function can cause decreased storage requirements, but need more time for execution than a pseudofunction.

The syntax of the #define directive is unique in that it is the only directive that distinguishes between upper and lower case letters. Symbolic constants and pseudofunctions must be written within the source code exactly as they are defined using #define.

Feedback

If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.