Subject: | Possibly return of use_package_optimistically() into a tri-state? |
Currently use_package_optimistically() either rethrows parsing
exceptions, or returns the module name if the module loaded, or has not
been found on disk. Is it possible to indicate this tri-state by
returning false instead when the module is not found? By the way: the
current documentation of use_package_optimistically() mentions the
return value in the paragraph explaining the VERSION argument. There is
no clear definition (yet) concerning what is returned on
use_package_optimisitically('Foo').
The use case: I am looking to deduplicate a bunch of code from
Class::C3::Componentised, by using Module::Runtime wherever possible.
Among other things it contains a method load_optional_class, which
either returns 1 on success, or returns 0 when the requested module is
not found (by examining $@) or rethrows the exception. Currently my code
looks like this (note - the horrible API choices were made years ago, I
am keeping them for backcompat purposes):
sub load_optional_class {
my ($class, $f_class) = @_;
# can not short circuit to M::R::require_module (or even better -
# to M::R::use_package_optimistically) because someone may be hooking
# ensure_class_loaded() :(((
# ensure_class_loaded either returns a () (*not* true) or throws
# it has already been converted to use M::R::require_module() so
# it correctly does the module name checks etc
eval {
$class->ensure_class_loaded($f_class);
1;
} && return 1;
my $err = $@; # so we don't lose it
if ( ! eval { Module::Runtime::check_module_name($f_class); 1 } ) {
$err = $@;
}
else {
my $fn = quotemeta(
Module::Runtime::module_notional_filename($f_class) );
return 0 if ($err =~ /\ACan't locate ${fn} in \@INC/ );
}
if ($class->can('throw_exception')) {
$class->throw_exception($err);
}
else {
die $err;
}
}
If M::R::use_package_optimistically() returned false on "can't locate"
errors, then the above could have been shortened to:
sub load_optional_class {
my ($class, $f_class) = @_;
# can not short circuit to M::R::require_module (or even better -
# to M::R::use_package_optimistically) because someone may be hooking
# ensure_class_loaded() :(((
# ensure_class_loaded either returns a () (*not* true) or throws
# it has already been converted to use M::R::require_module() so
# it correctly does the module name checks etc
eval {
$class->ensure_class_loaded($f_class);
1;
} && return 1;
my $err = $@; # so we don't lose it
if (eval { Module::Runtime::use_package_optimistically($f_class) }) {
die "wtf... ensure_class_loaded fails but use_package_optimistically
succeeds...???"
}
elsif ($@ ne "") { # no exception but false
return 0;
}
if ($class->can('throw_exception')) {
$class->throw_exception($err);
}
else {
die $err;
}
}
Cheers