NAME

    HATX - A fluent interface for Hash and Array Transformations

SYNOPSIS

      use HATX qw/hatx/;
    
      # Multiple versions of journal.html and projmgmt.html
      my $files = [
        'journal-v1.0.tar.gz  1201',
        'journal-v1.1.tar.gz  1999',
        'journal-v1.2.tar.gz  3100',
        'projmgmt-v0.1.tar.gz  250',
        'projmgmt-v0.2.tar.gz  350'
      ];
    
      # Declare a helper object
      my $max = { journal => '0.0', projmgmt => '0.0' };
    
      # hatx($obj) clones $obj; no clobbering
      my $h = hatx($files)
        # Internal object becomes equivalent to:
        # [ 'journal-v1.0.tar.gz  1201',
        #   'journal-v1.1.tar.gz  1999',
        #   'journal-v1.2.tar.gz  3100',
        #   'projmgmt-v0.1.tar.gz  250',
        #   'projmgmt-v0.2.tar.gz  350' ]
    
       # Extract components: file, version, bytes
       ->map(sub {
          $_[0] =~ /(journal|projmgmt)-v(.+).tar.gz\s+(\d+)/;
          return [$1, $2, $3];      # e.g. ['journal', '1.0', 1201]
        })
        # Internal object becomes equivalent to:
        # [ ['journal', '1.0', 1201]
        #   ['journal', '1.1', 1999]
        #   ['journal', '1.2', 3100]
        #   ['projmgmt', '0.1', 250]
        #   ['projmgmt', '0.2', 350] ]
    
      # Accumulate file count and file sizes
      ->apply(sub {
          my ($v, $res) = @_;
          $res->{count}++;
          $res->{bytes} += $v->[2];
        }, my $stats = { count => 0, bytes => 0 })
        # Internal object unchanged
        # The $stats variable becomes { count => 5, bytes => 6900 }
    
      # Determine the max version of each file, store into $max
      ->apply(sub {
          my ($v, $res) = @_;
          my ($file, $ver, $size) = @$v;
          if ($ver gt $res->{$file}) { $res->{$file} = $ver }
        }, $max)
        # Internal object unchanged
        # $max variable becomes { journal => '1.2', projmgmt => '0.2' }
    
      # Keep only the max version
      ->grep(sub {
          my ($v, $res) = @_;
          my ($file, $ver, $size) = @$v;
          return $ver eq $res->{$file};
        }, $max)
        # Internal object reduced to:
        # [ ['journal', '1.2', 3100]
        #   ['projmgmt', '0.2', 350] ]
      ;

METHODS

 hatx( $objref )

    DESCRIPTION

        Clone the given $objref to create a 'hatx' object instance. The
        'hatx' object has an internal structure which is:
    
            One of: hashref | arrayref | undef
    
        This internal structure shall be called 'haref' in the rest of this
        document.

    ARGUMENTS

        $objref - Reference to either a hash or an array

    RETURNS

        An instance of the HATX object.

 to_obj()

    DESCRIPTION

        Converts the internal haref and returns it.

    ARGUMENTS

        None.

    RETURNS

        One of: hashref | arrayref | undef

 map( $fn, [,@args] )

    DESCRIPTION

        Apply the given function, $fn, to each element of the internal
        haref, replacing the entire haref.

    ARGUMENTS

        $fn - A user-provided function with a suitable signature.
    
          If internal haref is a hashref, $fn should have signature:
    
            $fn->($hkey_s, $hval_s [,@args]) returning ($hkey_t, $hval_t)
    
            WHERE
              $hkey_s   Key of source hashref pair
              $hval_s   Value of source hashref pair
              @args     Optional user variables
              $hkey_t   Key of target hashref pair
              $hval_t   Value of target hashref pair
    
          If the internal haref is an arrayref, $fn should have the signature:
    
            $fn->($val_s [,@args]) returning ($val_t)
    
            WHERE
              $val_s    An element of the source arrayref
              @args     Optional user variables
              $val_t    An element of the target arrayref
    
        @args - Optional arguments that are passed to $fn

    RETURNS

        The hatx object with the target haref.

 grep( $fn [,@args] )

    DESCRIPTION

        Retain only elements of the haref where $fn returns true.

    ARGUMENTS

        $fn - A user-provided function with a suitable signature.
    
          If internal haref is a hashref, $fn should have signature:
    
            $fn->($hkey_s, $hval_s [,@args]) returning ($hkey_t, $hval_t)
    
            WHERE
              $hkey_s   Key of source hashref pair
              $hval_s   Value of source hashref pair
              @args     Optional user variables
              $hkey_t   Key of target hashref pair
              $hval_t   Value of target hashref pair
    
          If the internal haref is an arrayref, $fn should have the signature:
    
            $fn->($val_s [,@args]) returning ($val_t)
    
            WHERE
              $val_s    An element of the source arrayref
              @args     Optional user variables
              $val_t    An element of the target arrayref
    
        @args - Optional arguments that are passed to $fn

    RETURNS

        The hatx object with elements containing only 'grepped' elements.

 sort( $fn )

    DESCRIPTION

        Sorts contents of arrayref. Hashrefs are unmodified.

    ARGUMENTS

        $fn - A function reference with prototype ($$) i.e. taking two
        arguments. See https://perldoc.perl.org/functions/sort.
    
        Examples of $fn:
    
          sub ($$) { $_[1] cmp $_[0] }    # Sort descending alphabetically
          sub ($$) { $_[0] <=> $_[1] }    # Sort ascending numerically
          sub ($$) { $_[1] <=> $_[0] }    # Sort descending numerically

    RETURNS

        The sorted hatx object.

 to_href( $fn [,@args] )

    DESCRIPTION

        Convert internal arrayref to hashref using the given function, $fn,
        fn and optionally additional arguments, @args, as needed.

    ARGUMENTS

        $fn - A user-provided function reference with signature:
    
          $fn->($val [,@args]) returning ($hkey, $hval)
    
          WHERE
            $val    An element of the source arrayref
            @args   Optional user variables
            $hkey   Key of target hashref pair
            $hval   Value of target hashref pair
    
        @args - Optional arguments that are passed to $fn

    RETURNS

        The hatx object where the internal structure is a hashref.

 to_aref( $fn [,@args] )

    DESCRIPTION

        Convert internal hashref to arrayref using the given function, $fn
        and optionally additional arguments, @args, as needed.

    ARGUMENTS

        $fn - A user-provided function reference with signature:
    
          $fn->($hkey, $hval [,@args]) returning ($val)
    
          WHERE
            $hkey   Key of source hashref pair
            $hval   Value of source hashref pair
            @args   Optional user variables
            $val    An element of the target arrayref
    
        @args - Optional arguments that are passed to $fn

    RETURNS

        The hatx object where the internal structure is a hashref.

 apply( $fn [,@args] )

    DESCRIPTION

        Apply the given function, $fn to each item in the haref. The haref
        is unchanged. Typically used to find aggregate values e.g. max/min or
        totals which are then stored into @args.

    ARGUMENTS

        $fn - A user-provided function with a suitable signature.
    
          If internal haref is a hashref, $fn should have signature:
    
            $fn->($hkey_s, $hval_s [,@args]) with no return values
    
            WHERE
              $hkey_s   Key of source hashref pair
              $hval_s   Value of source hashref pair
              @args     Optional user variables
    
          If the internal haref is an arrayref, $fn should have the signature:
    
            $fn->($val_s [,@args]) with no return values
    
            WHERE
              $val_s    An element of the source arrayref
              @args     Optional user variables
    
        @args - Optional arguments that are passed to $fn

    RETURNS

        The same hatx object.

AUTHOR

    Hoe Kit CHEW <hoekit@gmail.com>

COPYRIGHT

    Copyright 2024- Hoe Kit CHEW

LICENSE

    This library is free software; you can redistribute it and/or modify it
    under the same terms as Perl itself.

