Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re: Perl Idioms Explained - my ($foo, $bar) = @{shift(@_)}{qw/ -foo -bar /}

by hardburn (Abbot)
on Mar 01, 2004 at 14:33 UTC ( [id://332920]=note: print w/replies, xml ) Need Help??


in reply to Perl Idioms Explained - my ($foo, $bar) = @{shift(@_)}{qw/ -foo -bar /}

That's nice for a short parameter list, but it could get bluky for large lists (like the HTML::Template constructor). I prefer something like this:

{ my @PARAMS = qw( foo bar baz ); sub new { my $class = shift; my $in = shift; my $self = { map { $_ => $in->{$_} || '' } @PARAMS }; bless $self, $class; } }

The above is more self-documenting, because all the parameters taken are listed above the subroutine and can be easily broken into multiple lines. It also doesn't mix the parameter definitions with other code.

----
: () { :|:& };:

Note: All code is untested, unless otherwise stated

Replies are listed 'Best First'.
Re: Re: Perl Idioms Explained - my ($foo, $bar) = @{shift(@_)}{qw/ -foo -bar /}
by ihb (Deacon) on Apr 13, 2004 at 03:58 UTC

    What I don't like with default argument setups like yours is that they too often throw away a 0 argument. I find this quite disturbing, especially when I sometimes just want to set something to false but the routine does my $foo = shift; $self->{foo} = $foo if defined $foo and I gave a false (undefined) value. But I digress.

    To adress the real issue again, I'd like to provide some constructors I sometimes use. I'm not very consistant myself in this matter, and I'm lazy and strict from time to time.

    An alternative way to write yours, that I find more attractive is

    { my %SELF = map { $_ => '' } qw( foo bar baz ); sub new { my $self = bless { %SELF } => shift; @$self{keys %SELF) = @{+shift}{keys %SELF}; return $self; } }
    This still explicitly defines the parameters, yet honours false values. You can also easily set other default values by just extending the list assigned to %SELF.

    Another way I've used is

    { my %SELF = ( foo => 0, bar => "", baz => [], ); sub new { my $self = bless {} => shift; my %p = @_; croak("...") if keys %p > keys %SELF; # If given a bad key. $self->$_($p{$_}) foreach keys %p; # Lazy. Damn lazy. return $self; } }
    I can't say this is a routine I recommend for daily use, but it was a slick routine in its context.

    Yet another...

    sub new { my $self = bless { foo => 0, bar => "", baz => [], this_should_not_be_touched_here => {}, } => shift; my %p = @_; $self->{$_} = delete $p{$_} for grep exists $p{$_} => qw/ foo bar baz /; # Note, this list doesn't equal keys(%$self). croak("Unknown parameters: @{[keys %p]}") if %p; return $self; }
    The benefit with this is that you don't expose some elements that perhaps shouldn't be set in the constructor. The other is that you easily detect typos as they'll show up as unknown parameters.

    I really had no point besides the false value issue with this post. I just felt like elaborating and tossing around ideas. :-)

    ihb

      A zero and empty string are (mostly) the same thing as far as Perl is concerned. The only time I worry about ditching undef values is if my interface exlicitly states that undef is different from any other false value. Otherwise you're asking to get a lot of 'use of unintitilized value' warnings.

      BTW--I like your @$self{keys %SELF) = @{+shift}{keys %SELF}; example, but it deserves some comments for the poor maintance programmer, who may not have as much Perl-foo as you do.

      ----
      : () { :|:& };:

      Note: All code is untested, unless otherwise stated

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://332920]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (4)
As of 2024-04-19 16:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found