http://www.perlmonks.org?node_id=491162

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Greetings. I am trying to figure out how to override 'use'.

BEGIN{ use subs qw(use); sub use{ print "Using fake use\n"; } } use Data::Dumper;
However, this didn't seem to work. I tried enclosing the enclosing the 'subs' pragma and the fake 'use' definition in a BEGIN block because the 'use' occurs at compile time. Alas, this didn't seem to work.

Thus I have come to you seeking enlightenment. I am going about this wrong? Is it even possible to override the 'use' special form? Is their documentation anywhere specifying what CORE subroutines are and are not overridable?

Replies are listed 'Best First'.
Re: Overriding 'use'?
by Zaxo (Archbishop) on Sep 12, 2005 at 06:52 UTC

    There are several theories about how to tell when a builtin is overridable, for example if prototype 'CORE::foo' is defined foo is overridable. That's mostly true, but there are exceptions.

    Here's a quick way to tell:

    $ perl -e'BEGIN{ *CORE::GLOBAL::use = sub{1};} use CGI qw/:standard/; +print header' Content-Type: text/html; charset=ISO-8859-1 $
    The override didn't take, so use is what it is.

    A simpler version:

    $ perl -e'use Fatal qw/use/;' Cannot make a non-overridable builtin fatal at /usr/lib/perl5/5.8.4/Fa +tal.pm line 108. BEGIN failed--compilation aborted at -e line 1. $
    Unfortunately, Fatal uses the defined prototype rule to decide that.

    After Compline,
    Zaxo

Re: Overriding 'use'?
by rinceWind (Monsignor) on Sep 12, 2005 at 10:51 UTC

    You've not actually stated what you want to override 'use' for. If you are wanting to intercept use (and require), there is another way to do this.

    Perl 5.8.x: If you insert a CODEREF into @INC (unshift, push or splice), the sub gets invoked magically, and can do its own work to provide the module. See perldoc -f require. To intercept 'use', you need to do this in a BEGIN block at the top of your main script.

    --

    Oh Lord, won’t you burn me a Knoppix CD ?
    My friends all rate Windows, I must disagree.
    Your powers of persuasion will set them all free,
    So oh Lord, won’t you burn me a Knoppix CD ?
    (Missquoting Janis Joplin)

      Also, depending on what you want to do, you could override the import routine of a module, either wrapping it or replacing it entirely. You still suffer the load penalties of require, but you can rejigger the part that actually does work. Not sure why you would want to do it, but just want to point out that it's possible.

      # Replace Data::Dumper::import BEGIN { no warnings 'redefine'; require Data::Dumper; *Data::Dumper::import = sub { warn "Can't use Data::Dumper" }; }

      Since a module is only require-ed once, any subsequent calls to use Data::Dumper should skip the require call, but will invoke your new "import" routine. I'd guess this is only really useful if you wrap it rather than replace it. E.g.

      # Count times "Data::Dumper::import" is called, e.g. via use BEGIN { no warnings 'redefine'; require Data::Dumper; # initialize the counter my $dumper_counter = 0; # save the original import sub before replacing it my $dumper_import = *Data::Dumper::import{CODE}; # install import wrapper with closures *Data::Dumper::import = sub { $dumper_counter++; $dumper_import->(@_); }; }

      Big warning bells should be going off in your head if you actually want to try stuff like this. (E.g. import isn't always called; import looks at caller to find what package to install into, so you may need to use Sub::Uplevel to fake it, etc.) This is fine for experimentation, but I'd warn against it for any production needs. But, nevertheless, it's instructive into just how flexible the Perl symbol table system is.

      -xdg

      Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.