FOR EACH
Iterates elements of data types that can be seen as a collection.
Syntax
FOR EACH <element> IN <array>|<object>|<string>
<statements>
The name of a variable that gets assigned a new value on each iteration.
IN <array>
This is a value of data type Array. The FOR EACH loop iterates all array elements in the first dimension and assigns their values to <element>.
IN <object>
This is a value of data type Object. The FOR EACH loop iterates all instance variables of the object and assigns their values to <element>.
IN <string>
This is a value of data type Character string. The FOR EACH loop iterates all individual characters of the string and assigns them to <element>.
LOOP
The LOOP statement unconditionally branches to the FOR EACH statement, i.e. to the begin of the loop, where the next value is assigned to <element>.
EXIT
The EXIT statement unconditionally terminates the FOR EACH loop and branches to the statement following NEXT.
Description
The FOR EACH statement forms a control structure that executes a block of statements for a data type containing multiple elements. This can be data of type Array, Object or Character string. The loop iterates all elements contained in the data and assigns the value of the next element to <element> on each iteration.
FOR EACH is similar to the regular FOR loop. But it completes considerably faster than a FOR loop, since there is no explicit loop counter. In contrast, FOR EACH uses a n implicit loop counter whose value can be queried using the functionHB_EnumIndex(). Other than this, LOOP and EXIT statements within the loop are treated the same as in a FOR loop.
When FOR EACH statements are nested, each loop maintains its own counter, i.e. HB_EnumIndex() retrieves the counter of the loop that is currently executed. When the FOR EACH loop is finished, its loop counter is set to 0.
FOR EACH
Info
See also: AEval(),HB_EnumIndex(),FOR,DO CASE,DO WHILE,IF,SWITCH,WITH OBJECT Category: Control structures,Statements,xHarbour extensions
Example
// The example demonstrates the FOR EACH statement using two // nested loops. The outer loop iterates an array while the // inner loop iterates character strings.
PROCEDURE Main()
LOCAL aArray := { "Hello", "World" } LOCAL cString, cChar
FOR EACH cString IN aArray
? "--- Outer loop ---"
? HB_EnumIndex(), cString
? "--- Inner loop ---"
FOR EACH cChar IN cSTring
? HB_EnumIndex(), cChar NEXT
NEXT
? "--- End ---"
? HB_EnumIndex() RETURN
/* Output of example:
Outer loop
FUNCTION
FUNCTION
Declares a function along with its formal parameters.
Syntax
[STATIC] FUNCTION <funcName>( [<params,...>] ) [FIELD <fieldName,...> [IN <aliasName>]]
[MEMVAR <var_Dynamic,...>]
[LOCAL <var_Local> [:= <expression>] ,... ] [STATIC <var_Static> [:= <expression>] ,... ]
<Statements>
RETURN <retVal>
Arguments
FUNCTION <funcName>( [<params,...>] )
This is the symbolic name of the declared function. It must begin with a letter or underscore followed by digits, letters or underscores. The symbolic name can contain up to 63 characters.
Optionally, the names of parameters <params,...> accepted by the function can be specified as a comma separated list. These function parameters have LOCAL scope within the function.
When the function is declared as STATIC FUNCTION, it is only visible within the PRG file that contains the function declaration and cannot be invoked from elsewhere.
FIELD <fieldName>
An optional list of field variables to use within the FUNCTION can be declared with theFIELD statement.
MEMVAR <var_Dynamic>
If dynamic memory variables, i.e. PRIVATE or PUBLIC variables, are used in the function, they are declared with theMEMVARstatement.
LOCAL <var_Local> [:= <expression>]
Local variables are declared and optionally initialized using theLOCALstatement.
STATIC <var_Static> [:= <expression>]
Static variables are declared and optionally initialized using theSTATICstatement.
RETURN <retVal>
The RETURN statement terminates a function and branches control back to the calling routine, returning the value <retVal> to it.
Description
The FUNCTION statement declares a function along with an optional list of parameters accepted by the function. Statements programmed in the function body form a self-contained part of a program that is executed when a function is called. Thus, tasks of a program can be split into several functions, each of which performs a sub-task when invoked.
FUNCTION The body of a function ends with the next FUNCTION, PROCEDURE or CLASS declaration, or at the end of file, which implies that function declarations cannot be nested.
The execution of a function ends when a RETURN statement is encountered in the function body, which must return a value <retVal> to the calling routine. This value is mandatory for functions and can be of any data type. The RETURN value is the only difference between functions and procedures.
When a function is declared with the STATIC modifier, its visibility is restricted to the PRG file that contains the STATIC FUNCTION declaration. The names of STATIC functions are resolved by the compiler and do not exist at runtime of a program. The names of non-STATIC functions, also referred to as public functions, are resolved by the linker and do exist at runtime. Thus, public functions can be accessed by the Macro operator (&) while STATIC functions cannot.
It is possible to declare STATIC functions with the same symbolic name in different PRG files. A name conflict to a public function with the same name declared in another PRG file does not arise.
However, the symbolic names of public functions, procedures or classes must always be unique.
When a function is invoked with values being passed to it, they are assigned to the formal parameters declared with <params,...>. All variables declared in this list are LOCAL variables and their visibility is restricted to the statements programmed in the function body.
The number of values passed to a function does not need to match the number of parameters declared.
When fewer values are passed, the corresponding parameters are initialized with NIL. When more values are passed, the additional values are not asssigned to parameters but can be retrieved using functionHB_AParams().
Undefined parameter list a function can be declared with an undefined parameter list using the ellipsis sign (...) as a placeholder for the parameter list. A function declared in such way can receive an unknown number of parameters.
Info
See also: FIELD,HB_AParams(),LOCAL,MEMVAR,METHOD (declaration),PARAMETERS, PCount(),PRIVATE,PROCEDURE,PUBLIC,RETURN,STATIC
Category: Declaration,Statements
Examples
// The example shows two functions used to calculate the number of // days for a month.
PROCEDURE Main
? DaysOfMonth( StoD( "20000201" ) ) // Result: 29
? DaysOfMonth( StoD( "20010201" ) ) // Result: 28
? DaysOfMonth( StoD( "20040201" ) ) // Result: 29
? DaysOfMonth( StoD( "20050301" ) ) // Result: 31
? DaysOfMonth( StoD( "20051101" ) ) // Result: 30 RETURN
FUNCTION DaysOfMonth( dDate ) LOCAL nMonth
IF Valtype( dDate ) <> "D"
dDate := Date() ENDIF
nMonth := Month( dDate )
FUNCTION
RETURN IIf( IsLeapYear( dDate ), 29, 28 ) ELSEIF nMonth $ {4,6,9,11}
RETURN 30 ENDIF
RETURN 31
STATIC FUNCTION IsLeapYear( dDate ) LOCAL nYear := Year( dDate )
RETURN ( nYear % 4 == 0 ) .OR. ( nYear % 400 == 0 )
// The example demonstrates how an unknown number of command line // arguments passed to an xHarbour application can be processed.
PROCEDURE Main( ... )
LOCAL aArg := HB_AParams() LOCAL cArg
FOR EACH cArg IN aArg DO CASE
CASE Upper( cArg ) IN ("-H/H-?/?")
? "Help requested"
CASE .NOT. cArg[1] IN ( "-/" )
?? " argument:", cArg CASE Upper( cArg ) IN ("-X/X")
? "Execution requested"
OTHERWISE
? "Unknown:", cArg ENDCASE
NEXT RETURN
GLOBAL
GLOBAL
Declares and optionally initializes a GLOBAL memory variable.
Syntax
GLOBAL <varName> [:= <xValue> ] GLOBAL EXTERNAL <extVarName>
Arguments
GLOBAL <varName>
<varName> is the symbolic name of the global variable to declare.
<xValue>
<xValue> is an optional value to assign to the GLOBAL variable after being declared. To assign a value, the inline assignment operator (:=) must be used. The simple assignment operator (=) cannot be used. Only literal values are allowed for <xValue> when declaring GLOBAL variables.
GLOBAL EXTERNAL <extVarName>
This is the name of a GLOBAL variable that is declared in another PRG file and must be referred to in the current PRG file.
Description
The GLOBAL statement declares a memory variable that has GLOBAL scope. Global variables are resolved by the compiler, i.e. their symbolic name cannot be retrieved during runtime. This makes access to GLOBAL variables much faster than to memory variables of PRIVATE or PUBLIC scope, whose symbolic variable names exist at runtime.
The names of GLOBAL variables cannot be included in macro-expressions since they cannot be resolved by the macro operator (&). This operator requires the symbolic name of a variable to exist at runtime.
The lifetime of GLOBAL variables is identical with the lifetime of a program. They are visible and accessible throughout the functions and procedures of all PRG files that declare or refer to global variables.
Variable of other types cannot have the same symbolic name as a GLOBAL variable since a global variable's name must be unique for all modules accessing such a variable. In addition, a GLOBAL can only be declared in one PRG file using the GLOBAL statement. When a global variable must be accessed in another PRG file, it must be referred to using the GLOBAL EXTERNAL statement.
Info
See also: LOCAL,MEMVAR,PRIVATE,PUBLIC,STATIC Category: Declaration,Statements,xHarbour extensions
Example
// The example demonstrates how to declare/initialize a global variable // in one file, while it is referred to in a second file.
GLOBAL
GLOBAL gName := "My Global"
PROCEDURE Main
? gName // result: My Global
Test()
? gName // result: New Name
RETURN
** Global2.prg
GLOBAL EXTERNAL gName PROCEDURE Test
gName := "New Name"
RETURN
HIDDEN:
HIDDEN:
Declares the HIDDEN attribute for a group of member variables and/or methods.
Syntax
HIDDEN:
Description
The HIDDEN: attribute restricts access to member variables and methods of a class. Hidden members can only be accessed in the methods of the class(es) declared in a PRG module. It is the most
restrictive attribute. Hidden members cannot be accessed in the context of a FUNCTION or PROCEDURE, only in the context of a METHOD implemented in the declaring PRG module.
A less restrictive visibility attribute isPROTECTED:.
Info
See also: CLASS,DATA,EXPORTED:,METHOD (declaration),PROTECTED:
Category: Class declaration,Declaration,xHarbour extensions Header: hbclass.ch
Source: vm\classes.c
LIB: xhb.lib
DLL: xhbdll.dll
Example
// The example uses two files to demonstrate the protection // of a hidden member variable outside the declaring PRG module.
** MAIN.PRG uses the class PROCEDURE Main
LOCAL obj
obj := Test():new( "Hello", "World" )
obj:print() // result: Hello World
? obj:varTwo // result: World
? obj:varOne // Scope Violation <HIDDEN>: VARONE RETURN
** TEST.PRG declares the class
#include "Hbclass.ch"
CLASS Test HIDDEN:
DATA varOne EXPORTED:
DATA varTwo METHOD init METHOD print ENDCLASS
HIDDEN:
::varOne := p1 ::varTwo := p2 RETURN self
METHOD print CLASS Test
? ::varOne, ::varTwo RETURN self
IF
IF
Executes a block of statements based on one or more conditions.
Syntax
IF <Condition1>
<Statements>
[ ELSEIF <ConditionN>
<Statements> ] [ ELSE
<Statements> ] END[IF]
Arguments
IF <Condition1> [ELSEIF <ConditionN>]
<Condition1> to <ConditionN> are logical expressions. The statements following the first expression that yields the value .T. (true) are executed.
ELSE
If no condition results in the value .T. (true), the statements following the ELSE statement, if present, are executed.
Description
This statement executes a block of statements if the condition, related to the block, evaluates to true. If a condition evaluates to true, the following statements are executed until the next ELSEIF, ELSE or END[IF] statement is encountered.
If no condition in the entire IF...ELSEIF structure evaluates to true, control is passed to the first statement following the ELSE statement.
It is possible to include other control structures like DO WHILE and FOR within a single IF...ELSE structure.
Note: The IF...ELSEIF...ENDIF statement is equal to the DO CASE...ENDCASE statement.
Info
See also: BEGIN SEQUENCE,DO CASE,DO WHILE,FOR,If() | IIf(),SWITCH Category: Control structures,Statements
Example
// The example shows different forms of the IF END[IF] statement.
PROCEDURE Main
LOCAL nSalary := 1600 IF .F.
? "This will never be executed"
END IF .T.
? "This will always be executed"
IF
IF nSalary < 1000
? "Start looking for another job!"
ELSEIF nSalary < 1500
? "That's pretty good"
ELSEIF nSalary < 2000
? "You should be happy"
ELSE
? "You should be very happy"
ENDIF RETURN