|
NAMEGetargs::Long - Named subroutine arguments, with optional type checkingSYNOPSISuse Getargs::Long; # case sensitive use Getargs::Long qw(ignorecase); # case insensitive # Simple, args mandatory my ($val, $other) = getargs(@_, qw(val other)); # Simple, args optional (in [] means optional) my ($val, $other) = getargs(@_, [qw(val other)]); # Simple with typechecking, args mandatory my ($val, $other) = getargs(@_, qw(val=Class::X other=ARRAY)); # Simple with typechecking, args optional my ($val, $other) = getargs(@_, [qw(val=Class::X other=ARRAY)]); # Faster version, building dedicated argument parsing routine my ($val, $other) = cgetargs(@_, qw(val other)); # Other cases, use full specs: my ($x, $y, $z, $a, $b, $c) = xgetargs(@_, # Non-mandatory, defaults to undef unless specified otherwise 'x' => ['i'], # integer, no default 'y' => ['ARRAY', ['a', 'b']], # Has a default 'z' => [], # No typecheck, can be anything # Mandatory arguments 'a' => 'i', # integer (scalar) 'b' => 'TYPE', # TYPE or any heir of TYPE 'c' => undef, # unspecified type but mandatory ); # Extract remaining unparsed args in @extra my ($val, $other, @extra) = getargs(@_, { -strict => 0 }, qw(val other)); # Alter behaviour of the getargs() routines via switches in hashref my ($val, $other) = getargs(@_, { -strict => 1, # unknown switches are fatal -ignorecase => 1, # override package's global -inplace => 1, # edit @_ inplace: remove parsed args -extra => 0, # suppress return of extra arguments }, qw(val other) ); DESCRIPTIONThe "Getargs::Long" module allows usage of named parameters in function calls, along with optional argument type-checking. It provides an easy way to get at the parameters within the routine, and yields concise descriptions for the common cases of all-mandatory and all-optional parameter lists.The validation of arguments can be done by a structure-driven routine getargs() which is fine for infrequently called routines (but should be slower), or via a dedicated routine created and compiled on the fly the fist time it is needed, by using the cgetargs() family (expected to be faster). The "Log::Agent" module is used to report errors, which leaves to the application the choice of the final logging method: to a file, to STDERR, or to syslog. EXAMPLESBefore going through the interface specification, a little example will help illustrate both caller and callee sides. Let's write a routine that can be called as either:f(-x => 1, -y => 2, -z => 3); # -switch form f(x => 1, y => 2, z => 3); # concise form (- are optional) f(y => 1, x => 2); # order changed, z may be omitted Since we have an optional parameter z but mandatory x and y, we can't use the short form of getargs() and must therefore use xgetargs(): sub f { my ($x, $y ,$z) = xgetargs(@_, -x => 'i', # mandatory, integer -y => 'i', # mandatory, integer -z => ['i', 0], # optional integer, defaults to 0 ); # code use $x, $y, $z } That's quite simple and direct if you think of [] as "optional". Note that we pass xgetargs() a reference to @_. If we had all arguments mandatory and wished to nonethless benefit from the named specification at call time to avoid having the caller remember the exact parameter ordering, we could write: sub f { my ($x, $y ,$z) = getargs(@_, qw(x=i y=i z=i)); # code of f } Without parameter type checking, that would be even more concise. Besides, if f() is frequently called, it might be more efficient to build a routine dynamically to parse the arguments rather than letting getargs() parse the same data structures again and again: sub f { my ($x, $y ,$z) = cgetargs(@_, qw(x y z)); # 'c' for cached/compiled # code of f } If you call f() with an improper argument, logcroak() will be called to issue an exception from the persepective of the caller, i.e. pointing to the place f() is called instead of within f() at the getargs() call, which would be rather useless. Here are some more examples: Example 1 -- All mandatory: sub f { my ($port, $server) = getargs(@_, qw(port=i server=HTTP::Server)); } f(-server => $server, port => 80); # or -port, since - is optional f(port => 80, server => $server); f(server => $server); # WRONG: missing mandatory -port f(server => 80, port => 80); # WRONG: -server not an HTTP::Server f(server => undef, port => 80); # WRONG: -server cannot be undef Example 2 -- All optional sub cmd { my ($a, $o) = getargs(@_, [qw(a o=s)]); } cmd(); # OK cmd(-a => undef); # OK -a accepts anything, even undef cmd(-a => 1, -o => ".."); # OK cmd(-a => 1, -o => undef); # WRONG: -o does not accept undef cmd(-x => 1); # WRONG: -x is not a known argument name Example 3 -- Mixed optional / mandatory sub f { my ($x, $z) = xgetargs(@_, -x => 'i', # -x mandatory integer -z => ['n', -20.4], # -z optional, defaults to -20.4 ); } f(x => 1, z => {}); # WRONG: z is not a numerical value f(z => 1, x => -2); # OK f(-z => 1); # WRONG: mandatory x is missing f(-z => undef); # WRONG: z cannot be undef Example 4 -- Parsing options sub f { my ($x, $z) = xgetargs(@_, { -strict => 0, -ignorecase => 1 }, -x => 'i', # -x mandatory integer -z => ['n', -20.4], # -z optional, defaults to -20.4 ); } f(x => 1, foo => {}); # OK, -foo ignored since not strict f(-X => 1); # OK, -X actually specifies -x with ignorecase INTERFACEAll the routines take a mandatory first argument, called arglist, which is the array containing the named arguments for the routine (i.e. a succession of name => value tuples). This array is implicitely passed as reference, and will usually be given as @_.All the routines take an optional options argument which comes in the second place. It is an hash reference containing named options that alter the behaviour of the routine. More details given in the Options section. All the routines return a list of the arguments in the order they are specified, each slot in the list being either the argument value, if present, or "undef" if missing (and not mandatory). Simple CasesSimple cases are handled by getargs(): named arguments should either be all mandatory or all optional, and there is no provision for specifying a default value for optional parameters.The getargs() routine and its cousin cgetargs() have two different interfaces, depending on whether the arguments are all mandatory or all optional. We'll only specify for getargs(), but the signature of cgetargs() is identical.
Complex CasesThe xgetargs() routine and its cousin cxgetargs() (for the caching version) allow for a more verbose description of named parameters which allows specifying arguments that are mandatory or optional, and also give default values to optional arguments.
OptionsAll the getargs() and xgetargs() routines take an optional hash reference as second argument. Keys in this hash define options that apply locally to the call. In the case of caching routines, e.g. cxgetargs(), the options are only considered the first time, when the analyzing routine is built, and are ignored on subsequent calls. Therefore, it is wise to use manifest constants when specifying options, or use the non-caching function family instead if your options need to be dynamically computed (please, don't do that).Options given there must be spelled out with the leading "-" and are case sensitive. To enable an option, give a true value. For instance: sub f { my ($x, $z) = cxgetargs(@_, { -strict => 0, -ignorecase => 1 }, -x => 'i', # -x mandatory integer -z => ['n', -20.4], # -z optional, defaults to -20.4 ); } supplies two options, turning "-ignorecase" on and "-strict" off. The available options are, in alphabetical order:
BUGSCurrently, types 'i', 'n' and 's' all mean the same thing, but that will change. Don't take the current implementation's deficiency as an excuse for lamely specifying your scalar types.You must be careful in this implementation to list options and variables in the very same order. Some day, I will probably add another routine to take arguments the way "Getopt::Long" does to cope with this ordering problem (but it forces to spell out variables twice -- once for declaration, and once for specifying a pointer to it). RELATED MODULESee Params::Validate for another take at parameter validation. It is a completely independant module, developped by Dave Rolsky, which may also interest you. Its interface and purpose are different though.LICENSEThis library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See the file LICENSE in the distribution for details.AUTHORThe original code (written before September 15, 2004) was written by Raphael Manfredi <Raphael_Manfredi@pobox.com>.Maintenance of this module is now being done by David Coppit <david@coppit.org>. SEE ALSOLog::Agent, Params::Validate
Visit the GSP FreeBSD Man Page Interface. |