NAME
Types::Core - Core types defined as tests and literals (ease of use)
VERSION
Version "0.3.2";
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); }
Create Class function as constant and to test membership
...
sub Stat(;*); # needed for prototype
local * Stat = InClass Stat;
my $p=bless [], Task;
P "p isa %s", Task if Task $p;
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
Needed for consistency with 'ref' (and typ). 'ref' passes back the actual value of the 'ref' if it is a ref. Following that example, 'typ' return the underlying type of a perl-ref if it is a reference. In the same way, 'blessed' returns the name of the object's blessing (its class or package name) if it is 'blessed'.
Warning: take care that Scalar::Util's version of blessed
isn't also included, as it throws away the package or blessing name and only returns '1' if its argument is blessed. perl-type of a reference if it is a reference.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 references
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) as the value of the string passed in. With no argument uses $_
as the parameter. Returns the number or undef
if the field does not evaluate to a number. isnum
is an optional import that must be mentioned in the modules arguments. Note: to determine if false, you must use defined(isnum)
since numeric '0' can be returned and also evaluates 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 (for debugging purposes).
Failures can occur if Cmp is asked to compare different object with different refs ('blessed' refname), or same blessed class and different underlying types. Unblessed values and those of the same class can be compared.
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.
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 654:
=over without closing =back