Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Re: "Backing up" a subroutine during runtime.

by TGI (Parson)
on Oct 21, 2008 at 18:49 UTC ( [id://718561] : note . print w/replies, xml ) Need Help??


in reply to "Backing up" a subroutine during runtime.

This looks pretty slick.

I'd probably put some more abstraction into the interface of the loader function. Also, you shouldn't need two steps to create a backup and install a new sub.

#!/usr/bin/perl package test_package; use strict; use warnings; sub new { return bless {}; } sub test_function { print "Original test_function! $_[1]\n"; } sub loader { my $self = shift; my $override = shift; # Name of function to override. my $new_function = shift; # code ref to install my $backup; # keep a code ref of the original here. local @_; eval { no strict 'refs'; no warnings 'redefine'; die "Can't override non-existant function $override\n" unless exists &{$override}; $backup = \&{$override}; *{$override} = $new_function; }; if ( $@ ) { warn "ERROR: $@\n" if ( $@ ); $backup = undef; } return $backup; } package main; use strict; use warnings; my $counter = 0; my $f = new test_package(); $f->test_function($counter++); # 1 my $newsub = sub { print "New output! $_[1]+\n"; 1 }; # Replace function, get backup in return. my $backup = $f->loader( 'test_package::test_function', $newsub ); $f->test_function($counter++); # Restore function. $f->loader( "test_package::test_function", $backup); $f->test_function($counter++); my $faked =$f->loader( "test_package::fake_function", $newsub ); warn "Unable to override function" unless $faked; #$f->fake_function( 'Fake'); # program will die

If you specifically want to focus on overriding and restoring functions, you could actually use your object to store the names of overridden functions and their original code refs. Then your code could look like this:

$f->override( 'test::function', sub { print 'foo' } ); # Do your testing; $f->restore( 'test::function' );

Update: You might also want to look at Sub::Installer.


TGI says moo