STORE

STORE*

Assign a value to one or more variables

Syntax

      STORE <exp> TO <idVar list>
         <idVar> = <exp>
         <idVar> := [ <idVar2> := ...] <exp>

Arguments

<exp> is a value of any data type that is assigned to the specified variables.

TO <idVar list> defines a list of one or more local, static, public, private, or field variables that are assigned the value <exp>. If any <idVar> is not visible or does not exist, a private variable is created and assigned <exp>.

Description

STORE assigns a value to one or more variables of any storage class. The storage classes of Clipper variables are local, static, field, private, and public. STORE is identical to the simple assignment operators (=) and (:=). In fact, a STORE statement is preprocessed into an assignment statement using the inline operator (:=). Like all of the assignment operators, STORE assigns to the most recently declared and visible variable referenced by <idVar>. If, however, the variable reference is ambiguous (i.e., not declared at compile time or not explicitly qualified with an alias), it is assumed to be MEMVAR. At runtime, if no private or public variable exists with the specified name, a private variable is created.

To override a declaration, you can specify the <idVar> prefaced by an alias. If <idVar> is a field variable, use the name of the work area. For private and public variables, you can use the memory variable alias (MEMVAR->). To assign to a field variable in the currently selected work area (as opposed to a particular named work area), you can use the field alias (FIELD->).

As a matter of principle, all variables other than field variables should be declared. Preface field variables with the alias. Use of private and public variables is discouraged since they violate basic principles of modular programming and are much slower than local and static variables.

Note that the STORE command is a compatibility command and not recommended for any assignment operation. Clipper provides assignment operators that supersede the STORE command, including the inline assignment operator (:=), the increment and decrement operators (++) and (–), and the compound assignment operators (+=, -=, *=, /=). Refer to the Operators and Variables sections of the “Basic Concepts” chapter in the Programming and Utilities Guide for more information.

Notes

. Assigning a value to an entire array: In Clipper, neither the STORE command nor the assignment operators can assign a single value to an entire array. Use the AFILL() function for this purpose.

. Memo fields: Assigning a memo field to a variable assigns a character value to that variable.

Examples

      .  These statements create and assign values to undeclared
         private variables:

      STORE "string" TO cVar1, cVar2, cVar3
      cVar1:= "string2"
      cVar2:= MEMVAR->cVar1

      .  These statements assign multiple variables using both STORE
         and the inline assignment operator (:=).  The methods produce
         identical code:

      STORE "value" to cVar1, cVar2, cVar3
      cVar1 := cVar2 := cVar3 := "value"

      .  These statements assign values to the same field referenced
         explicitly with an alias.  The first assignment uses the field alias
         (FIELD->), where the second uses the actual alias name:

      USE Sales NEW
      FIELD->CustBal = 1200.98
      Sales->CustBal = 1200.98

Seealso

AFILL(), LOCAL, PRIVATE, PUBLIC, RELEASE, REPLACE

SAVE

SAVE

Save variables to a memory (.mem) file

Syntax

      SAVE TO <xcMemFile> [ALL [LIKE | EXCEPT <skeleton>]]

Arguments

<xcMemFile> is the memory (.mem) file to SAVE to disk. You may specify the file name as a literal string or as a character expression enclosed in parentheses. If you specify no extension, the file is created with a .mem extension.

ALL [LIKE|EXCEPT <skeleton>] defines the set of visible private and public memory variables to save to <xcMemFile>. <skeleton> is the wildcard mask that characterizes a group of memory variables to SAVE. The wildcard characters supported are * and ?.

Description

SAVE copies public and private memory variables visible within the current procedure or user-defined function to a memory (.mem) file. Arrays and local and static variables, however, cannot be SAVEd. When variables are SAVEd, they are copied without any reference to scope. Variables hidden by PRIVATE or LOCAL declarations are not SAVEd.

If you specify the ALL LIKE clause, variable names matching the <skeleton> mask are saved. By contrast, if you specify ALL EXCEPT, variable names not matching the <skeleton> are saved.

You can specify a <skeleton> that includes wildcard characters. The * wildcard character matches any group of adjacent characters ending a variable name and can be specified only at the end of the <skeleton>. The ? wildcard character matches any single character and can be specified anywhere within the <skeleton>.

Examples

      .  This example saves all visible private and public variables to
         Temp.mem:

         PRIVATE cOne := "1"
         SAVE ALL TO Temp

      .  This example saves all visible private and public variables
         with names beginning with "c" to Myvars.mem:

         SAVE ALL LIKE c* TO MyVars

      .  This example saves all visible private and public variables
         with names that do not begin with "c" to Myvars2.mem:

         SAVE ALL EXCEPT c* TO MyVars2

Seealso

LOCAL, PRIVATE, PUBLIC, RESTORE

RESTORE

RESTORE

Retrieve memory variables from a memory (.mem) file

Syntax

      RESTORE FROM <xcMemFile> [ADDITIVE]

Arguments

<xcMemFile> is the memory (.mem) file to load from disk. If an extension is not specified, the extension .mem is assumed. The file name may be specified as a literal string or as a character expression enclosed in parentheses.

ADDITIVE causes memory variables loaded from the memory file to be added to the existing pool of memory variables.

Description

RESTORE is a memory variable command that recreates public and private variables previously SAVEd to a memory (.mem) file and initializes them with their former values. The scope of the variable is not SAVEd with the variable, but is instead established when the variable is RESTOREd. Arrays and local variables cannot be SAVEd or RESTOREd.

When memory variables are RESTOREd, they are recreated as private variables with the scope of the current procedure or user-defined function unless they exist as public variables and you specify the ADDITIVE clause. If ADDITIVE is specified, public and private variables with the same names are overwritten unless hidden with PRIVATE. If ADDITIVE is not specified, all public and private variables are released before the memory file is loaded.

Local and static variables are unaffected by RESTORE. If a local or static variable has been declared in the current procedure or user- defined function and a variable with the same name is RESTOREd, only the local or static variable is visible unless references to the RESTOREd variable are prefaced with the MEMVAR alias.

Examples

      .  This example demonstrates a typical application of SAVE and
         RESTORE.  Here memory variables containing screens are SAVEd
         TO and RESTOREd FROM memory files:

      // Create and use a pseudoarray of screens
      SAVE SCREEN TO cScreen1
      SAVE ALL LIKE cScreen* TO Screens
      //
      <statements>...
      //
      RESTORE FROM Screens ADDITIVE
      nNumber = "1"
      RESTORE SCREEN FROM ("cScreen" + nNumber)

Seealso

LOCAL, PRIVATE, PUBLIC, SAVE

RELEASE

RELEASE

Delete public and private memory variables

Syntax

      RELEASE <idMemvar list>
         RELEASE ALL [LIKE | EXCEPT <skeleton>]

Arguments

<idMemvar list> is a list of private or public variables or arrays to delete.

ALL [LIKE|EXCEPT <skeleton>] defines the set of visible private memory variables to assign, or to exclude from assignment of, a NIL value. <skeleton> is the wildcard mask to specify a group of memory variables to delete. The wildcard characters supported are * and ?.

Description

RELEASE is a memory variable command that performs one of two actions depending on how it is specified. If RELEASE is specified with <idMemvar list>, the specified public and private memory variables and/or arrays are deleted from memory. Previous hidden instances (public or private variables defined in higher-level procedures) become accessible upon termination of the procedure where the variable was originally created.

If RELEASE is specified with any form of the ALL clause, private memory variables created at the current procedure level are assigned a NIL and not deleted until the current procedure or user-defined function terminates. Public variables are unaffected by this form of the RELEASE command. To release public variables, you must RELEASE them explicitly or use CLEAR MEMORY.

Local or static variables are not affected by the RELEASE command. Local variables are released automatically when the procedure or user- defined function (where the variables were declared) terminates. Static variables cannot be released since they exist for the duration of the program.

Seealso

CLEAR MEMORY, LOCAL, PRIVATE, PUBLIC, QUIT

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

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

FUNCTION

FUNCTION

Declare a user-defined function name and formal parameters

Syntax

       [STATIC] FUNCTION <idFunction>[(<idParam list>)]
              [LOCAL <identifier> [[:= <initializer>], ... ]]
              [STATIC <identifier> [[:= <initializer>], ... ]]
              [FIELD <identifier list> [IN <idAlias>]]
              [MEMVAR <identifier list>]
              .
              . <executable statements>
              .
              RETURN <exp>

Arguments

<idFunction> is the name of the user-defined function to be declared. User-defined function names can be any length, but only the first 10 characters are significant. Names can contain any combination of characters, numbers, or underscores, but must begin with a character or an underscore. Leading underscores are not recommended since they are reserved for internal functions.

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

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

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

STATIC declares and optionally initializes a list of variables or arrays whose visibility is the current user-defined function and lifetime is the duration of the program.

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.

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

<identifier> and <identifier list> are labels to be used as variable or array names.

<initializer> is a value to which an array or variable is originally set in an inline expression. RETURN <exp> passes control back to the calling procedure or user-defined function, returning the result of <exp> as the value of the function. Each function must have at least one

RETURN statement that returns a value. RETURN statements can occur anywhere in the body of a function.

Description

The FUNCTION statement declares a user-defined function and an optional list of local variables to receive parameters often referred to as formal parameters. A user-defined function is a subprogram comprised of a set of declarations and statements executed whenever you refer to <idFunction> followed by an open and closed parentheses pair. A function definition begins with a FUNCTION statement which is the FUNCTION declaration and ends with the next FUNCTION statement, PROCEDURE statement, or end of file.

Functions encapsulate a computational block of code and then later create expressions using the value returned. Functions and procedures increase both readability and modularity, isolate change, and help manage complexity.

A function in Harbour is the same as a procedure, except that it must return a value. The returned value can be any data type including an array, a code block, or NIL. Each function must begin with a FUNCTION statement and contain at least one RETURN statement with an argument. Function declarations cannot be nested within other function definitions. A user-defined function can be used wherever standard functions are supported, including expressions.

The visibility of function names falls into two classes. Functions that are visible anywhere in a program are referred to as public functions and declared with a FUNCTION statement. Functions that are visible only within the current program (.prg) file are referred to as static functions and declared with a STATIC FUNCTION statement.

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

For more information on user-defined functions, variable declarations, and parameter passing, refer to the “Basic Concepts” chapter.

Notes

. Calling a user-defined function: Use the same notation to call a user-defined function as when calling a standard Harbour function: <idFunction>([<argument list>])

You can call a user-defined function within an expression or on a line by itself. If called on a line by itself, the return value is ignored.

You can also call a user-defined function as an aliased expression by prefacing it with an alias and enclosing it in parentheses: <idAlias>->(<idFunction>(<argument list>))

When you call a user-defined function as an aliased expression, the work area associated with <idAlias> is selected, the expression is executed, and the original work area is then reselected. You can specify an aliased expression on a line by itself, as you would any other expression.

A user-defined function in Harbour may call itself recursively. This means you can make a reference to a user-defined function in statements or expressions of the same user-defined function definition.

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

Functions receive parameters in the order passed. In Harbour, the number of parameters does not have to match the number of arguments passed. You can skip arguments or omit them from the end of the argument list. A parameter not receiving a value or reference is initialized to NIL. You can skip a parameter by passing NIL. If arguments are specified, PCOUNT() returns the position of the last argument passed. (If more arguments are passed than are parameters, they are ignored.)

Parameters specified in a user-defined function can receive arguments passed by value or reference. The default method for expressions and variables is by value. This includes variables that contain references to arrays and objects. All variables except field variables, when prefaced with the pass-by-reference operator (@), are passed by reference. Field variables cannot be passed by reference and are always passed by value.

Examples

       .  This example demonstrates a user-defined function that formats
          numeric values as currency:
       ? Currency( 1000 )               // Result: Þ1,000.00
       FUNCTION Currency( nNumber )
          LOCAL cNumber
          IF nNumber < 0
             cNumber := TRANSFORM(-1 * nNumber, ;
                   "999,999,999,999.99")
             cNumber := PADL("(Þ" + LTRIM(cNumber) + ")", ;
                   LEN(cNumber))
          ELSE
             cNumber := TRANSFORM(nNumber, ;
                   "999,999,999,999.99")
             cNumber := PADL("Þ" + LTRIM(cNumber), ;
                   LEN(cNumber))
          ENDIF
          RETURN cNumber
       . This example demonstrates a user-defined function that takes a
          character string formatted as a comma-separated list and returns 
          an array with one element per item:
       aList := ListAsArray("One, Two")
       // Result: {"One", "Two"}
       FUNCTION ListAsArray( cList )
          LOCAL nPos
          // Define an empty array
          LOCAL aList := {}
          //
          DO WHILE (nPos := AT(",", cList)) != 0
             // Add a new element
             AADD(aList, SUBSTR(cList, 1, nPos - 1))
             cList := SUBSTR(cList, nPos + 1)
          ENDDO
          AADD(aList, cList)
          //
          // Return the array
          RETURN aList
       .  This example checks for a skipped argument by comparing
          the parameter to NIL:
       FUNCTION MyFunc( param1, param2, param3 )
          IF param2 == NIL
             param2 := "default value"
          ENDIF
          .
          . <statements>
          .
          RETURN NIL
       .  This example uses the user-defined function, Currency()
          (defined above), as an aliased expression:
       USE Invoices NEW
       USE Customer NEW
       ? Invoices->(Currency(Amount))

Seealso

LOCAL, PARAMETERS, PCOUNT(), PRIVATE, PROCEDURE, RETURN