Well, I haven't heard anything and I'll assume no news is good news. Here's my formal registration request: name: Params::Validate DLSI: adpf Author: DROLSKY Description: Validate positional/named subroutine parameters This belongs under section 12, I'm guessing. And the POD. This will change a little bit before the first release but its basically done. =head1 NAME Params::Validate - Validate method/function parameters =head1 SYNOPSIS use Params::Validate qw(:all); # takes named params (hash or hashref) sub foo { validate( @_, { foo => 1, # mandatory bar => 0, # optional } ); } # takes positional params sub bar { validate( @_, 1, 1, 0 ); # first two are mandatory, third is optional } sub foo2 { validate( @_, { foo => { type => ARRAYREF }, # specify a type bar => { can => [ 'print', 'flush', 'frobnicate' ] }, # specify an interface baz => { type => SCALAR, # a scalar ... callbacks => { 'numbers only' => sub { shift() =~ /^\d+$/ }, # ... that is a plain integer 'less than 90' => sub { shift() < 90 }, # ... and smaller than 90 }, } } ); } =head1 DESCRIPTION The Params::Validate module allows you to validate method or function call parameters to an arbitrary level of specificity. At the simplest level, it is capable of validating the required parameters were given and that no unspecified additional parameters were passed in. It is also capable of referring that a parameter is of a specific type, that it is an object of a certain class hierarchy, that it possesses certain methods, etc. =head2 EXPORT The module always exports the C<validate> method. In addition, it can export the following constants, which are used as part of the type checking. These are C<SCALAR>, C<ARRAYREF>, C<HASHREF>, C<CODEREF>, C<GLOB>, C<GLOBREF>, and C<SCALARREF>, and C<HANDLE>. These are explained in more detail later on. These constants are available via the tag C<:types>. There is also a C<:all> tag, which for now is equivalent to C<:types> tag. =head1 USAGE The validation mechanism provided by this module can handle both named parameters or positional. For the most part, the same features are available for each. The biggest difference is the way that the C<validate> subroutine is called by the subroutine that wants the validation done. The other difference is in the error messages produced when validation checks fail. When handling named parameters, the module is capable of handling either a hash or a hash reference transparently. All calls to the C<validate> subroutine start like this: validate( @_, ... ); What goes in the '...' depends on what validation you want performed and whether you are using named or positional parameters. Subroutines expecting named parameters should call the C<validate> subroutine like this: validate( @_, { parameter1 => ... validation, parameter2 => ... validation, ... } ); Subroutines expected positional parameters should call the C<validate> subroutine like this: validate( @_, { validation }, { validation }, { validation } ); =head2 Mandatory/Optional Parameters If you just want to specify that some parameters are mandatory and others are optional, this can be done very simply. For a subroutine expecting named parameters, you would do this: validate( @_, { foo => 1, bar => 1, baz => 0 } ); This says that the C<foo> and C<bar> parameters are mandatory and that the C<baz> parameter is optional. The presence of any other parameters will cause an error. For a subroutine expecting positional parameters, you would do this: validate( @_, 1, 1, 0, 0 ); This says that you expect at least 2 and no more than 4 parameters. If you have a subroutine that has a minimum number of parameters but can take any maximum number, you can do this: validate( @_, 1, 1, (0) x @_ ); This will always be valid as long as at least two parameters are given. A similar construct could be used for the more complex validation parameters described further on. Please note that this: validate( @_, 1, 1, 0, 1, 1 ); makes absolutely no sense, so don't do it. Any zeros must come at the end of the validation specification. =head2 Type Validation This module supports the following simple types, which can be L<exported as constants|EXPORT>: =over 4 =item * SCALAR A scalar which is not a reference, such as C<10> or C<'hello'>. =item * ARRAYREF An array reference such as C<[1, 2, 3]> or C<\@foo>. =item * HASHREF A hash reference such as C<{ a => 1, b => 2 }> or C<\%bar>. =item * CODEREF A subroutine reference such as C<\&foo_sub> or C<sub { print "hello" }>. =item * GLOB This one is a bit tricky. A glob would be something like C<*FOO>, but not C<\*FOO>, which is a glob reference. It should be noted that this trick: my $fh = do { local *FH; }; makes C<$fh> a glob, not a glob reference. On the other hand, the return value from C<Symbol::gensym> is a glob reference. Either can be used as a file or directory handle. =item * GLOBREF A glob reference such as C<\*FOO>. See the L<GLOB|GLOB> entry above for more details. =item * SCALARREF A reference to a scalar such as C<\$x>. =item * HANDLE This option is special, in that it just the equivalent of C<GLOB | GLOBREF>. However, it seems likely to me that most people interested in either globs or glob references are likely to really be interested in whether what is being in is a potentially valid file or directory handle. =back To specify that a parameter must be of a given type when using named parameters, do this: validate( @_, { foo => { type => SCALAR }, bar => { type => HASHREF } } ); If a parameter can be of more than one type, just use the bitwise or (C<|>) operator to combine them. validate( @_, { foo => { type => GLOB | GLOBREF } ); For positional parameters, this can be specified as follows: validate( @_, { type => SCALAR | ARRAYREF }, { type => CODEREF } ); =head2 Interface Validation To specify that a parameter is expected to have a certain set of methods, we can do the following: validate( @_, { foo => { can => 'bar' } } ); # just has to be able to ->bar ... or ... validate( @_, { foo => { can => [ qw( bar print ) ] } } ); # must be able to ->bar and ->print =head2 Class Validation A word of warning. When constructing your external interfaces, it is probably better to specify what you methods you expect an object to have rather than what class it should be of (or a child of). This will make your API much more flexible. With that said, if you want to verify that an incoming parameter belongs to a class (or a child class) or classes, do: validate( @_, { foo => { isa => 'My::Frobnicator' } } ); ... or ... validate( @_, { foo => { can => [ qw( My::Frobnicator IO::Handle ) ] } } ); # must be both, not either! =head2 Callback Validation If none of the above are enough, it is possible to pass in one or more callbacks to validate the parameter. The callback will be given the B<value> of the parameter as its sole argument. Callbacks are specified as hash reference. The key is an id for the callback (used in error messages) and the value is a subroutine reference, such as: validate( @_, { foo => callbacks => { 'smaller than a breadbox' => sub { shift() < $breadbox }, 'green or blue' => sub { my $val = shift; $val eq 'green' || $val eq 'blue' } } } ); On a side note, I would highly recommend taking a look at Damian Conway's Regexp::Common module, which could greatly simply the callbacks you use, as it provides patterns useful for validating all sorts of data. =head2 Mandatory/Optional Revisited If you want to specify something such as type or interface, plus the fact that a parameter can be optional, do this: validate( @_, { foo => { type => SCALAR }, bar => { type => ARRAYREF, optional => 1 } } ); or this for positional parameters: validate( @_, { type => SCALAR }, { type => ARRAYREF, optional => 1 } ); By default, parameters are assumed to be mandatory unless specified as optional. =head1 LIMITATIONS Right now there is no way (short of a callback) to specify that something must be of one of a list of classes, or that it must possess one of a list of methods. If this is desired, it can be added in the future. =head1 SEE ALSO Carp::Assert and Class::Contract. =head1 AUTHOR Dave Rolsky, <[EMAIL PROTECTED]> =cut