Hash Details – 1


Some details of hash manipulations:

HB_HCOPY() function copies a hash to another.

Syntax :

   HB_HCOPY( <hsDestination>, <hsSource>, [<nStart>], [<nCount>] ) -> 
             <hsDestination>

 As noticed in syntax, copy operation may be limited by  [<nStart>], [<nCount>]  arguments.

 But a hash may NOT built by “COPY” method; because  <hsDestination> argument  isn’t optional.

   hFruits  := { "fruits" => { "apple", "cherry", "apricot" } }
   hFruits2 := HB_HCOPY( hFruits )   // Argument error !

Though it’s possible in two steps:

   hFruits2 := HB_HASH()   // Built first an empty hash
   hFruits2 := HB_HCOPY(hFruits2, hFruits ) // copy second onto first

As a result, for hash copy process two hashes should be exist:

   hFruits := { "fruits" => { "apple", "cherry", "apricot" } }
   hDays   := { "days"   => { "sunday", "monday" } }
   hFruits := HB_HCOPY( hFruits, hDays )

or 

   hFruits := { "fruits" => { "apple", "cherry", "apricot" } }
   hDays   := { "days"   => { "sunday", "monday" } }
   hTarget := HB_HASH()
   hTarget := HB_HCOPY( hTarget, hFruits )
   hTarget := HB_HCOPY( hTarget, hDays )

HB_HMERGE() function merge two hashes.

Syntax:

   HB_HMERGE( <hsDestination>, <hsSource>, <bBlock>|<nPosition> ) -> 
              <hsDestination>
   hFruits := { "fruits" => { "apple", "cherry", "apricot" } }
   hDays   := { "days"   => { "sunday", "monday" } }
   hMerged := HB_HMERGE( hFruits, hDays )

hFruits :

    1 days => sunday monday

    2 fruits => apple cherry apricot

hTarget :

    1 days => sunday monday

    2 fruits => apple cherry apricot

AADD( hFruits[ "fruits" ], "melon" )

hFruits and hTarget :

  1 days => sunday monday

  2 fruits => apple cherry apricot melon

Result of above tests :

HB_HCOPY() and HB_HMERGE() doesn’t “physically” copy / merge hashes data; instead, copy / merge only by reference(s).

HB_HCLONE() function :  Cloning (exact copy of) hashes.

Syntax:

   HB_HCLONE( <hsTable> ) -> <hsDestination>
   hFruits := { "fruits" => { "apple", "cherry", "apricot" } }
   hClone := HB_HCLONE( hFruits )

hClone : fruits => apple cherry apricot

   AADD( hFruits[ "fruits" ], "melon" )  // Source changed

    hClone : fruits => apple cherry apricot

*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._./*

Hash Details - 1

 Copy, Merge & Clone Hashes. 

*/
#define NTrim( x ) IF( HB_ISNUMERIC( x ), LTRIM( STR( x ) ), x )
PROCEDURE Main()
  SET COLO TO "W/B"

  cLMarj := SPACE( 3 )

  CLS
  ? "Copy one hash to another : HB_HCOPY() function : " 
  ? "Syntax :",;
  "HB_HCOPY( <hsDestination>, <hsSource>, [<nStart>]," 
  ? " [<nCount>] ) -> <hsDestination>"
  hFruits := { "fruits" => { "apple", "cherry", "apricot" } }
  hDays := { "days" => { "sunday", "monday" } } 

  * hFruits2 := HB_HCOPY( hFruits ) // Argument error !
  hFruits := HB_HCOPY( hFruits, hDays )
  ListHash( hFruits, "Copied-1 (Fruits)" )

  hDays[ "days" ] := "friday"
  ListHash( hFruits, "copied or referenced ?" )
  hTarget := HB_HASH()
  hFruits := { "fruits" => { "apple", "cherry", "apricot" } }
  hDays := { "days" => { "sunday", "monday" } } 

  hTarget := HB_HCOPY( hTarget, hFruits )
  hTarget := HB_HCOPY( hTarget, hDays )

  ListHash( hTarget, "Copied-2 ( Target )" )

  AADD( hFruits[ "fruits" ], "melon" )
  ListHash( hTarget, "copied or referenced ?" )

  ? "Merge two hashes : HB_HMERGE() function : " 
  ? "Syntax :",;
  "HB_HMERGE( <hsDestination>, <hsSource>, <bBlock>|"
  ? " <nPosition> ) -> <hsDestination>"

  hFruits := { "fruits" => { "apple", "cherry", "apricot" } }
  hDays := { "days" => { "sunday", "monday" } } 

  hMerged := HB_HMERGE( hFruits, hDays )

  ListHash( hFruits, "Merged (hFruits)" )
  ListHash( hMerged, "Merged (hTarget)" )
  AADD( hFruits[ "fruits" ], "melon" )
  ListHash( hFruits, "Merged or referenced ? ( hFruits) " )
  ListHash( hMerged, "Merged or referenced ? ( hMerged) " )

  * 
  * Result of above tests :
  * 
  * HB_HCOPY() and HB_HMERGE() doesn't "physically" copy / merge hashes data;
  * 
  * instead copy / merge only by reference(s).
  *
  ? "Cloning (exact copy of) hashes : HB_HCLONE() function : " 
  ? "Syntax :",;
  "HB_HCLONE( <hsTable> ) -> <hsDestination>"

  hFruits := { "fruits" => { "apple", "cherry", "apricot" } }
  hClone := HB_HCLONE( hFruits )
  ListHash( hClone, "Cloned" )
  AADD( hFruits[ "fruits" ], "melon" )
  ListHash( hClone, "Source changed" )

  ?
  @ MAXROW(), 0
  WAIT "EOF HashDetails-1.prg"

RETURN // HashDetails-1.Main()
*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.

PROCEDURE ListHash( hHash, cComment )

  LOCAL x1Pair := NIL

  cComment := IF( HB_ISNIL( cComment ), '', cComment )

  ? cComment, '' 
  * ?? "-- Type :", VALTYPE( hHash ),'' 
  * ?? "size:", NTrim ( LEN( hHash ) ) 
  ?
  FOR EACH x1Pair IN hHash
     nIndex := x1Pair:__ENUMINDEX()
     x1Key := x1Pair:__ENUMKEY()
     x1Value := x1Pair:__ENUMVALUE()
     ? cLMarj, NTrim( nIndex ) 
     * ?? '', VALTYPE( x1Pair )
     ?? '', NTrim( x1Key ), "=>"
     * ?? '', VALTYPE( x1Key ) 
     * ?? VALTYPE( x1Value ) 
     IF HB_ISARRAY( x1Value ) 
        AEVAL( x1Value, { | x1 | QQOUT( '', x1 ) } )
     ELSE 
        ?? '', NTrim( x1Value )
     ENDIF 
  NEXT

  ? REPL( "~", 32 ) 

RETURN // ListHash()
*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.

HashDets1