Beefy Boxes and Bandwidth Generously Provided by pair Networks DiBona
Perl Monk, Perl Meditation

Comment on


I was all set to give a superb answer to Tests for 'printing' code. I went to test my code and ruined it all.

Here's the great code failure:

use Errno ':POSIX'; { no warnings 'redefine', 'once'; local *CORE::GLOBAL::print = sub { $! = ENOSPC; return; }; print 'test', $/ or die $!; }
I intended to override builtin print so that it prints nothing, and triggers a 'No space left on device' system error in the same way print would. The handiness for testing is obvious. Trouble is this code doggedly prints 'test', completely ignoring the override.

After poking around for syntactos and scratching my head and reading the wrong docs, I posed the question in CB. Why doesn't this work? I got two answers.

One was that print is not overridable because it is an object method and doesn't really act like a function. That makes sense - the indirect object notation of print FOO @List makes the handle look very like an object. But, in Perl, or in OO in general, what kind of object method isn't overridable? Why isn't there something like a *CORE::GLOBAL::IO namespace with an overridable print method? Or is there?

The more convincing answer was that print is not overridable because the prototype is too complicated. The ability to have a default indirect object is the only complication I see, but it seems enough. The comment in perldoc -f prototype about things not overridable, things whose arguments are not expressible as a prototype, and things which don't really act like functions was the major justification for this view.

That doesn't entirely hold water. The expression prototype 'CORE::glob' evaluates to undef. Code from Camel3, p307 shows how to make glob take perl regular expressions rather than shell glob patterns. Corrected, it reads,

*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
which works just fine. In spite of the prototype docs, glob is overridable, certainly function-like, and it obviously has the simple prototype (;$), though that seems not reflected in CORE::.

I'm puzzled that global print is not overridable. It seems a natural function to want to do that to. It doesn't modify its arguments, so prototypes don't play an important role. In fact, many uses would ignore the arguments. Does anyone know why *CORE::GLOBAL::print is read-only?

I've tried this with my oldest perl, 5.004_02 for djgpp, and the behavior is the same. Prototypes were present in that version, so perhaps that's no surprise. Was global print ever overridable?

I'd appreciate any technical or historical insight the monks may offer on these questions. Print seems an odd function to leave out of the fun.

After Compline,

In reply to !Overriding Builtin print by Zaxo

and:  <code> code here </code>

  • Please read these before you post! —
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Log In?

    What's my password?
    Create A New User
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others meditating upon the Monastery: (4)
    As of 2014-03-16 05:44 GMT
    Find Nodes?
      Voting Booth?

      Have you used a cryptocurrency?

      Results (326 votes), past polls