http://www.perlmonks.org?node_id=800455

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

Every now and again, I want to set the value of a number of properties on an object from a hash, where the method name is the same as the key name, but with a prefix, eg

$object->set_date( $hash{ date } );

But how to do this for all the keys in a hash? I've thought of two methods:

Method 1: --------- for ( keys %hash ) { my $method = "set_$_"; $object->$method( $hash{ $_ } ); } Method 2: --------- for ( keys %hash ) { $object->${ \"set_$_" }( $hash{ $_ } ); }

I prefer the second method, because it is shorter, but (1) it is less readable and (2) Perl::Tidy reformats it with a space before the arrow, which still works, but looks rather odd:

$object ->${ \"set_$_" }( $hash{$_} );

Which method would you prefer? One of the above, or some other syntax?

(Note: I benchmarked the difference between these two, and while the temp var is slightly faster, the difference is negligible.)

#!/usr/bin/perl use strict; use warnings; use Benchmark qw(cmpthese); package foo; { sub set_var1 { } sub set_var2 { } sub set_var3 { } sub set_var4 { } sub set_var5 { } } package main; my $object = bless {}, 'foo'; my %hash = map { ( "var$_" => $_ ) } ( 1 .. 5 ); sub temp_var { for ( keys %hash ) { my $method = "set_$_"; $object->$method( $hash{$_} ); } } sub deref { for ( keys %hash ) { $object ->${ \"set_$_" }( $hash{$_} ); } } cmpthese( 1_000_000, { temp_var => \&temp_var, deref => \&deref } );
Results:
Rate deref temp_var deref 176991/s -- -18% temp_var 215054/s 22% --

Update: corrected a typo in Method 2, thanks to zwon for pointing it out

Replies are listed 'Best First'.
Re: Formatting dynamic method names
by zwon (Abbot) on Oct 10, 2009 at 13:43 UTC

    Perhaps it should be

    Method 2: --------- for ( keys %hash ) { $object->${ \"set_$_" }( $hash{$_} ); }

    Update: concerning the question, I would prefer first method. It explains itself, so it is clear what it is doing even for newbie. Second statement, though shorter, will require more time to read and understand for some persons.

      You mean, without the space before the arrow? Yes, it should, but given that I use Perl::Tidy on my code, it's always going to put the space in there. Sorry - just realised that I'd left out the value :$ - will update
Re: Formatting dynamic method names
by AnomalousMonk (Archbishop) on Oct 10, 2009 at 20:15 UTC
    sub temp_var { for ( keys %hash ) { my $method = "set_$_"; $object->$method( $hash{$_} ); } }
    This benchmark code also includes the creation of a lexical scalar as well as assignment to it. The benchmark would be slightly more accurate (and slightly faster) if the lexical were defined outside the loop and used inside. (However, I doubt the speed difference would be significant.)

    I would agree with zwon in preferring the 'temp var' approach.

      Interesting - here are the results:

      Rate deref temp_var reused_lexic +al deref 173010/s -- -21% -2 +7% temp_var 218818/s 26% -- - +8% reused_lexical 238095/s 38% 9% +--

      (Note: these benchmarks are for interest only, and are firmly in the field of premature optimization)