++ed by:
ADAMJS

1 PAUSE user
1 non-PAUSE user.

Linda A Walsh
and 1 contributors

NAME

Types::Core - Core types defined as tests and literals (ease of use)

VERSION

Version "0.2.4";

SYNOPSIS

  my @data_types = (ARRAY CODE GLOB HASH IO REF SCALAR);
  my $ref = $_[0];
  P "Error: expected %s", HASH unless HASH $ref;

Syntax symplifier for type checking.

Allows easy, unquoted use of var types (ARRAY, SCALAR, etc.) as literals, and allows standard type names to be used as boolean checks of the type of a reference as well as passing through the value of the reference. For example: HASH $href will return true if the reference points to a HASH or a HASH-based object. For example, "HASH $href" check routines of references.

USAGE

    TYPE <Ref> - Check if Ref has underlying type, TYPE

    TYPE - Literal usage equal to itself

EXAMPLE

  printf "type = %s\n", HASH if HASH $var;

Same as:

  printf "type = %s\n", 'HASH' if ref $var eq 'HASH';)

DESCRIPTION

For the most basic functions listed in the Synopsis, they take either 0 or 1 arguments. If 1 parameter, then they test it to see if the ref is of the given type (blessed or not). If false, undef is returned, of true, the ref, itself is returned.

For no args, they return literals of themselves, allowing the named strings to be used as Literals w/o quotes.

MORE EXAMPLES

Initialization

  our %field_types = (Paths{type => ARRAY, ...});

Flow Routing

    ...
    my $ref_arg = ref $arg;
    return  ARRAY $ref_arg              ? statAR_2_Ino_t($path,$arg)  :
            InClass('stat_t', $ref_arg) ? stat_t_2_Ino_t($path, $arg) :
            _path_2_Ino_t($path); }

Data Verification

  sub Type_check($;$) { ...
    if (ARRAY $cfp) { 
      for (@$cfp) { 
        die P "Field %s does not exist", $_ unless exists $v->{$_}; 
        my $cls_ftpp = $class."::field_types"; 
        if (HASH $cls_ftpp) { 
          if ($cls_ftpp->{type} eq ARRAY) {  ...

Param Checking

  sub popable (+) { 
    my $ar = $_[0]; 
    ARRAY $ar or die P "popable only works with arrays, not %s", ref $ar; }

Return Value Checks and Dereference Protection

  my $Inos = $mp->get_sorted_Ino_t_Array; 
  return undef unless ARRAY $Inos and @$Inos >= 2;

Non-instantiating existence checks in references: ErV.

     ErV $ref, FIELDNAME;        # Exist[in]reference? Value : C<undef>
     ErV $hashref, FIELDNAME;    # Exist[in]hashref?   Value : C<undef>

    If fieldname exists in the ref pointed to by the reference, return the value, else return undef.

Note: What's EhV? (Deprecated)

      You may see older code using C<EhV>.  M<Types::Core> only had this checker
      for hashes, but given combinations of various references, the more
      general C<ErV> replaced it.

OPTIONAL FUNCTIONS: typ & blessed

     typ REF;                    #return underlying type of REF

Once you bless a reference to an object, its type becomes hidden from ref. typ allows you to peek into a class reference to see the basic perl type that the class is based on.

Most users of a class won't have a need for that information, but a 'friend' of the class might in order to offer helper functions.

    blessed REF;                #test if REF is blessed or not

Included for it's usefulness in type checking. Similar functionality as implemented in Scalar::Util. This version of blessed will use the Scalar::Util version if it is already present. Otherwise it uses a pure-perl implementation.

EXAMPLE: ErV

To prevent automatic creation of variables when accessed or tested for undef, (i.e. autovivification), one must test for existence first, before attempting to read or test the 'defined'-ness of the value.

This results in a 2 step process to retrive a value:

  exists $name{$testname} ? $name{testname} : undef;

If you have multiple levels of hash tables say retrieving SSN's via {$lastname}{$firstname} in object member 'name2ssns' but don't know if the object member is valid or not, the safe way to write this would be:

  my $p = $this;
  if (exists $p->{name2ssns} && defined $p->{name2ssns}) {
    $p = $p->{name2ssns};
    if (exists $p->{$lastname} && defined $p->{$lastname}) {
      $p = $p->{$lastname};
      if (exists $p->{$firstname}) {
        return $p->{$firstname};
      }
    }
  }
  return undef;

ErV saves some steps. Instead of testing for existence, 'definedness', and then use the value to go deeper in the structuer, ErV does the testing and returns the value (or undef) in one step. Thus, the above could be written:

  my $p = $this;
  return $p = ErV $p, name2ssns      and
             $p = ErV $p, $lastname  and 
                  ErV $p, $firstname;

This not only saves coding space & time, but allows faster comprehension of what is going on (presuming familiarity with ErV).

Multiple levels of hashes or arrays may be tested in one usage. Example:

  my $nested_refs = {};
  $nested_refs->{a}{b}{c}{d}[2]{f}[1] = 7;
  P "---\nval=%s", ErV $nested_refs, a, b, c, d, e, f, g;
  ---
  val=7

  The current ErV handles around thirty levels of nested hashing.
      

MORE OPTIONAL FUNCTIONS mk_array and mk_hash

$< >

    mk_array $p->ar;

without mk_array, the following generates a runtime error (can't use an undefined value as an ARRAY reference):

    my $ar;
    printf "items in ar:%s\n", 0+@{$ar};

but using mk_array will ensure there is an ARRAY ref there if there is not one there already:

    my $ar;
    mk_array $ar;
    printf "items in ar:%s\n", 0+@{$ar};

While the above would be solved by initalizing $ar when defined, expicit initialization might be useful to protect against the same type of error in dynamically allocated variables.

UTILITY FUNCTIONS: isnum & Cmp

     isnum STR              #return <NUM> if it starts at beginning of STR

     Cmp [$p1,$p2]          # C<cmp>-like function for nested structures
                            # uses C<$a>, C<$b> as default inputs
                            # can be used in sort for well-behaved data
                            # (incompare-able data will return undef)
                            # builtin debug to see where compare fails
#

isnum checks for a number (int, float, or with exponent) at the beginning of the string passed in. With no argument uses $_ as the parameter. Returns the number with any non-number suffix stripped off or undef if no num is found at the beginning of the string. isnum is an optional import that must be included via @EXPORTS_OK. Note: to determine if false, you must use defined(isnum) since numeric '0' can be returned and would also evaluate to false.

The existence of Cmp is a side effect of testing needs. To compare validity of released functions, it was necessary to recursively compare nested data structures. To support development, debug output was added that can be toggled on at runtime to see where a compare fails.

Normally you only use two parameters $a and $b that are references to the data structures to be compared. If debugging is wanted, a third (or first if $a and $b are used) parameter can be pass with a non-zero value to enable primitive debug output.

Additionally, if the compare fails and does not return an integer value (returning undef instead), a 2nd return value can tell you where in the compare it failed. To grab that return value, use a two element list or an array to catch the status, like

  C<my ($result, $err)=Cmp; (pointers passed in C<$a> and C<$b>)

If the compare was successful, it will return -1, 0 or 1 as 'cmp' does. If it fails, $result will contain undef and $err will contain a number indicating what test failed.

Failures can occur if Cmp is asked to compare different object with different refs ('blessed' refname), or same blessed class and different underlying types. Unbless values and those in the same classes can be compared.

NOTE on INCLUDING OPTIONAL (EXPORT_OK) FUNCTIONS

Importing optional functions does not cancel default imports as this module uses Xporter. To dselect default exports, add '-' (minus or dash) at the beginning of argument list to Types::Core as in use Types::Core qw(- blessed);. See Xporter for more details.

COMPATIBILITY NOTE: with Perl 5.12.5 and earlier

    In order for earlier perls to parse things correctly parentheses are needed for two or more arguments after a ErV test verb.

2 POD Errors

The following errors were encountered while parsing the POD:

Around line 588:

=back without =over

Around line 592:

=over without closing =back