Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

Overloading Perl's Built-In's

by bbfu (Curate)
on Jan 12, 2001 at 12:41 UTC ( #51326=perlquestion: print w/replies, xml ) Need Help??

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

I was looking at the Time::localtime module and noticed that it overloaded perl's built-in, localtime(). I was wondering how it it worked.

Looking to the internals, it seemed to me that it just exported (via Exporter) it's localtime() function. Nothing special. When I tried that, however, it didn't work.

Try as I might, I could not get my module to overload the built-in in the use'ing program. I thought I understood exporting fairly well. I even tried exporting by hand (via typeglob assignment, see The Second Try below) to no avail. (I know I'm doing this correctly because it works for variables and non-built-in functions.)

As far as I can tell, Time::localtime is not doing anything special besides exporting the function. There must be something I'm missing!

I've included a simple test program and two modules (the Exporter version and the typeglob version) below, as well as the output I get from the program and what the output should be.

Can anyone please help me to understand what's going on here and what I'm doing wrong?

The Program

#!/usr/bin/perl -w use strict; use lib '.'; use MyTest; my $x = "blah blah blah\n"; chomp($x); print "^$x\$\n";
The First Module
package MyTest; use strict; BEGIN { use Exporter (); use vars qw(@ISA @EXPORT); @ISA = qw(Exporter); @EXPORT = qw(chomp); } sub chomp(@) { my $str = shift; CORE::chomp($str); return $str . "_this is a test"; } 1;
The Second Try
package MyTest; use strict; sub import { *main::chomp = \&MyTest::chomp; # Doesn't work # *::chomp = \&MyTest::chomp; # Doesn't work either # *CORE::chomp = \&MyTest::chomp; # Nope # *main::chomp = \*MyTest::chomp; # Sorry, no go # *::chomp = \*MyTest::chomp; # I wish # *CORE::chomp = \*MyTest::chomp; # Please, give it up } sub chomp($) { my $str = shift; CORE::chomp($str); return $str . "_this is a test"; } 1;
The Output ^blah blah blah$ What The Output Should Be ^blah blah blah_this is a test$

Replies are listed 'Best First'.
Re: Overloading Perl's Built-In's
by danger (Priest) on Jan 12, 2001 at 13:50 UTC

    Not all built-in functions may be overridden, and chomp() is one of the ones that can't be overridden. Even if it were, you're new versions of chomp() wouldn't have worked as you expected because you only operating on a copy of the argument rather than the argument itself.

    Only functions with 'weak' keywords may be overridden -- those are the ones defined to return a negative value in toke.c in the perl source code. Here is a list of + keywords, which includes all the functions that may *not* be overridden (since it is a shorter list):

    __DATA__ __END__ AUTOLOAD BEGIN CHECK chop chomp DESTROY do delete def +ined END else eval each elsif exists for format foreach grep goto glob INIT + if keys last local m my map next no our pop pos push print printf package prototype q qr qq qw qx redo return s scalar shift sort split splice study sub tr tie tied use undef until untie unless unshift while y

      Even if it were, you're new versions of chomp() wouldn't have worked as you expected because you only operating on a copy of the argument rather than the argument itself.

      Actually, that was the point of the new chomp(). Stems from this discussion in this thread. Though, of course, I was using the function kind-of incorrectly, since it would've not worked if the function had been overloaded. But I was looking for the extra "\n" before the '$' at the end (hrm, I just realized my "expected output" is wrong! :).

      Anyway, thanks bunches for explaining about the 'weak' keywords and return values in toke.c! I'll have to take a look at that file when I get the chance.

Re: Overloading Perl's Built-In's
by dchetlin (Friar) on Jan 12, 2001 at 13:57 UTC
    This is an excellent and well thought out question. Solid ++. The answer is, you haven't done anything wrong. The documentation is a little unclear on this point, but certain Perl operators are overridable, and certain others aren't. In perl 5.6.0 and earlier, chomp was not overridable. So nothing you can do will get your subroutine to be called in place of the built-in.

    However, our very own ctweten noticed this in September and discovered that there's no reason at all chomp (and chop) shouldn't be overridable, and patched perl to make that possible. This change was too late for 5.6.0, but is in 5.7.0 and has been integrated into the 5.6.1 trial release 1. So, pending something horrifically bizarre, your first test module should work just fine on 5.6.1.

    In the meantime, I would suggest playing around with a different operator to learn how to overload built-ins. If you're interested and have a copy of the source for your version of perl sitting around, the way to figure out what's overridable is by this one-liner, courtesy Nick Ing-Simmons:

    perl -ne 'print "$1\n" if /return\s*KEY_(\w+)/' toke.c

    Hope this is helpful. Keep up the good work.


      Thanks for your help! I'm definately going to have to look at toke.c when I get the chance (tomorrow at work =).

      Is Perl 5.7 out already? I knew about 5.6 and I thought they were working on 5.6.2... Did they skip over 5.6.2 and are comming back to it after 5.7? Maybe I should start reading Perl News, too! =) And I only just found this site!

        Is Perl 5.7 out already
        • 5.7 is the development branch that will eventually produce 5.8.

        • 5.6.x is the maintenance and bugfix branch for 5.6.

        "Perl makes the fun jobs fun
        and the boring jobs bearable" - me

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://51326]
Approved by root
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (6)
As of 2021-01-15 17:54 GMT
Find Nodes?
    Voting Booth?