Suppose a Perl module named MyApplication/Subcomponent.pm, and like usual the file starts with package MyApplication::Subcomponent; This module happens to define a collection of utility functions. One of those utility functions needs to create an instance of a local, internal-use-only class. The class definition is very simple so I'll just paste it here. It's a RAII class that saves and restores the value of an environment variable.
{
package MyApplication::Subcomponent::restore_ENV_THING;
sub DESTROY {
my $self = shift;
$ENV{THING} = ${ $self };
}
sub new {
my $class = shift;
my $old_value = $ENV{THING};
$ENV{THING} = shift;
return bless \$old_value, $class;
}
}
It's my understanding that I have to give this class a name in the global space of package names, and I have to name it starting from the root: I can't just write package restore_ENV_THING; because that would stomp on the top level of the namespace.
So here's the question: What, if anything, could I do so that the code that uses this class -- which is guaranteed to be in the same file as the above code block and lexically below it -- could be written
sub utility_routine_that_needs_to_save_and_restore_THING {
my $restorer = restore_ENV_THING->new($temporary_value);
...
}
instead of
sub utility_routine_that_needs_to_save_and_restore_THING {
my $restorer = MyApplication::Subcomponent::restore_ENV_THING
->new($temporary_value);
...
}
If you know a trick that would allow me not to have to give the class a name in the global space of package names (perhaps something not entirely unlike what open my $fh, ... does?) I would like to hear about that too.
Note that MyApplication has some unusual constraints on its code:
- The oldest supported version of Perl is 5.006. Yes, you read that right, 5.006. In particular this means I cannot use lexically scoped subs.
- No CPAN modules may be used, only modules that were included in the stdlib as of 5.006. This is why I don't just use Guard or Scope::Guard, and why I am manually defining the class using primitives.
- Cannot ship any XS code itself. This is why I am using
sub DESTROYfor RAII even though that won't work right if the guard object is mishandled in the caller; as far as I know, there's no way to do better without dropping down to C.