[% setvar title UNIVERSAL::require() %]
Note: these documents may be out of date. Do not use as reference! |
To see what is currently happening visit http://www.perl6.org/
UNIVERSAL::require()
Maintainer: Michael G Schwern <schwern@pobox.com> Date: 17 Sep 2000 Mailing List: perl6-language@perl.org Number: 253 Version: 1 Status: Developing
UNIVERSAL::require() allows modules to be loaded from variables with $module->require rather than the current eval "require $module";
Currently, to load a module one uses either require() or use() with a bareword
expression. require $variable
is reserved for loading and evaling files.
It is not obvious how one loads a module from the value of a variable.
Currently, its done like this:
$module = "Some::Module"; eval "require $module";
This has two problems. First, its unintuitive. Secondly, $@ is often accidentally not checked, so if the module load fails the error will not be noticed.
As a solution, a UNIVERSAL:::require() method can be added with the following syntax:
$module = "Some::Module"; $module->require;
This is neatly analagous with $module->import and causes a run-time error should the module fail to load.
UNIVERSAL::use() and thus $module-
use> would be an obvious analogy, but
unfortunately use() is a compile-time beastie. Variables and methods are
run-time. It would be confusing for use() to be compile-time and
UNIVERSAL::use() to be run-time, so UNIVERSAL::use() should not be.
Instead, this code suffices:
BEGIN { $module->require; $module->import; }
We see here how neatly the UNIVERSAL::require() syntax lines up with Exporter::import().
Of course, if you really want a run-time use() method you can easily write one.
The lack of a UNIVERSAL::use() leaves out module version checking (ie. use
Some::Module 0.23
). UNIVERSAL::require() can take on this feature by taking
a version as an argument.
$module->require(0.23);
What should happen if UNIVERSAL::require() is called as an object method?
Should it eval "require ".ref $obj
or should it be an error? Because the
situation is very rare when you will have an object from a class which has not
yet been required, UNIVERSAL::require() should only work as a class method.
$obj-
require> should be an explicit run-time error.
If require() is desired as an object method, it can easily be overridden with:
sub require { my $proto = shift; my $class = ref $proto || $proto; return $class->SUPER::require; }
Ta da.
A complete Perl 5 implementation follows:
package UNIVERSAL; sub require { my($class, $want_version) = @_; die("UNIVERSAL::require() can only be run as a class method") if ref $class; die("UNIVERSAL::require() takes no or one arguments") if @_ > 2; # Load the module. my $return = eval "CORE::require $class"; # Check for module load failure. if( $@ ) { $@ =~ s/ at .*?\n$//; die sprintf "$@ at %s line %d.\n", (caller)[1,2]; } # Module version check. my $have_version = ${$class.'::VERSION'}; if( @_ == 2 and $have_version < $want_version ) { die sprintf "%s version %s required--this is only version %s ". "at %s line %d\n", $class, $want_version, $have_version, (caller)[1,2]; } return $return; }
this could be added to UNIVERSAL.pm and eventually implemented in universal.c. It could even be safely added to Perl 5.
RFC 103 laments that require $class
does not DWIM.