Subject: | UNIVERSAL::require for non-file modules |
Date: | Sun, 12 Nov 2006 18:10:53 -0600 |
To: | bug-UNIVERSAL-require [...] rt.cpan.org |
From: | Michael G Schwern <schwern [...] gmail.com> |
Allow ->require to work on non-file modules.
For example, let's say you define a package in a test...
{ package Foo; sub bar { 23 } }
And then call Foo->require. Right now it will fail because there is no Foo.pm. What if it did a check similar to base.pm? Part of Ruz's patch below does just that.
Show quoted text
-------- Original Message --------
Subject: [PATCH] UNIVERSAL::require speed up
Date: Fri, 30 Jul 2004 14:43:29 +0400
From: Ruslan U. Zakirov <cubic@acronis.ru>
To: Michael G Schwern <schwern@pobox.com>
Hello, Michael.
This patch integrates version glob check into your module to be shure
that we don't call 'eval "..."' if required module is allready in place.
This patch has only one limitation: with patch applied require doesn't
return correct 'return value' of the required module. IMHO this value is
useless and I don't know any module that relay on this value except true
or false context.
I don't remeber exactly where I got this glob trick, but find it very
usefull especially in parsers with run-time plugins based on modules.
Benchmark: timing 900000 iterations of plain, old, new...
plain: 38 wallclock secs (35.77 usr + 0.03 sys = 35.80 CPU) @
25139.66/s (n=900000)
old: 49 wallclock secs (46.46 usr + 0.04 sys = 46.50 CPU) @
19354.84/s (n=900000)
new: 14 wallclock secs (13.36 usr + 0.02 sys = 13.38 CPU) @
67264.57/s (n=900000)
Also I stripped args sanity checks from local version:
12 wallclock secs (12.61 usr + 0.01 sys = 12.62 CPU) @ 71315.37/s
(n=900000)
Best regards. Ruslan.
diff -Nru UNIVERSAL-exports-0.03/lib/UNIVERSAL/require.pm UNIVERSAL-exports-0.03-c1/lib/UNIVERSAL/require.pm
--- UNIVERSAL-exports-0.03/lib/UNIVERSAL/require.pm 2001-12-17 06:00:45.000000000 +0300
+++ UNIVERSAL-exports-0.03-c1/lib/UNIVERSAL/require.pm 2004-07-30 14:09:35.000000000 +0400
@@ -94,15 +94,22 @@
die("UNIVERSAL::require() takes no or one arguments") if @_ > 2;
- # Load the module.
- my $return = eval "CORE::require $module";
+ my $return = 1;
- # Check for module load failure.
- if( $@ ) {
- $@ =~ s/ at .*?\n$//;
- $UNIVERSAL::require::ERROR = sprintf "$@ at %s line %d.\n",
- (caller)[1,2];
- return 0;
+ # Check if module is allready in place
+ no strict qw( refs );
+ my $vglob = ${'${module}::'}{'VERSION'};
+ unless( $vglob ) {
+ # Load module
+ $return = eval "CORE::require $module";
+
+ # Check for module load failure.
+ if( $@ ) {
+ $@ =~ s/ at .*?\n$//;
+ $UNIVERSAL::require::ERROR = sprintf "$@ at %s line %d.\n",
+ (caller)[1,2];
+ return 0;
+ }
}
# Module version check. We can't just call UNIVERSAL->VERSION
@@ -114,6 +121,12 @@
return 0;
}
+ # Set fake module version if doesn't check version and
+ # module have no scalar VERSION
+ unless( @_ != 2 && $vglob ) {
+ *{ '${module}::VERSION' } = '-1, By UNIVERSAL-require';
+ }
+
return $return;
}
diff -Nru UNIVERSAL-exports-0.03/t/require.t UNIVERSAL-exports-0.03-c1/t/require.t
--- UNIVERSAL-exports-0.03/t/require.t 2001-12-17 06:00:59.000000000 +0300
+++ UNIVERSAL-exports-0.03-c1/t/require.t 2004-07-30 13:46:05.000000000 +0400
@@ -47,7 +47,7 @@
use lib qw(t);
-ok( Dummy->require == 23, 'require()' );
+ok( Dummy->require, 'require()' );
ok( $UNIVERSAL::require::ERROR eq '', ' $ERROR empty' );
ok( $Dummy::VERSION, ' $VERSION ok' );
@@ -55,7 +55,7 @@
$SIG{__WARN__} = sub { warn @_
unless $_[0] =~ /^Subroutine \w+ redefined/ };
delete $INC{'Dummy.pm'};
- ok( Dummy->require(0.4) == 23, 'require($version)' );
+ ok( Dummy->require(0.4), 'require($version)' );
ok( $UNIVERSAL::require::ERROR eq '', ' $ERROR empty' );
delete $INC{'Dummy.pm'};