INIT PROCEDURE

INIT PROCEDURE

Declare an initialization procedure

Syntax

       INIT PROCEDURE <idProcedure> [(<idParam list>)]
          [FIELD <idField list> [IN <idAlias>]]
          [LOCAL <identifier> [[:= <initializer>]]]
          [MEMVAR <identifer list>]
          .
          . <executable statements>
          .
          [RETURN]

Arguments

INIT PROCEDURE declares a procedure that will be executed at program startup.

<idProcedure> is the name of the initialization procedure to declare. Initialization procedure names can be any length, but only the first 10 characters are significant. Names may not begin with an underscore but can contain any combination of characters, numbers, or underscores.

<idParam list> is the declaration of one or more parameter variables. Variables specified in this list are declared local.

FIELD declares a list of identifiers to use as field names whenever encountered. If the IN clause is specified, referring to the declared name includes an implicit reference to the specified alias.

LOCAL declares and, optionally, initializes a list of variables or arrays whose visibility and lifetime is the current procedure.

MEMVAR declares a list of identifiers to use as private or public memory variables or arrays whenever encountered.

RETURN passes control to the next initialization procedure or the first executable routine in the program, if no other initialization procedures are pending.

Description

The INIT PROCEDURE statement declares a procedure that will be executed at program startup. INIT procedures are called prior to the first executable statement in a Clipper application, and are useful for performing common initialization tasks such as reading configuration settings, or opening a communications port.

INIT PROCEDUREs are executed implicitly by Clipper at program startup. The visibility of initialization procedures is restricted to the system; therefore, it is not possible to call an INIT PROCEDURE from a procedure or user-defined function. Each INIT PROCEDURE receives a copy of the DOS command line arguments used to invoke the application.

Control passes from one INIT PROCEDURE to the next until all procedures in the initialization list have been called. Control then passes to the first executable statement in the program.

The ANNOUNCE statement declares a module identifier for a source (.prg) file. Once declared, INIT PROCEDUREs are referenced by this module identifier. An application may use any number of initialization procedures by explicitly REQUESTing their module identifiers.

If an error is raised during system initialization, the system returns to DOS, and pending initialization procedures are not called.

Examples

       .  The following example uses both INIT and EXIT PROCEDUREs to
       save and restore the context of the operating system. You can have
       your program, "Myfile.prg", REQUEST SaveDos:

       ANNOUNCE SaveDos
       #define DOS_SCREEN    1
       #define DOS_ROW       2
       #define DOS_COL       3
       #define DOS_CURSOR    4
       #define DOS_COUNT     4
       STATIC saSaveDos[ SD_COUNT ]
       INIT PROCEDURE dosSave()
          SAVE SCREEN TO saSaveDos[ DOS_SCREEN ]
          saSaveDos[ DOS_ROW ]    := ROW()
          saSaveDos[ DOS_COL ]    := COL()
          saSaveDos[ DOS_CURSOR ] := SETCURSOR()
          RETURN
       EXIT PROCEDURE dosRestore()
          RESTORE SCREEN FROM saSaveDos[ DOS_SCREEN ]
          SETPOS   ( saSaveDos[ DOS_ROW ], saSaveDos[ DOS_COL ] )
          SETCURSOR( saSaveDos[ DOS_CURSOR ] )
          RETURN

Seealso

ANNOUNCE, REQUEST, EXIT PROCEDURE

WITH OBJECT

WITH OBJECT

Identifies an object to receive multiple messages.

Syntax

       WITH OBJECT <object>
          :<message1>
          [<statements>]
          [:<messageN>]
       END

Arguments

WITH OBJECT <object> <object> is the symbolic name of a variable that holds a reference to an object. The object is to receive messages in the WITH OBJECT control structure.

:<message> All expressions that begin with the send operator in the OBJECT WITH block are sent as messages to <object>.

Description

The WITH OBJECT control structure delimits a block of statements where the object variable <object> receives multiple messages in abbreviated form. The name of the object variable can be omitted from a message sending expression, so that only the send operator (:) followed by the message to send must be typed.

WITH OBJECT basically relieves a programmer from typing. The name of the object variable is typed only once at the beginning of the WITH OBJECT block, and all subsequent messages sent to the object start with the send operator, omitting the object’s variable name.

Example

       // The example builds a simple database browser using a TBrowse object.
       // The columns added to the object and the cursor navigation logic is
       // programmed using the WITH OBJECT control structure.
       #include "inkey.ch"
       PROCEDURE Main
          LOCAL oTBrowse, aFields, cField, nKey
          USE Customer
          aFields := Array( FCount() )
          AEval( aFields, {|x,i| aFields[i] := FieldName(i) } )
          oTBrowse := TBrowseDB()
          WITH OBJECT oTBrowse
             FOR EACH cField IN aFields
                :addColumn( TBColumnNew( cField, FieldBlock( cField ) ) )
             NEXT
          END
          nKey := 0
          DO WHILE nKey <> K_ESC
             WITH OBJECT oTBrowse
                DO WHILE .NOT. :stabilize()
                ENDDO
                nKey := Inkey(0)
                SWITCH nKey
                   CASE K_UP
                     :up()       ; EXIT
                   CASE K_DOWN
                     :down()     ; EXIT
                   CASE K_LEFT
                     :left()     ; EXIT
                   CASE K_RIGHT
                     :right()    ; EXIT
                   CASE K_PGUP
                     :pageUp()   ; EXIT
                   CASE K_PGDN
                     :pageDown() ; EXIT
                   CASE K_HOME
                     :home()     ; EXIT
                   CASE K_END
                     :end()      ; EXIT
                END
             END
          ENDDO
          CLOSE Customer
       RETURN

Seealso

CLASS, METHOD

TRY [CATCH]

TRY [CATCH]

Alternate usage of BEGIN SEQUENCE

Syntax

       TRY
             <statements>
          [CATCH [<exp>] ]
             <errorHandling>
          [FINALLY
             <guaranteed> ]
       END      

Description

TRY/CATCH struct is similar to BEGIN/SEQUENCE struct:

         #xcommand TRY => BEGIN SEQUENCE WITH {| oErr | Break( oErr ) }
         #xcommand CATCH [<!oErr!>] => RECOVER [USING <oErr>] <-oErr->
         #xcommand ENDTRY => END

Alternatively TRY [CATCH] [FINALLY] statements are available on xHB library working like the SEQUENCE construct.

Seealso

BEGIN SEQUENCE

SWITCH

SWITCH

Executes one or more blocks of statements.

Syntax

       SWITCH SwitchExp
          CASE LiteralExp1
            ...
            [EXIT]
         [CASE LiteralExp2]
            ...
            [EXIT]
         [CASE LiteralExpn]
            ...
            [EXIT]
         OTHERWISE
                ...
       END [SWITCH]

Arguments

The <LiteralExp> must be a compiled time resolvable numeric or character expression, and may involve operators, as long as such operators involve compile time static value.

CASE <LiteralExp1> .. <LiteralExp> is a constant value of the same data type as <SwitchExp>.

The EXIT optional statement is the equivalent of the C statement break, and if present, execution of the SWITCH structure will end when the EXIT statement is reached, otherwise it will continue with the first statement below the next CASE statement (fall through)

Description

SWITCH is a Harbour construct inspired by the C implementation of switch().

The SWITCH statement compares a constant value against a series of constant values. It is similar to the DO CASE statement but outperforms it to a great extent due to the restrictions introduced with values permitted for comparison. As a general rule, only literal values in form integer or character constants may follow the CASE clauses.

The SWITCH statement evaluates <SwitchExp> and then searches for a first match between the resulting value and <LiteralExp>. When a match is found, the statements following the corresponding CASE clause are executed down to the END statement. To suppress execution of statements of the next CASE clause, the EXIT statement must be explicitely used. This is a major difference to the DO CASE statement where subsequent CASE clauses are skipped once a first match is found.

If no initial match is found with the CASE clauses, the statements following OTHERWISE are executed, if present.

Example

        // The example demonstrates the SWITCH control structure
        // Try with and without EXIT statements
        PROC Main()
           LOCAL cSName := "Doe"
           SWITCH cSName

              CASE "Abba"
                 ? "Abaneoer"
                 EXIT

              CASE "Bo"
                 ? "Boeing"
                 EXIT
              CASE "Doe"
                 ? "John"
                 EXIT

              OTHERWISE
                 ? "Guest"
           END

            ?? '', cSName
           ?
           WAIT "EOF SwitchTest.prg"
        RETU

Seealso

DO CASE, IF…ELSEIF…ENDIF

STATIC

STATIC

Declare and initialize static variables and arrays

Syntax

       STATIC <identifier> [[:= <initializer>], ... ]

Arguments

<identifier> is the name of the variable or array to declare static. If the <identifier> is followed by square brackets ([ ]), it is created as an array. If the <identifier> is an array, the syntax for specifying the number of elements for each dimension can be array[<nElements>, <nElements2>, …] or array[<nElements>]

[<nElements2>]… The maximum number of elements is 4096. The maximum number of dimensions is limited only by available memory.

<initializer> is the optional assignment of a value to a new static variable. An <initializer> for a static variable consists of the inline assignment operator (:=) followed by a compile-time constant expression consisting entirely of constants and operators or a literal array. If no explicit <initializer> is specified, the variable is given an initial value of NIL. In the case of an array, each element is NIL. Array identifiers cannot be given values with an <initializer>.

Note: The macro operator (&) cannot be used in a STATIC declaration statement.

Description

The STATIC statement declares variables and arrays that have a lifetime of the entire program but are only visible within the entity that creates them. Static variables are visible only within a procedure or user-defined function if declared after a PROCEDURE or FUNCTION statement. Static variables are visible to all procedures and functions in a program (.prg) file (i.e., have filewide scope) if they are declared before the first procedure or user-defined function definition in the file. Use the /N compiler option to compile a program with filewide variable scoping.

All static variables in a program are created when the program is first invoked, and all values specified in a static <initializer> are assigned to the variable before the beginning of program execution.

Declarations of static variables within a procedure or user-defined function must occur before any executable statement including PRIVATE, PUBLIC, and PARAMETERS. If a variable of the same name is declared FIELD, LOCAL, or MEMVAR within the body of a procedure or user-defined function, a compiler error occurs and no object (.OBJ) file is generated.

The maximum number of static variables in a program is limited only by available memory.

Notes

. Inspecting static variables within the Debugger: To access static variable names within the Harbour debugger, you must compile program (.prg) files using the /B option so that static variable information is included in the object (.OBJ) file.

. Macro expressions: You may not refer to static variables within macro expressions or variables. If a static variable is referred to within a macro expression or variable, a private or public variable of the same name will be accessed instead. If no such variable exists, a runtime error will be generated.

. Memory files: Static variables cannot be SAVED to or RESTOREd from memory (.mem) files.

. Type of a static local variable: Since TYPE() uses the macro operator (&) to evaluate its argument, you cannot use TYPE() to determine the type of a local or static variable or an expression containing a local or static variable reference. The VALTYPE() function provides this facility by evaluating the function argument and returning the data type of its return value.

Examples

       .  This example declares static variables both with and without
          initializers:
          STATIC aArray1[20, 10], aArray2[20][10]
          STATIC cVar, cVar2
          STATIC cString := "my string", var
          STATIC aArray := {1, 2, 3}
       .  This example manipulates a static variable within a user-
          defined function.  In this example, a count variable increments
          itself each time the function is called:
          FUNCTION MyCounter( nNewValue )
             STATIC nCounter := 0         // Initial value assigned once
             IF nNewValue != NIL
                nCounter:= nNewValue      // New value for nCounter
             ELSE
                nCounter++                // Increment nCounter
             ENDIF
             RETURN nCounter
       .  This example demonstrates a static variable declaration that
          has filewide scope.  In this code fragment, aArray is visible to both
          procedures that follow the declaration:
          STATIC aArray := {1, 2, 3, 4}
          FUNCTION One
             ? aArray[1]                  // Result: 1
             RETURN NIL
          FUNCTION Two
             ? aArray[3]                  // Result: 3
             RETURN NIL

Seealso

FUNCTION, LOCAL, PARAMETERS, PRIVATE, PROCEDURE, PUBLIC

RUN

RUN

Executes an operating system command.

Syntax

       RUN <CommandLine>

Arguments

<CommandLine> This is the command to be executed on the operating system level. It can be specified as literal or as character string in parentheses.

Description

The RUN command opens a new command shell and executes the operating system commands specified with <CommandLine>.

RUN does not return until <CommandLine> is completed by the operating system. When RUN is complete, the new command shell is closed.

Example

       // The example executes the DIR command, directs its output into
       // a file and displays the result with Notepad.exe
       PROCEDURE Main
          LOCAL cCommand := "Notepad.exe files.lst"

          CLS

          ? "DIR command"
          RUN dir > files.lst

          ? "Executing Notepad.exe"
          RUN (cCommand)

          ? "Done"
       RETURN

Seealso

( ), FUNCTION, PROCEDURE

RETURN

RETURN

Terminate a procedure, user-defined function, or program

Syntax

       RETURN [<exp>]

Arguments

<exp> is an expression of any type that evaluates to the return value for user-defined functions. If a user-defined function terminates without executing a RETURN statement, the return value is NIL.

Description

RETURN terminates a procedure, user-defined function, or program by returning control to either the calling procedure or user-defined function. When RETURN executes in the highest level procedure, control passes to the operating system. All private variables created and local variables declared in the current procedure or user-defined function are released when control returns to the calling procedure.

There can be more than one RETURN in a procedure or user-defined function. A procedure or user-defined function need not, however, end with a RETURN. Since user-defined functions must return values, each must contain at least one RETURN statement with an argument.

Note: A procedure or user-defined function definition is terminated by a PROCEDURE statement, a FUNCTION statement, or end of file but not by a RETURN statement.

Notes

. Arrays: Since array is a data type like any other data type, instances of array type are really values like character strings and, therefore, can be RETURNed from a user-defined function.

. RETURN TO MASTER: Harbour does not support RETURN TO MASTER or any other form of RETURN specifying the level to which the call is to return. You can, however, simulate these operations with BEGIN SEQUENCE…END.

Examples

       .  These examples illustrate the general form of the RETURN
          statement in a procedure and in a user-defined function:
          PROCEDURE <idProcedure>
             //
             <statements>...
             //
             RETURN
          FUNCTION <idFunction>
             //
             <statements>...
             //
             RETURN <expReturn>
       .  This example returns an array, created in a user-defined
          function, to a calling procedure or user-defined function:
          FUNCTION PassArrayBack
             PRIVATE aArray[10][10]
             aArray[1][1] = "myString"
             RETURN aArray

Seealso

BEGIN SEQUENCE, FUNCTION, LOCAL, PRIVATE, PROCEDURE

PUBLIC

PUBLIC

Create and initialize public memory variables and arrays

Syntax

       PUBLIC <identifier> [[:= <initializer>], ... ]

Arguments

<identifier> is the name of a public variable or array to create. If the <identifier> is followed by square brackets ([ ]), it is created as an array. If the <identifier> is an array, the syntax for specifying the number of elements for each dimension can be array[<nElements>, <nElements2>, …] or array[<nElements>][<nElements2>]…. The maximum number of elements per dimension is 4096. The maximum number of dimensions per array is limited only by available memory.

<initializer> is the optional assignment of a value to a new public variable. Array identifiers, however, cannot be given values with an <initializer>. An <initializer> for a public variable consists of the inline assignment operator (:=) followed by any valid Harbour expression including a literal array. Except for arrays, if no <initializer> is specified, public variables are initialized to false (.F.). This is an exception to the general rule that uninitialized variables are NIL. With arrays, however, the initial value of each element is NIL.

A list of variables and arrays can be created and, optionally, initialized with one PUBLIC statement if each definition is separated by a comma.

Description

The PUBLIC statement creates variables and arrays visible to all procedures and user-defined functions in a program. Public variables exist for the duration of the program or until explicitly released with CLEAR ALL, CLEAR MEMORY, or RELEASE. Declaring private, local, or static variables or arrays with the same name as existing public variables temporarily hides those public variables until the overriding variables are released or are no longer visible. An attempt to create a public variable with the same name as an existing and visible private variable is simply ignored (see Notes below for an exception).

Attempting to specify a PUBLIC variable that conflicts with a previous FIELD, LOCAL, or STATIC declaration of the same name results in a fatal compiler error. This is true regardless of the scope of the declaration.

PUBLIC statements are executable statements and, therefore, must be specified within the body of a procedure or user-defined function definition. They also must follow all compile-time declarations, such as FIELD, LOCAL, MEMVAR, and STATIC.

The maximum number of public and private variables and arrays that can simultaneously exist in a single program is 2048.

For more information on variable declarations and scoping, refer to the Variables section in the “Basic Concepts” chapter.

Notes

. Public array name conflicts with existing private variables: The statement, PUBLIC x[10], will not create the public array x if there is already a private or public variable x. It will, however, destroy the contents of the existing x, replacing it with a reference to a ten-element array.

Examples

       .  This example creates two PUBLIC arrays and one PUBLIC
          variable:
          PUBLIC aArray1[10, 10], var2
          PUBLIC aArray2[20][10]
       .  The following PUBLIC statements create variables and
          initialize them with values:
          PUBLIC cString := SPACE(10), cColor := SETCOLOR()
          PUBLIC aArray := {1, 2, 3}, aArray2 := ARRAY(12, 24)

Seealso

LOCAL, MEMVAR, PARAMETERS, PRIVATE, STATIC

PROCEDURE

PROCEDURE

Declare a procedure name and formal parameters

Syntax

       [STATIC] PROCEDURE <idProcedure> [(<idParam list>)]
              [FIELD <idField list> [IN <idAlias>]
              [LOCAL <identifier> [[:= <initializer>], ... ]]
              [MEMVAR <identifier list>]
              [STATIC <identifier> [[:= <initializer>], ... ]]
              .
              . <executable statements>
              .
              [RETURN]

Arguments

<idProcedure> is the name of the procedure to be declared. Procedure names can be any length, but only the first 10 characters are significant. Names can contain any combination of characters, numbers, or underscores, but leading underscores are reserved.

<idParam list> is the declaration of one or more parameter variables. Variables specified in this list are declared local.

STATIC PROCEDURE declares a procedure that can be called only by procedures and user-defined functions declared in the same program (.prg) file.

FIELD declares a list of identifiers, <idField list>, to use as field names whenever encountered. If the IN clause is specified, referring to the declared name, <idAlias> is a reference to the appropriate work area of the specified database.

LOCAL declares and optionally initializes a list of variables or arrays whose visibility and lifetime is the current procedure.

<identifier>, <identifier list> is a label or labels used as variable or array names. If the <identifier> is followed by square brackets ([ ]), it is created as an array. If the <identifier> is an array, the syntax for specifying the number of elements for each dimension can be array[<nElements>, <nElements2>, …] or array[<nElements>][<nElements2>]… The maximum number of elements per dimension is 4096. The maximum number of dimensions per array is limited only by available memory.

<initializer> is the value to which an optional inline assignment sets the <identifier> variable–essentially, the assignment operator, (:=) –followed by any valid Harbour expression, including a literal array. If no <initializer> is specified, variables are initialized to NIL. In the case of arrays, all element are initialized to NIL.

MEMVAR declares a list of identifiers, <identifier list>, to use as private or public memory variables or arrays whenever encountered.

STATIC declares and, optionally, initializes a list of variables or arrays whose visibility is the current procedure and whose lifetime is the duration of the program.

RETURN passes control back to the calling procedure or user-defined function. If a RETURN is not specified, control passes back to the calling routine when the procedure definitions ends. In all cases, the compiler terminates the procedure definition when it encounters another PROCEDURE statement, FUNCTION statement, or end of file character.

Description

The PROCEDURE statement declares a procedure and an optional list of local variables to receive parameters passed from a calling routine. A procedure is a subprogram comprised of a set of declarations and statements executed whenever you refer to <idProcedure>, followed by an open and close parentheses pair or with the DO statement. A procedure definition begins with a PROCEDURE statement and ends with the next PROCEDURE statement, FUNCTION statement, or end of file.

Procedures that encapsulate computational blocks of code provide readability and modularity, isolate change, and help manage complexity.

A procedure in Harbour is the same as a user-defined function, with the exception that it always returns NIL. Each procedure must begin with a PROCEDURE statement and may, optionally, contain a RETURN statement to return control to the calling procedure or user-defined function. A RETURN statement, however, is not required. Procedure declarations cannot be nested within other procedure definitions.

The visibility of procedure names falls into two classes. Procedures that are visible anywhere in a program are referred to as public procedures and declared with a PROCEDURE statement. Procedures that are visible only within the current program (.prg) file are referred to as static procedures and declared with a STATIC PROCEDURE statement. Static procedures have filewide scope.

Static procedures are quite useful for a number of reasons. First, they limit visibility of a procedure name thereby restricting access to the procedure. Because of this, subsystems defined within a single program (.prg) file can provide an access protocol with a series of public procedures and conceal the implementation details of the subsystem within static procedures and functions. Second, since the static procedure references are resolved at compile time, they preempt references to public procedures and functions which are resolved at link time. This ensures that, within a program file, a reference to a static procedure executes that procedure if there is a name conflict with a public procedure or function.

For more information on procedures, variable declarations, and parameter passing, refer to the “Basic Concepts” chapter.

Notes

. Calling a procedure: There are two ways to call a procedure in Harbour. The first and preferred way is the function-calling convention. Here you call the procedure as you would a Harbour function on a line by itself:

<idProcedure>([<argument list>])

The second and obsolete way is the command-calling convention using the DO…WITH command. The two methods of calling procedures differ only in the default method of passing parameters. The function- calling convention passes variables by value as a default, whereas the command-calling convention passes them by reference as a default.

A procedure can also be called as an aliased expression if it is prefaced with an alias and invoked using the function-calling convention, like this: <idAlias> ->(<idProcedure>(<argument list>)) When called as an aliased expression, the work area associated with <idAlias> is selected, the procedure is executed, and then the original work area is reselected. Like an expression or function, an aliased procedure can be specified on a line by itself. A procedure in Harbour may call itself recursively. This means you can call a procedure in the same procedure definition.

. Parameters: Procedures like user-defined functions can receive parameters passed from a calling procedure, user-defined function, or the DOS command line. A parameter is a place for a value or reference. In Harbour there are two ways to receive parameters: a list of local variable names can be declared as a part of the PROCEDURE declaration (referred to as formal parameters), or a list of private variables can be specified in a separate PARAMETERS statement. Note that you cannot mix a declaration of formal parameters with a PARAMETERS statement. Attempting this will cause a fatal compiler error.

Procedures receive parameters in the order passed. In Harbour the number of parameters need not match the number of arguments passed. Arguments can be skipped or left off the end of the argument list. A parameter not receiving a value or reference is initialized to NIL. If arguments are specified, PCOUNT() returns the position of the last argument passed.

Parameters specified in a procedure can receive arguments passed by value or by reference. The default method for expressions and variables depends on the calling convention. With the function-calling convention, the default passing method for expressions and variables is by value. This includes variables containing references to arrays and objects. With the command- calling convention, the default method for passing variables is by reference except for field variables, which are always passed by value. Whenever a field variable is passed, it must be specified enclosed in parentheses unless declared with the FIELD statement. Failure to do so will generate a runtime error.

Examples

       .  This example shows a skeleton of a typical Harbour
          procedure that uses lexical variables:
          PROCEDURE Skeleton( cName, cClassRoom, nBones, ;
                                  nJoints )
             LOCAL nCrossBones, aOnHand := {"skull", ;
                                           "metacarpals"}
             STATIC nCounter := 0
             .
             . <executable statements>
             .
             RETURN
       .  This example determines whether an argument was skipped by
          comparing the parameter to NIL:
          PROCEDURE MyProc( param1, param2, param3 )
             IF param2 != NIL
                param2 := "default value"
             ENDIF
             .
             . <statements>
             .
             RETURN
       .  This example invokes the procedure, UpdateAmount(), as an
          aliased expression:
          USE Invoices NEW
          USE Customer NEW
          Invoices->(UpdateAmount(Amount + Amount * nInterest))

Seealso

FUNCTION, LOCAL, PARAMETERS, PCOUNT(), RETURN, STATIC

PRIVATE

Create and initialize private memory variables and arrays

Syntax

       PRIVATE <identifier> [[:= <initializer>], ... ]

Arguments

<identifier> is the name of a private variable or array to create. If the <identifier> is followed by square brackets ([ ]), an array is created and assigned to the <identifier>. When the <identifier> specification indicates an array, the syntax for specifying the number of elements for each dimension can be array[<nElements>, <nElements2>, …] or array[<nElements>][<nElements2>]… The maximum number of elements per dimension is 4096. The maximum number of dimensions is limited only by available memory.

<initializer> is the optional assignment of a value to a new private variable. An array cannot be given values with an <initializer>. An <initializer> for a private variable consists of the inline assignment operator (:=) followed by any valid Harbour expression including a literal array. If no explicit <initializer> is specified, the variable is initialized to NIL. In the case of an array, each element is initialized to NIL.

You can create and, optionally, initialize a list of variables and arrays with one PRIVATE statement if the definitions are separated by commas.

Description

The PRIVATE statement creates variables and arrays visible within the current and invoked procedures or user-defined functions. This class of variable is said to have dynamic scope. Private variables exist for the duration of the active procedure or until explicitly released with CLEAR ALL, CLEAR MEMORY, or RELEASE. When a private variable or array is created, existing and visible private and public variables of the same name are hidden until the current procedure or user-defined function terminates.

Attempting to specify a PRIVATE variable that conflicts with a previous FIELD, LOCAL, or STATIC declaration of the same name results in a fatal compiler error. This is true regardless of the scope of the declaration.

PRIVATE statements are executable statements and, therefore, must be specified within the body of a procedure or user-defined function and must follow all variable declarations, such as FIELD, LOCAL, MEMVAR, and STATIC.

In addition to the PRIVATE statement, private variables are also created in two other ways:

. Assignment to a variable that does not exist or is not visible will create a private variable .

Parameters received using the PARAMETERS statement are created as private variables with the same lifetime and visibility.

No more than 2048 private and public variables and arrays can simultaneously exist in a single program.

For more information on variable declarations and scoping, refer to the Variables section in the “Basic Concepts” chapter.

Notes

. Compatibility: The ALL, LIKE, and EXCEPT clauses of the PRIVATE statement supported by other dBASE dialects are not supported.

Examples

       .  This example creates two PRIVATE arrays and three other
          PRIVATE variables:
          PRIVATE aArray1[10], aArray2[20], var1, var2, var3
       .  This example creates a multidimensional private array using
          each element addressing convention:
          PRIVATE aArray[10][10][10], aArray2[10, 10, 10]
       .  This example uses PRIVATE statements to create and initialize
          arrays and variables:
          PRIVATE aArray := { 1, 2, 3, 4 }, ;
                aArray2 := ARRAY(12, 24)
          PRIVATE cChar := SPACE(10), cColor := SETCOLOR()

Seealso

FIELD, LOCAL, MEMVAR, PARAMETERS, PUBLIC, STATIC