On Sun, Apr 13, 2008 at 5:45 PM, Randal L. Schwartz
<[EMAIL PROTECTED]> wrote:
> >>>>> "Kelly" == Kelly Jones <[EMAIL PROTECTED]> writes:
>
>  Kelly> I have a file with this in it:
>  Kelly> a.b = 10
>  Kelly> c.d.e = 11
>  Kelly> f.g.h.i.j.k = 12
>
>  Kelly> Based on that, I want to set:
>
>  Kelly> $HASH{a}{b} = 10;
>  Kelly> $HASH{c}{d}{e} = 11;
>  Kelly> $HASH{f}{g}{h}{i}{j}{k} = 12;
>
>  Kelly> This is easy using eval(), but is there a better way?
>
>  Yes. http://www.perlmonks.org/index.pl?node_id=443584
snip

At least in Perl 5.8.8 the for loop solution is faster (significantly
so for the get case), but the reduce solution is more general.  When
only getting values, the reduce method autovivifies keys; this could
cause errors in the program later.

get_for didn't autovivify 42 42
get_pte did autovivify 42 42
get_reduce did autovivify 42 42
set_for 42 42
set_pte 42 42
set_reduce 42 42
               Rate   set_pte   get_pte set_reduce get_reduce   set_for  get_for
set_pte    196495/s        --       -0%       -15%       -19%      -29%     -68%
get_pte    197284/s        0%        --       -15%       -19%      -28%     -68%
set_reduce 231848/s       18%       18%         --        -5%      -16%     -62%
get_reduce 242811/s       24%       23%         5%         --      -12%     -60%
set_for    275692/s       40%       40%        19%        14%        --     -55%
get_for    607350/s      209%      208%       162%       150%      120%       --

#!/usr/bin/perl

use strict;
use warnings;

use List::Util;
use Benchmark;

sub pointer_to_element {
        local ($a, $b);
        return List::Util::reduce(sub { \($$a->{$b}) }, \shift, @_);
}

my %h;
my %subs = (
        set_pte => sub {
                my $ref = pointer_to_element(\%h, qw<foo bar baz>);
                return $$ref = 42;
        },
        get_pte => sub {
                my $ref = pointer_to_element(\%h, qw<foo bar baz>);
                return $$ref;
        },
        set_reduce => sub {
                my $ref = List::Util::reduce(sub {\($$a->{$b}) }, \(\%h), 
qw<foo bar baz>);
                return $$ref = 42;
        },
        get_reduce => sub {
                my $ref = List::Util::reduce(sub {\($$a->{$b}) }, \(\%h), 
qw<foo bar baz>);
                return $$ref;
        },
        set_for    => sub {
                my $ref = \%h;
                $ref = $ref->{$_} = {} for qw<foo bar>;
                return $ref->{baz} = 42;
        },
        get_for    => sub {
                my $ref = \%h;
                $ref = $ref->{$_} for qw<foo bar>;
                return $ref->{baz};
        },
);

for my $sub (sort keys %subs) {
        print "$sub ";
        %h = ();
        if ($sub =~ /^get/) {
                my $val = $subs{$sub}->();
                print exists $h{foo}{bar}{baz} ? "did " : "didn't ", 
"autovivify ";
                $h{foo}{bar}{baz} = 42
        }
        $subs{$sub}->();
        print $subs{$sub}->(), " $h{foo}{bar}{baz}\n";
}

Benchmark::cmpthese(-1, \%subs);

snip
>  And if you want better answers to questions, use monks.
>  Not sure why these mailing lists exist, anyway!
snip

Well, this mailing list exists specifically because all of the
alternatives (Perl Monks, c.l.p.m, c.l.p, etc.) were/are seen as being
hostile to new users.  I admit that this list has started to
degenerate (and I am just as guilty as anyone else).  Perhaps it is
time to start sending out the FAQ again (I have been meaning to, but
Real Life(tm) interfered).  If anyone has any updates for the FAQ, let
me know.

-- 
Chas. Owens
wonkden.net
The most important skill a programmer can have is the ability to read.

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/


Reply via email to