develooper Front page | perl.perl5.porters | Postings from March 2000

AUTOLOADREF

Thread Next
From:
M.J.T. Guy
Date:
March 15, 2000 01:51
Subject:
AUTOLOADREF
Message ID:
E12VASS-0006zZ-00@ursa.cus.cam.ac.uk
You can do lots of clever things with AUTOLOAD.    But there's also a
lot wrong with it.

*  you can't take a reference to an autoloaded subroutine

*  you can't optimise autoloaded constant subs

*  the search for autoloaded methods has to be done in the "wrong"
   order

*  autoload and prototypes don't mix well

*  there's no way for autoload to report "failed to load"

*  the use of global variable $AUTOLOAD is ugly at best

*  search the p5p archives for lots of other examples

All these problems have the same root cause  -  the fact that you can't
load a subroutine without also calling it.

So I propose a new reserved subroutine AUTOLOADREF.   (The name is
deliberately ugly to encourage people to make better suggestions.
Also see below for an alternative to a new reserved word.)

If it exists, AUTOLOADREF is called whenever AUTOLOAD would have been
called (and before AUTOLOAD if both exist) with arguments

        AUTOLOADREF( $subname, $flags, @_ )

It returns a reference to the required subroutine (which it may also
have defined), or false on error.    [ How should error messages
be reported? ]    Then Perl simply calls the returned subroutine.

The behaviour of method loading is modified  -   AUTOLOADREF is
simply called at the appropriate point in the search of the @ISA tree,
rather than in a second pass as with AUTOLOAD.    So AUTOLOADREF
does the Right Thing with respect to inheritance, unlike AUTOLOAD.

To get constant subs right, we can call AUTOLOADREF at compile time
and then check the resulting prototype.    It also allows to
do the Right Thing wrt prototypes.    (And it presumably would make
unnecessary the optimisation which causes $main::{foo} to be '$@'
which is currently causing trouble.)    This also allows subroutines
to be autoloaded at compile time if desired.

The $flags are used to tell AUTOLOADREF why it's being called:

       * normal load and execute
       * take reference
       * compile time prototype / constant check

In the "normal load" case, AUTOLOADREF has the option of returning
a reference to a scalar or to an array, indicating that it *has*
actually called the subroutine, and here is the scalar / list result.
This allows simulation of those special AUTOLOADs which don't define
a subroutine but simply calculate the result directly.

In the "compile time" case, AUTOLOADREF has the option of returning
a true result which isn't a reference.    This says  "the subroutine
exists, and I've predeclared it (possibly with prototype)" and
allows compile time prototype checking without compile time loading,
so you can do the Right Thing in cases like

         if ($very_rare_condition()) {
               my_enormous_subroutine;
         };

That's about it.    I'm sure there are lots of other goodies that can be
derived from this approach, but this message has got long enough already.

And I'd guess it'd all be very easy to implement  -  basically just
copying out the current AUTOLOAD code, mutatis mutandis.    But I
haven't actually investigated the sources.

Oh.. and an alternative to a new reserved word?    The modern Perlish
way would be to have an attribute, say

      sub AUTOLOAD : newfangled { ... }

But this has a disadvantage that it isn't backward compatible.   With
a separate subroutine, a module can supply both AUTOLOADREF for new
Perls and AUTOLOAD for old Perls (presumably just a wrapper round
AUTOLOADREF).    That's why I stipulated above that AUTOLOADREF should
be checked before AUTOLOAD.


OK, that's enough.     Now tell me what I've overlooked.



Mike Guy

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About