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

Hey Monks,

I'm looking for a way to create a reference to a function in the CORE:: pseudo package. Basically, I want $printfunc->("hello") to either use some user-defined function ('myprint' below) or the built-in print (CORE::print), depending on what $printfunc is set to.

However, there seems to be some problem with the 'pseudo' package CORE, check it out:
sub myprint { print "MYPRINT: ", @_; } my $printfunc; # Works $printfunc = \&main::myprint; $printfunc->("hello\n"); # Doesn't work $printfunc = \&CORE::print; $printfunc->("hello\n");
I could possibly wrap it up in
sub coreprint { print @_; }; $printfunc = \&coreprint;
but I'm a stickler and would like get a more elegant solution :). Any ideas?

Replies are listed 'Best First'.
Re: Reference to functions in CORE:: pseudo package?
by blokhead (Monsignor) on Feb 01, 2004 at 19:38 UTC
    From perlsub (emphasis added):
    To unambiguously refer to the built-in form, precede the built-in name with the special package qualifier CORE::. For example, saying CORE::open() always refers to the built-in open(), even if the current package has imported some other subroutine called &open() from elsewhere. Even though it looks like a regular function call, it isn't: you can't take a reference to it, such as the incorrect \&CORE::open might appear to produce.
    I think there's nothing wrong with wrapping print in a sub like you have. The only inelegant thing is that you are creating a new named sub. Why not use an anonymous sub like this?
    sub myprint { print "MYPRINT: ", @_; } my $printfunc = $condition ? sub { print @_; } : \&myprint; $printfunc->("hello world\n");
    Or even make myprint anonymous as well:
    my $printfunc = $condition ? sub { print @_; } : sub { print "MYPRINT: ", @_; }

    blokhead

Re: Reference to functions in CORE:: pseudo package?
by Zaxo (Archbishop) on Feb 01, 2004 at 23:14 UTC

    There is a highly magical way to override some core keywords. Here, I'll override glob to never find anything,

    $ ls AGM AGM.pm foo $ perl -e'print prototype("CORE::glob"), $/' $ perl -e'{ local *CORE::GLOBAL::glob = sub {()}; while (<*>) {print " +Oh, No!\n"} } while (<*>){ print "Ha!\n"}' Ha! Ha! Ha! $
    I tried printing the prototype of the builtin function to see if a prototype was needed to override.

    Unfortunately, print cannot be overridden. I told that tale in !Overriding Builtin print.

    After Compline,
    Zaxo

      AFAIK, it only works to override keywords at compile time (i.e. in BEGIN or with use). That kinda ruins it for scoped override like you have. (Though you may be able to use a named sub and temporarily replace the sub with local).

      Update: Zaxo's code does work, though I don't understand why. Perhaps something special about glob? Trying to override a different function works the way I recall:

      $ # override in BEGIN block works $ perl -e'BEGIN { *CORE::GLOBAL::sin = sub { "a" } } print sin(0)' a $ # override at runtime doesn't have any effect $ perl -e'*CORE::GLOBAL::sin = sub { "a" }; print sin(0)' 0 $ # using local, still no effect $ perl -e'{ local *CORE::GLOBAL::sin = sub { "a" }; print sin(0) } pri +nt sin(0) ' 00