Be aware that doing

sub describe { my $ref = shift(); my %person = %{$ref}; print "$person{name} is a $person{job}" } ... describe( { person=>'buffy', job=>'vampire slayer' } );

You are not "passing an anonymous hash" you are

  • use the hash we just calculated as the index into the array of arrays we (re) constructed
  • follow the VALUE pointer and get the string 'Buffy'
  • push that onto a new array (@_) that we will pass to print
  • Look up the address of the function print and pass the array @_ to it.
  • Discard the variable $ref
  • Discard the hash %person
  • Discard the array @_ (twice)
  • Discard the anonymous hash
  • Return to the calling program.
  • NOTE: This is far from an accurate picture, but the main inaccuracies are in the steps that I haven't expanded!

    The point is that by constructing an anonymous hash from a list, passing that hash, by reference to a sub, then flattening that hash back to a list and then constructing a new hash from that list, you are doing a huge amount of work that is completely unnecessary and wasteful. It is true that perl does this in the "twinkling of an eye", but by avoiding it, it could achieve the same ends in a "twinkle of a twinkling".

    If your going to use named parameters to subs, either pass a list in and construct the hash (once) at the destination.

    sub describe { my %person = @_; print "$person{name} is a $person{job}" } ... describe( person=>'buffy', job=>'vampire slayer' );

    Or, construct the anonymous hash in the calling program, pass a reference and use that reference to access the hash you constructed.

    sub describe { my $personref = shift; print "$person->{name} is a $person->{job}"; } ... describe( { person=>'buffy', job=>'vampire slayer' } );

    The way you are doing it here is just sooo wasteful. For two element hashes with short keys and one depth of call, the overhead is probably not dramatic in realtime terms. But if you use this practice for larger hashes with longer keys and going a several levels deep, it really begins to mount up.

    By way of demonstration, these results from the benchmark below show the difference in using 4 different methods of passing two strings to a sub and using those parameters to contruct a string for printing.

    p:\test>Bench Rate describe1 describe2 describe3 describe4 describe1 5186/s -- -28% -76% -78% describe2 7232/s 39% -- -66% -70% describe3 21387/s 312% 196% -- -11% describe4 24048/s 364% 233% 12% --

    For this set of results, the sub only constructed the string and didn't actually print it. Print is a relatively expensive operation. One view is that if the sub you are calling is going to do anything substancial (like calling print), the overhead of the parameter passing and access tends to pail in to insignificance. After all those numbers above show that describe1() will process 5,186 pairs of parameters in a second or one pair every 193 microseconds. Okay, but describe4() does 24,080 in a second or 1 every 41 microseconds. but to be fair, here are the results from the same benchmark, this time actually calling print.

    p:\test>Bench -P -N=-1 >log Rate describe1 describe2 describe3 describe4 describe1 4458/s -- -25% -71% -73% describe2 5907/s 32% -- -62% -65% describe3 15361/s 245% 160% -- -8% describe4 16639/s 273% 182% 8% --

    As you can see, that slows thing down considerably. describe4() is now only 2 1/2 times quicker rather than 3 1/2 times quicker than describe1(). And, if the sub was doing anything more substantial, then this difference is further depleted, but it is worth thinkng about when you code your subs.

    The benchmark code

    #! perl -slw use strict; use Benchmark qw[ cmpthese ]; use vars qw[ $P $N ]; sub describe1 { my $ref = shift; my %person = %{ $ref }; my @__passed_to_print = "$person{person} is a $person{job}"; print @__passed_to_print if $P; } sub describe2 { my $ref = shift; my @__passed_to_print = "$ref->{person} is a $ref->{job}"; print @__passed_to_print if $P; } sub describe3 { my( $person, $job ) = @_; my @__passed_to_print = "$person is a $job"; print @__passed_to_print if $P; } use constant { PERSON=>0, JOB=>1 }; sub describe4 { my @__passed_to_print = "$_[PERSON] is a $_[JOB]"; print @__passed_to_print if $P; } cmpthese( $N || -1, { describe1 => q[ describe1( { person=>'Buffy', job=>'Vampire Slayer +' } ); ], describe2 => q[ describe2( { person=>'Buffy', job=>'Vampire Slayer +' } ); ], describe3 => q[ describe3( 'Buffy', 'Vampire Slayer +' ); ], describe4 => q[ describe4( 'Buffy', 'Vampire Slayer +' ); ], });

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
    If I understand your problem, I can solve it! Of course, the same can be said for you.


    In reply to Re: Re: Re: Sending an anonymous hash to a sub by BrowserUk
    in thread Sending an anonymous hash to a sub by Cody Pendant

    Title:
    Use:  <p> text here (a paragraph) </p>
    and:  <code> code here </code>
    to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.