tags:

views:

110

answers:

3

The Overriding Built-in Functions section of the perlsub documentation provides

There is a second method that is sometimes applicable when you wish to override a built-in everywhere, without regard to namespace boundaries. This is achieved by importing a sub into the special namespace CORE::GLOBAL::.

and then gives a few examples. At the end, however, is

Finally, some built-ins (e.g. exists or grep) can't be overridden.

What is the full list?

+8  A: 

Any value that is negative in toke.c can be overridden; all others may not. You can look at the source code here.

For example, let's look at waitpid on line 10,396:

    case 'w':
      if (name[1] == 'a' &&
          name[2] == 'i' &&
          name[3] == 't' &&
          name[4] == 'p' &&
          name[5] == 'i' &&
          name[6] == 'd')
      {                                       /* waitpid    */
        return -KEY_waitpid;
      }

Since waitpid is negative, it may be overridden. How about grep?

        case 'r':
          if (name[2] == 'e' &&
              name[3] == 'p')
          {                                   /* grep       */
            return KEY_grep;
          }

It's positive, so it cannot be overridden. That means that the following keywords cannot be overridden:

chop, defined, delete, do, dump, each, else, elsif, eval, exists, for, foreach, format, glob, goto, grep, if, keys, last, local, m, map, my, next, no, package, pop, pos, print, printf, prototype, push, q, qq, qw, qx, redo, return, s, scalar, shift, sort, splice, split, study, sub, tie, tied, tr, undef, unless, unshift, untie, until, use, while, y

John Feminella
The link in the OP contains a specific example of mocking `glob`.
mobrule
That example does it by exporting a `glob` symbol to the calling package, not replacing a symbol in `CORE::GLOBAL::`
friedo
There must be some additional magic: `chop` and `splice` can be mocked. I think `shift`, `unshift`, `push`, and `pop` can, too.
mobrule
@friedo: it's even stranger than that. From what I can tell, you can set `*CORE::GLOBAL::glob`, and then `CORE::glob` will call the mocked function, too.
mobrule
+2  A: 

There was an earlier question on SO lamenting the difficulty of mocking the filetest operators (-f, -d, -x, ...)

mobrule
+3  A: 

The prototype function will tell you if you can override a CORE:: function.

Here is a hacked together attempt to get all the functions without having to type them:

#!/usr/bin/perl

use strict;
use warnings;

open my $fh, "-|", "perldoc", "-u", "perlfunc" or die $!;
my %seen;
while (<$fh>) {
    next unless my ($func) = /=item ([a-z]\w+)/;
    next if $seen{$func}++;

    my $prototype = prototype "CORE::$func";

    print "$func is ", defined $prototype ? "overiddable with $prototype " :
        "not overiddable", "\n";
}
Chas. Owens
There is additional magic that allows `do`, `require`, and `glob` to be overridden. See `perlsub` for the what (if not the how and why).
mobrule