Many built-in functions may be
overridden, although (like knocking holes in your
walls) you should do this only occasionally and for good reason.
Typically, this might be done by a package attempting to emulate
missing built-in functionality on a non-Unix system. (Do not confuse
overriding with overloading, which adds
additional object-oriented meanings to built-in operators, but doesn't
override much of anything. See the discussion of the
overload
module in Chapter 13 for more on that.)
Overriding may be done only by importing the name from
a module--ordinary predeclaration isn't good enough. To be perfectly
forthcoming, it's the assignment of a code reference to a typeglob
that triggers the override, as in *open =
&myopen
. Furthermore, the assignment must occur in some
other package; this makes accidental overriding through typeglob
aliasing intentionally difficult. However, if you really want to do
your own overriding, don't despair, because the
subs
pragma lets you predeclare subroutines via the
import syntax, so those names then override the built-in ones:
use subs qw(chdir chroot chmod chown); chdir $somewhere; sub chdir { … }
In general, modules should not export built-in names like
open
or chdir
as part of their
default @EXPORT
list, since these names may sneak
into someone else's namespace and change the semantics unexpectedly.
If the module includes the name in the @EXPORT_OK
list instead, importers will be forced to explicitly request that the
built-in name be overridden, thus keeping everyone honest.
The original versions of the built-in functions are
always accessible via the CORE
pseudopackage.
Therefore, CORE::chdir
will always be the version
originally compiled into Perl, even if the chdir
keyword has been overridden.
Well, almost always. The foregoing mechanism for overriding
built-in functions is restricted, quite deliberately, to the package
that requests the import. But there is a more sweeping mechanism you
can use when you wish to override a built-in function everywhere,
without regard to namespace boundaries. This is achieved by defining
the function in the CORE::GLOBAL
pseudopackage.
Below is an example that replaces the glob
operator
with something that understands regular expressions. (Note that this
example does not implement everything needed to cleanly override
Perl's built-in glob
, which behaves differently
depending on whether it appears in a scalar or list context. Indeed,
many Perl built-ins have such context-sensitive behaviors, and any
properly written override should adequately support these. For a fully
functional example of glob overriding, study the
File::Glob
module bundled with Perl.) Anyway,
here's the antisocial version:
*CORE::GLOBAL::glob = sub { my $pat = shift; my @got; local *D; if (opendir D, '.') { @got = grep /$pat/, readdir D; closedir D; } return @got; } package Whatever; print <^[a-z_]+.pm$>; # show all pragmas in the current directory
By overriding glob
globally, this
preemptively forces a new (and subversive) behavior for the
glob
operator in every
namespace, without the cognizance or cooperation of modules that own
those namespaces. Naturally, this must be done with extreme
caution--if it must be done at all. And it probably mustn't.
Our overriding philosophy is: it's nice to be important, but it's more important to be nice.