The question "How can I monkey-patch an instance method in Perl?" got me thinking. Can I dynamically redefine Perl methods? Say I have a class like this one:
package MyClass;
sub new {
my $class = shift;
my $val = shift;
my $self = { val=> $val};
bless($self, $class);
return $self;
};
sub get_val {
my $self = shift;
return $self->{val}+10;
}
1;
And let's say that adding two numbers is really expensive.
I'd like to modify the class so that $val+10 is only computed the first time I call the method on that object. Subsequent calls to the method would return a cached value.
I could easily modify the method to include caching, but:
What I really want to do is specify a list of methods that I know always return the same value for a given instance. I then want to take this list and pass it to a function to add caching support to those methods
Is there an effective way to accomplish this?
Follow up. The code below works, but because use strict doesn't allow references by string I'm not 100% where I want to be.
sub myfn {
printf("computing\n");
return 10;
}
sub cache_fn {
my $fnref = shift;
my $orig = $fnref;
my $cacheval;
return sub {
if (defined($cacheval)) { return $cacheval; }
$cacheval = &$orig();
return $cacheval;
}
}
*{myfn} = cache_fn(\&myfn);
How do I modify to just do this?:
cache_fn(&myfn);
You can overwrite methods like get_val from another package like this:
*{MyClass::get_val} = sub { return $some_cached_value };
If you have a list of method names, you could do something like this:
my @methods = qw/ foo bar get_val /;
foreach my $meth ( @methods ) {
my $method_name = 'MyClass::' . $meth;
no strict 'refs';
*{$method_name} = sub { return $some_cached_value };
}
Is that what you imagine?
I write about several different things you might want to do in the "Dynamic Subroutines" chapter of Mastering Perl. Depending on what you are doing, you might want to wrap the subroutine, or redefine it, or subclass, or all sorts of other things.
Perl's a dynamic language, so there is a lot of black magic that you can do. Using it wisely is the trick.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With