| Params-Named documentation | Contained in the Params-Named distribution. |
Params::Named - Map incoming arguments to parameters of the same name.
use Params::Named;
use IO::All;
sub storeurl {
my $self = shift;
MAPARGS \my($src, $dest);
return io($src) > io($dest);
}
$obj->storeurl(src => $url, dest => $fh);
This module does just one thing - it maps named arguments to a subroutine's
lexical parameter variables or, more specifically, any lexical variables
passed into MAPARGS. Named parameters are exactly the same as a flattened
hash in that they provide a list of key => value pairs. So for each
key that matches a lexical variable passed to MAPARGS the corresponding
value will be mapped to that variable. Here is a short example to demonstrate
MAPARGS in action:
use Params::Named;
sub mapittome {
MAPARGS \my($this, @that, %other);
print "This is: '$this'\n";
print "That is: ", join(', ', @that), "\n";
print "The other: ", join(', ',
map "$_ => $other{$_}", keys %other), "\n";
}
mapittome this => 'a simple string',
that => [qw/a list of items/],
other => {qw/a hash containing pairs/};
## Or if you've got a hash.
my %args = (
this => 'using a hash',
that => [qw/is very cool/],
other => {qw/is it not cool?/},
);
mapittome %args;
The example above illustrates the mapping of mapittome's arguments to
its parameters. It will work on scalars, arrays and hashes, the 3 types
of lexical values.
Given a list of variables map those variables to named arguments from the
caller's argument. Taking advantage of one of Perl's more under-utilized
features, passing in a list of references as created by applying the
reference operator to a list will allow the mapping of compound variables
(without the reference lexically declared arrays and hashes flatten to an
empty list). Argument types must match their corresponding parameter types
e.g foo => \@things should map to a parameter declared as an array
e.g MAPARGS \my(@foo).
The arguments passed to MAPARGS don't need to be referenced if they are
simple scalars, but do need to be referenced if either an array or hash is
used.
MAPARGS
Parameter '%s' not mapped to an argumentThis warning is issued because a parameter couldn't be mapped to an argument
i.e if foo1 => 'bar' is accidentally passed to subroutine who's
parameter is $fool.
The parameter '%s' doesn't match argument type '%s'A given parameter doesn't match it's corresponding argument's type e.g
sub it'llbreak { MAPARGS \my($foo, @bar); ... }
## This will croak() because @bar's argument isn't an array reference.
it'llbreak foo => 'this', bar => 'that';
So either the parameter or the argument needs to be updated to reflect the desired behaviour.
Robin Houston for bug spotting, code refactoring, idea bouncing and releasing a new version of PadWalker (is there anything he can't do?).
Dan Brook <cpan@broquaint.com>
Copyright (c) 2005, Dan Brook. All Rights Reserved. This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.
| Params-Named documentation | Contained in the Params-Named distribution. |
package Params::Named; $VERSION = '1.0.2'; require Exporter; @ISA = 'Exporter'; @EXPORT = 'MAPARGS'; use strict; use Carp qw/croak carp/; use PadWalker 'var_name'; sub VAR { return {qw/SCALAR $ ARRAY @ HASH % REF $/}->{ref $_[0]}.$_[1]; } sub _set_param { my($p, $v, $n) = @_; # param, value, name return $$p = $v if ref $p eq 'SCALAR' && (ref $v || ref \$v) eq 'SCALAR' || (ref $v eq 'REF'); return @$p = @$v if ref $p eq 'ARRAY' && ref $v eq 'ARRAY'; return %$p = %$v if ref $p eq 'HASH' && ref $v eq 'HASH'; croak sprintf "The parameter '%s' doesn't match argument type '%s'", VAR($p,$n), ( ref $v || ref \$v ); } ## Map named arguments to variables of those names. sub MAPARGS { my %args = do { package DB; () = caller 1; @DB::args }; ## Map the lexicals of the caller to the caller's arguments. my %vmap = map { my $arg = ref $_ ? $_ : \$_; my $prm = substr(var_name(1, $arg), 1); exists $args{$prm} ? ($prm => $arg) : (() = carp "Parameter '${\VAR($arg,$prm)}' not mapped to an argument") } @_; ## Now assign the caller's arguments to the caller's lexicals. _set_param $vmap{$_} => $args{$_}, $_ for keys %vmap; return \%vmap; } 1;