This and other RFCs are available on the web at
  http://dev.perl.org/rfc/

=head1 TITLE

UNIVERSAL::require()

=head1 VERSION

  Maintainer: Michael G Schwern <[EMAIL PROTECTED]>
  Date: 17 Sep 2000
  Mailing List: [EMAIL PROTECTED]
  Number: 253
  Version: 1
  Status: Developing

=head1 ABSTRACT

UNIVERSAL::require() allows modules to be loaded from variables with
$module->require rather than the current eval "require $module";

=head1 DESCRIPTION

Currently, to load a module one uses either require() or use() with a bareword
expression.  C<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.


=head2 What about use()?

UNIVERSAL::use() and thus C<$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.


=head2 Version checking

The lack of a UNIVERSAL::use() leaves out module version checking (ie. C<use
Some::Module 0.23>).  UNIVERSAL::require() can take on this feature by taking
a version as an argument.

    $module->require(0.23);


=head2 UNIVERSAL::require() is only a class method.

What should happen if UNIVERSAL::require() is called as an object method? 
Should it C<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. 
C<$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.


=head1 IMPLEMENTATION

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.


=head1 REFERENCES

RFC 103 laments that C<require $class> does not DWIM.

Reply via email to