FOR EACH..NEXT loop

/*
ForEach.prg
In addition clasical FOR..NEXT loop, Harbour offers another FOR loop :
FOR EACH..NEXT.
Simplest syntax of this loop is :
   FOR EACH <xValue> IN <xList>
     ...
   NEXT
For arrays, this structure is equivalent to :
FOR <nIndex> := 1 TO LEN( <aArray> )
   <xValue> := <aArray>[ nIndex ]
    ...
 NEXT

Relations and rules for <xValue> and <xList> in FOR EACH loop :

If <xList> is ... <xValue> is ...
 ----------------- ----------------
 <array>           an element of <array> 
 <string>          a single character in the <string>
 <hash>            <xValue> of <xKey> => <xValue> pair in the <hash>

Strings can be processed by indexing like arrays.

For string iteration, lib is xHB, so you need add
xHB lib calling in the your compile command:
   hbmk2 -lxHB ForEach
and add your source prg file :
   #include "xhb.ch"

*/
#include "xhb.ch"
PROCEDURE Main()

 CLS

 aFruits := { "appricot", "cherry", "melon", "pear", "grapes", "mulberry" }

 c1Fruit := '' // Variable for iteration value must be exist 
               // before FOR ... statement 
 ?
 ? "Traversing an array :"
 ?
 FOR EACH c1Fruit IN aFruits 
     ?? c1Fruit, ''
 NEXT 

 /* Note that this loop is equivalent to : 
    ?
    FOR n1Fruit := 1 TO LEN( aFruits )
        c1Fruit := aFruits[ n1Fruit ]
        ?? c1Fruit, ''
    NEXT */

 /* For a list in reverse order with classical FOR 
    ? 
    FOR n1Fruit := LEN( aFruits ) TO 1 STEP -1
        c1Fruit := aFruits[ n1Fruit ]
        ?? c1Fruit, ''
    NEXT */ 

/* ... and with FOR EACH*/
    ? 
    ? "Traversing an array in revers order :"
    ?
    FOR EACH c1Fruit IN aFruits DESCEND
        ?? c1Fruit, ''
    NEXT 

/* Sometime we needs something like this : 

    ?
    FOR n1Fruit := 1 TO LEN( aFruits )
       c1Fruit := aFruits[ n1Fruit ]
       ?? STR( n1Fruit, 2 ), ":", c1Fruit + ';'
    NEXT */ 

/* FOR EACH loop allow us using some 'internal' functions;
                          but a 'special' way : */
   ?
   ? "Traversing an array with indexs :"
   ?
   FOR EACH c1Fruit IN aFruits 
       ?? STR( c1Fruit:__ENUMINDEX(), 2 ), ":", c1Fruit + ';'
   NEXT 

   cString := "This is a string"

/* ... and a string example : 

   ?
   ? "Iterating a string by FOR .. NEXT :"
   ?
   FOR nIndex := 1 TO LEN( cString )
      ?? cString[ nIndex ]
   NEXT */

   c1Char := ''
   ? 
   ? "Iterating a string :"
   ?
   FOR EACH c1Char IN cString
       ?? c1Char
   NEXT 

   ? 
   ? "Iterating a string in reverse order :"
   ?
   FOR EACH c1Char IN cString DESCEND
      ?? c1Char
   NEXT 

   ?
   ? "Nested loop example :"
   aArray := { "This is", "an array" }
   c1String := ''

   FOR EACH c1String IN aArray
      ? "----- Outer Loop -----"
      ? c1String:__ENUMINDEX(), c1String
      ? "----- Inner Loop -----"
      FOR EACH c1Char IN c1String
         ? c1Char:__ENUMINDEX(), c1Char
      NEXT 
   NEXT 

   ?
   ? "Traversing a Hash : "
   ? "EnumKey EnumValue EnumBase[ EnumKey ]"
   ? "-------- ---------------- -------------------"
   hSoftWare := { => }
   HB_HKeepOrder( hSoftWare, .T. ) 
   hSoftWare['MinGW ' ] := 'C Compiler '
   hSoftWare['Harbour' ] := 'Clipper Compiler'
   hSoftWare['HMG ' ] := 'GUI Library '
   hProgram := NIL // { => }
   FOR EACH hProgram IN hSoftWare
      ? hProgram:__ENUMKEY(), "=>", hProgram:__ENUMVALUE(),; 
      hProgram:__ENUMBASE()[hProgram:__ENUMKEY()] // Alternate syntax 
   NEXT 
   ?
   ? "Multiple base, multiple value : "
   aArrayNr := { 1, 2, 3 }
   aArrayEn := { "one", "two", "three" }
   aArrayFr := { "un", "deux", "Trois" }
   cNumNr := 0
   cNumEn := ''
   cNumFr := ''
   FOR EACH cNumNr, cNumEn, cNumFr IN aArrayNr, aArrayEn, aArrayFr
      ? cNumNr, cNumEn, cNumFr
   NEXT 

   @ MAXROW(), 0
   WAIT "EOF ForEach.prg"
RETURN // ForEach.Prg.Main()

ForEach

Operator overloading

/*
Operator overloading

 Some operators overloaded by extending their functionalities.
"$" was an operator for "checking substring existence in a string" 

 For example :

 ? "A" $ "ABC" // Result: .T.
 ? "Z" $ "ABC" // Result: .F.

 Now, this operator can be used for arrays and hashs too, not only strings.

 See examples below.

 "=>" was a preprocessor operator with meaning "translate to : ...".

Now, this operator can be used as a <key> - <value> separator in Hashs
for define and / or assign <key> - <value> to Hashs.
See examples below.

 "[ ]" was Array element indicator (Special)
 "{ }" was Literal array and code block delimiters (Special)

Now, this indicators can be used for hashs too. 
See examples below.

"+=" is self-increment operator that can be used both numeric 
and string values.

 Such as :

 cTest := "This"
 cTest += " is" 
 ? cTest // This is

 nTest := 3
 nTest += 10
 ? nTest // 13

 Now, this operator can be used for adding elements to an existing hash;
 ( but no for arrays ! ).
 Note : Extended functionalities of $ and += operators depends xHB lib.
        So need this usages to xHB lib and xHB.ch.

 See examples below.

*/
#include "xhb.ch"
PROCEDURE Main()

 CLS

 aFruits := { "apple", "appricot", "cherry", "melon", "pear", "mulberry" }

 ? "aFruits", IF( "pear" $ aFruits, '', 'not ' ) + "contain pear"
 ? "aFruits", IF( "grapes" $ aFruits, '', 'not ' ) +"contain grapes"

 aComplex := ARRAY( 10 )
AEVAL( aComplex, { | x1, i1 | aComplex[ i1 ] := i1 } )

 aComplex[ 5 ] := DATE()
 aComplex[ 7 ] := .F.

 ?
 ? "aComplex", IF( 3 $ aComplex, '', 'not ' ) + "contain 3"
 ? "aComplex", IF( 13 $ aComplex, '', 'not ' ) + "contain 13"
 ? "aComplex", IF( .T. $ aComplex, '', 'not ' ) + "contain .T."
 ? "aComplex", IF( .F. $ aComplex, '', 'not ' ) + "contain .F."
hEmpty := { => }
 ?
 ? "hEmpty is a", VALTYPE( hEmpty ), "type variable have",;
 STR( LEN( hEmpty ), 1 ), "element and it's",;
 IF( EMPTY( hEmpty ), '', 'not' ), "Empty"
hCountries := { 'Argentina' => "Buenos Aires" }
 hCountries += { 'Brasil' => "Brasilia" }
 hCountries += { 'Chile' => "Santiago" }
 hCountries += { 'Mexico' => "Mexico City" }

 ?
 ? "hCountries is a", VALTYPE( hCountries ), "type variable have",;
 STR( LEN( hCountries ), 1 ), "elements and and it's",;
 IF( EMPTY( hCountries ), '', 'not' ), "Empty"
cCountry := NIL
 FOR EACH cCountry IN hCountries
 ? cCountry:__ENUMKEY(), "=>", cCountry:__ENUMVALUE()
 NEXT 

 hDays := { 'Days' => { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" } }

 ?
 ? "hDays", IF( 'Days' $ hDays, '', 'not ' ) + "contain Days" 
 ? "hDays", IF( "Mon" $ hDays, '', 'not ' ) + "contain Mon" 
 ? "hDays['Days']", IF( "Fri" $ hDays["Days"], '', 'not ' ) + "contain Fri"
hLanguages := { "EN" => "English" } +; 
 { "DE" => "Deutsche" } +; 
 { "ES" => "Español" } +; 
 { "FR" => "Français" } +; 
 { "IT" => "Italiano" } +; 
 { "PL" => "Polkski" } +; 
 { "PT" => "Português" } +; 
 { "RU" => "Russkî" } +; 
 { "TR" => "Türkçe" }

 ?
 ? "hLanguages is a", VALTYPE( hLanguages ), "type variable have",;
 STR( LEN( hLanguages ), 1 ), "elements and and it's",;
 IF( EMPTY( hLanguages ), '', 'not' ), "Empty"
cLanguage := NIL 
 FOR EACH cLanguage IN hLanguages
 ? cLanguage:__ENUMKEY(), "=>", cLanguage:__ENUMVALUE()
 NEXT 

 @ MAXROW(), 0 
 WAIT "EOF OprOLoad.prg"
RETURN // OprOLoad.Prg.Main()
OprOLoad