Is it possible to redefine subroutines to be localized for a part of the code?

193 views Asked by At

Is it possible to redefine the _function_used_by_exported_function only for the exported_function call in the second_routine?

#!/usr/bin/env perl
use warnings; 
use strict;
use Needed::Module qw(exported_function);


sub first_routine {
    return exported_function( 2 );
}

no warnings 'redefine';

sub Needed::Module::_function_used_by_exported_function {
    return 'B';
}

sub second_routine {
    return exported_function( 5 );
}

say first_routine();
say second_routine();
1

There are 1 answers

0
simbabque On BEST ANSWER

You can locally redefine the sub _function_used_by_exported_function inside your sub second_routine.

package Foo;
use warnings; 
use strict;
use base qw(Exporter);
our @EXPORT = qw(exported_function);

sub exported_function {
  print 10 ** $_[0] + _function_used_by_exported_function();
}

sub _function_used_by_exported_function {
  return 5;
}

package main;
use warnings; 
use strict;

Foo->import; # "use"

sub first_routine {
    return exported_function( 2 );
}

sub second_routine {
    no warnings 'redefine';
    local *Foo::_function_used_by_exported_function = sub { return 2 };
    return exported_function( 5 );
}

say first_routine();
say second_routine();
say first_routine();

I lifted the typeglob assignment inside sub second_routine from brian d foy's Mastering Perl, Chapter 10 on page 161. The sub is redefined by assigning to the typeglob, which only replaces the coderef part of it. I use local to only do that inside the current block. That way, the outside world is not affected by the change, as you can see in the output.

1051
1000021
1051