In the example module below, the getters and setters are generated by adding anonymous subroutines to the symbol table. After the methods have been created in this manner, will the resulting code be functionally equivalent (in terms of behavior, speed, etc.) to a module with manually-written getters and setters, or does this approach have some sort of inherent liability? (I have done some basic speed benchmarking and have not detected any differences so far.)
package Module;
use strict;
use warnings;
BEGIN {
my @attr = qw(author title number);
no strict 'refs';
for my $a (@attr){
*{__PACKAGE__ . "::get_$a"} = sub { $_[0]->{$a} };
*{__PACKAGE__ . "::set_$a"} = sub { $_[0]->{$a} = $_[1] };
}
}
sub new {
my $class = shift;
bless { @_ }, $class;
}
1;
There should be no difference in runtime performance if the resulting code is the same in both cases. This is usually not possible, however, unless you use string
evalto create your subroutines. For example, the code you provided:will be ever-so-slightly slower than the code you would have written manually:
simply because the former has to get the value of the variable $a before using it as a key to the hash, whereas the later uses a constant as its hash key. Also, as an aside,
shiftusually tends to be faster than$_[0]. Here’s some benchmark code:and the results on my system:
They’re so close that differences may get lost in the noise, but over many trials I think you’ll see that the “manual shift” variant is the fastest. But as with all microbenchmarks like this, you have to test your exact scenario on your hardware and your version of perl to be sure of anything.
And here’s string eval thrown into the mix.
It should be exactly the same as the “manual” variants, plus or minus the statistical noise. My results:
Again, these are all so close that you’d have to take great pains and perform many trials to sort out the signal from the noise. But the difference between using a constant as a hash key and using a variable (whose value must first be retrieved) as a hash key should show through. (The
shiftoptimization is a separate issue and is more likely to change one way or the other in past or future versions of perl.)