Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Any chance of shooting myself in the foot with this code?
sub _sum { my $total = 0; return (map $total += $_, @hash{'foo', 'bar', 'baz'})[-1]; }
Or, perhaps, is there a neater WTDI with a nearly-one-liner like this (ie, other than your generic for-loop)?

Thx in advance...

Replies are listed 'Best First'.
Re: sum function
by merlyn (Sage) on Dec 25, 2000 at 20:17 UTC
Re: sum function
by chromatic (Archbishop) on Dec 25, 2000 at 23:39 UTC
    sub _sum { my $hash = shift; my $total = 0; $total += $_ for @$hash{ @_ }; return $total; }
    You can use a list of keys as indices into a hash. It's called a hash slice, and it's very very nice.
Re: sum function
by ichimunki (Priest) on Dec 25, 2000 at 19:40 UTC
    Here. This is definitely NOT shorter, but it is more robust. And unless I'm clueless, using map in a situation like this creates a second array in RAM, which you are throwing away. While this may not be a problem, it does not promote efficient memory management.
    #!/usr/bin/perl -w use strict; my %hash = ( foo => '123' , bar => '234', batz => '345', bongo => '100' ); #send reference to hash, and list of keys to sum print sum_hash( \%hash, 'foo', 'bar', 'batz' ) . "\n"; #send reference to hash, will sum all numeric values print sum_hash( \%hash ) . "\n"; sub sum_hash { my $t_hash = shift; my $total; if (@_) { for (@_) {$total += $t_hash->{$_}; } } else { for ( keys %$hashref ) { $total += $t_hash->{$_}; }; } return $total; }
      For the else block, it's simpler to iterate over the values() rather than the keys. (Mind the name of the variable...)
      else { for (values %$t_hash) { $total += $_ } # (use the statement modifier for if preferred) }
      The two blocks could also be combined into a single loop -- whether this is an improvement, I'm not sure. :)
      sub sum_hash { my $href = shift; my $total = 0; for ( @_ ? @{$href}{@_} : values %$href ) { $total += $_; } return $total; }
      If @_ contains any elements, iterate over a hash slice using the contents of @_ as the keys; otherwise iterate over all the values in the hash.
        Chipmunk, I love it. Your second method is especially Perlish.
Re: sum function
by I0 (Priest) on Dec 29, 2000 at 21:37 UTC
    return unpack'%99d*',pack'd*',@hash{'foo', 'bar', 'baz'};
      Stop that!

      That kind of code is evil!

      Besides which, you are making me think. :-)

        #or if your numbers are large use POSIX; unpack"%@{[(DBL_MAX_EXP)-1]}d*",pack"d*",@hash{'foo', 'bar', 'baz'};

        >;-}