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

I was working on a rather complicated script that had an internal debug mechanism whereby it would print trace data to a debug file if I set the debug flag in my script. And I was thinking, wouldn't it be cool if these comments were numbered. Then I was thinking, wouldn't it be cool if every print command generated an index value and prefixed the output with it. This way I could re-construct the order of the output messages.

So my question is: Is there a way to overload the print function to print a scalar index, increment the index, and then print whatever it was supposed to print in the first place? I can think of several uses for this, but I don't know how to do it.
Thanks. -Adam

Replies are listed 'Best First'.
Re: Line Numbers
by Abigail (Deacon) on Jul 02, 2000 at 12:34 UTC
    There's a short and a long answer. The short answer is no. (The reason is that the syntax is special cased. You cannot make a user function with the same prototype.)

    The long answer is, yes you can, provided you use IO::File and use its print method. Then you can just subclass IO::File, and mask the print method.

    -- Abigail

Re: Line Numbers
by wnodom (Initiate) on Jul 01, 2000 at 05:59 UTC

    Instead of overloading print, how about redirecting STDOUT with a tied filehandle? Try this:

    #! /usr/bin/perl -w
    
    package NumberedPrint;
    
    use strict;
    
    sub new
      {
        my $self = bless {}, shift;
        $self;
      }
    
    sub TIEHANDLE
      {
        shift->new(@_);
      }
    
    {
      my $printed_to_stdout = 0;
    
      sub PRINT
        {
          shift;
          print ORIGINAL_STDOUT ++$printed_to_stdout, ': ', @_;
        }
    
      sub PRINTF
        {
          shift;
          print ORIGINAL_STDOUT ++$printed_to_stdout, ': ', sprintf(@_);
        }
    }
    
    *ORIGINAL_STDOUT = *main::STDOUT;
    
    tie *main::STDOUT, 'NumberedPrint';
    
    package main;
    
    print "Hello.\n";
    print "Hello again.\n";
    print "Hello a third time.\n";
    
    print NumberedPrint::ORIGINAL_STDOUT "\nA line without a number.\n";
    
    select NumberedPrint::ORIGINAL_STDOUT;
    
    print "A lot of\n";
    print "lines without\n";
    print "any numbers.\n";
    print "\n";
    
    select STDOUT;
    
    print "The final line.\n";
    
    __END__
    
    

    This is probably pretty fragile, but may do what you need. I found a similar technique in Lennart Borgman's Win32::ASP::Cgi module, and it seems to work pretty well there (albeit for a totally different purpose).

    --Bill

Re: Line Numbers
by btrott (Parson) on Jun 30, 2000 at 22:56 UTC
    There's probably a way of overloading print (export to CORE::GLOBAL?); there's an example in the mod_perl guide for overloading die. So you may be able to overload print, but maybe not.

    But why don't you just write a debug (or trace) function that you can call. The debug function should print out whatever message it's given, but only if the debug flag is set. You could even make it OO, and make the debug flag a member of the Trace object. Or whatever you want to call it. Then you can do whatever you want in the debug method, including printing out numbered messages, and also printing out caller information, if you want.

      I've used similar techniques in the past, but they are not very satisfying. Additionally, this would require me to locate all my debug statements and upgrade them to the new method. I was hoping to avoid that.
Re: Line Numbers
by maverick (Curate) on Jun 30, 2000 at 23:36 UTC
    __LINE__ is a global symbol that represents the current line number of the script. This isn't exactly what you're looking for, but it should help you out none the less.
    print __LINE__, " some stuff with a line number\n";
    you might also want to check out the function "caller", it can give you the line number from which the current subroutine was called

    /\/\averick
RE: Line Numbers
by mdillon (Priest) on Jun 30, 2000 at 23:56 UTC
    i'm pretty sure that print cannot be overloaded. in the Perl Cookbook, recipe 12.11, print is listed as one of the functions that cannot be overloaded as of 5.004. it refers to the function keyword() in toke.c for determining whether or not you can overload a built-in function. looking at toke.c in 5.6, it looks as if it is still not possible to overload print.
Re: Line Numbers
by KM (Priest) on Jun 30, 2000 at 23:47 UTC
    After mucking around with this for a while, as well as having others muck around, we can't seem to come up with an easy way to overload print. If you are feeling ambitious, take a look at the code for Fatal.pm, which may help you. Also look at the archives for c.l.p.m(oderated|isc) and see if this has come up there. If you don't mind the first line not being numbered, you could always use $\ to do this. Interesting problem, hopefully I will have a tuit to muck with it this weekend. But, I believe that since 5.004 or something this is one of the functions that can't be overloaded.

    Cheers,
    KM

A reply falls below the community's threshold of quality. You may see it by logging in.