Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I redefine Perl class methods?

Tags:

perl

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:

  • I have a bunch of methods like this.
  • I'd rather not dirty up this method.

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);
like image 766
mmccoo Avatar asked Mar 11 '09 16:03

mmccoo


2 Answers

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?

like image 194
innaM Avatar answered Nov 19 '22 23:11

innaM


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.

like image 4
brian d foy Avatar answered Nov 19 '22 22:11

brian d foy