The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.
NAME
    Arguments - Perl subroutine type-checking

SYNOPSIS
    (This documents version 0.2 of Arguments.)

      package Flintstone;

      use Arguments;

      BEGIN {
        $Arguments::ARGUMENT_CHECKS{INTEGER}
          = sub { defined $_[0] and $_[0] =~ /^[+-]?\d+$/ },
      }

      sub fooby ($\%) : Arguments (INTEGER, HASH);
      sub tv_show ($) : Arguments (Flintstone);

DESCRIPTION
    Arguments provides argument checking during compile and run time,
    supplementing prototype declarations.

  Why?

    There are other ways of doing this -- Damian Conway's
    Attribute::Handlers and Attribute::Types are one very interesting route;
    Dave Rolsky's Params::Validate is another. I am doubtful if I have
    covered the gamut with the mention of just those two.

    However, I had an epiphany to use subroutine attributes for argument
    type checking, and to try and make it clean and simple to use (DCONWAY's
    work is too general-purpose for my needs, and has a lot of overhead). It
    is not there yet, but I hope to get it there. If nothing else, it is a
    new, fun area of Perl for me to explore.

    An obvious area to explore is reimplementing this module using
    Attribute::Handlers and hooking in Params::Validate for richer
    type-checking. Maybe I'll do that after installing L4. :-)

  Basic Use

    To use Arguments, a sub declares an attribute named *Arguments* listing
    the type of arguments, each matching a protype declaration:

      sub fooby ($\%) : Arguments (INTEGER, HASH);

    By default, Arguments has only two checks:

    Regular Expressions
        Any argument to the *Arguments* attribute starting with a "/" (the
        forward-slash character) is assumed to be the beginning of a regular
        expression formed by appending that argument to "qr". See the
        section on "qr/STRING/imosx" in the perlop manpage for details.
        Arguments to the sub call are then checked against this pattern. An
        example:

          sub eat_int_and_live ($) : Arguments (/^[+-]?\d+$/);

    References (the default)
        Any other argument is assumed to be a reference checked by
        "UNIVERSAL::isa". This includes non-blessed reference types such as
        *HASH*. An example:

          sub eat_code_and_die (&) : Arguments (CODE);

        This example is unexciting since Perl's own prototype-checking
        should catch argument mismatches.

  Enforcing Method Calls

    A more interesting example enforces method calls:

      package Flintstone;

      sub yabba_dabba_doo ($) : Arguments (Flintstone);

    The creates a run-time check that the first argument to
    "yabba_dabba_doo" is indeed a "Flintstone" or a package which has
    "Flintstone" as a base. Presently, Perl has no way of enforcing this
    restriction.

  Extending Argument Checks

    Packages may extend the argument checks by manipulating
    %Arguments::ARGUMENT_CHECKS in their "BEGIN" blocks. An example:

      BEGIN {
        $Arguments::ARGUMENT_CHECKS{INTEGER}
          = sub { defined $_[0] and $_[0] =~ /^[+-]?\d+$/ },
      }

      sub eat_int_and_live ($) : Arguments (INTEGER);

    This is the same as the example above for regular expressions, except
    that the intent of the sub declaration is more clear.

  EXPORT

    None. However, Arguements pushes itself onto the caller's @ISA array so
    that the MODIFY_CODE_ATTRIBUTES technique may work. See the section on
    "Package-specific Attribute Handling" in the attributes manpage for an
    explanation.

DIAGNOSTICS
    The following are the diagnostics generated by Arguments. Items marked
    "(W)" are non-fatal (invoke "Carp::carp"); those marked "(F)" are fatal
    (invoke "Carp::croak"). None of the diagnostics may be selectively
    disabled with categores. See <perllexwarn>.

    Can't use string ("%s") as %s ref while "strict refs" in use
        (F) Only hard references are allowed by "strict refs". Symbolic
        references are disallowed. See the perlref manpage.

        What this usually means for Arguments is that you have a poorly
        formed argument list to the *Arguments* attribute such as "Arguments
        (Apple Core)" instead of "Arguments (Apple, Core)".

        (F) The function requires more arguments than you specified.

    Not enough prototypes for %s
        (F) The function requires more prototypes in the *Arguments*
        attribute than you specified.

    Too many arguments for %s
        (F) The function requires fewer arguments than you specified.

    Too many prototypes for %s
        (F) The function requires fewer prototypes in the *Arguments*
        attribute than you specified.

    Type of arg %d to %s must be %s (not %s)
        (F) This function requires the argument in that position to be of a
        certain type. Arrays must be @NAME or "@{EXPR}". Hashes must be
        %NAME or "%{EXPR}". No implicit dereferencing is allowed--use the
        {EXPR} forms as an explicit dereference. See the perlref manpage.
        For blessed references, "UNIVERSAL::isa ($_[%d], '%s')" need be
        true.

TODO
    Tie type-checking of prototypes and attributes.
    Support for non-scalar prototypes (e.g., "sub (\@)").
    Support for optional prototypes (e.g., "sub ($;$)").
    Support for list prototypes (e.g., "sub (%)").
    Generate prototype declarations from the attributes.
    Tests.
AUTHOR
    B. K. Oxley (binkley) <binkley@bigfoot.com<

SEE ALSO
    the Attribute::Handlers manpage
    the Attribute::Types manpage
    the section on "isa ( TYPE )" in the UNIVERSAL manpage
    the attributes manpage
    the section on "qr/STRING/imosx" in the perlop manpage
    the perllexwarn manpage