Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re: $. - smarter than you might think

by shmem (Chancellor)
on Jun 22, 2006 at 22:35 UTC ( #557033=note: print w/replies, xml ) Need Help??


in reply to $. - smarter than you might think

You can even assign to it and cheat about the line number:
#!/usr/bin/perl <DATA>; $.= 39; print "$. $_" while <DATA>; __DATA__ line 1 line 2 line 3
BTW, the DATA filehandle is funny as well. This prints it's source along with line numbers (perl 5.8.8):
#!/usr/bin/perl seek DATA,0,0; print "$. $_" while <DATA>; __DATA__ line 1 line 2 line 3
gives
1 #!/usr/bin/perl 2 3 seek DATA,0,0; 4 print "$. $_" while <DATA>; 5 __DATA__ 6 7 line 1 8 line 2 9 line 3

Bug or feature? :-)

cheers,
--shmem

Update: this is covered implicitly in perl561delta, Potential to leak DATA filehandles:

Using the "__DATA__" token creates an implicit filehandle to th +e file that contains the token. It is the program's responsibility to + close it when it is done reading from it.

_($_=" "x(1<<5)."?\n".q/)Oo.  G\        /
                              /\_/(q    /
----------------------------  \__(m.====.(_("always off the crowd"))."
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

Replies are listed 'Best First'.
Re^2: $. - smarter than you might think
by GrandFather (Saint) on Jun 22, 2006 at 22:53 UTC

    Ohh, that's nice, if you expect it. :)

    So you can have a Perl script print itself by:

    use warnings; use strict; seek DATA, 0, 0; print while <DATA>; __END__

    so long as __END__ or __DATA__ are present.

    Of course that also means that you have to my $dataStart = tell DATA; if you want to seek DATA back to the data start rather than script start.


    DWIM is Perl's answer to Gödel
      heh.. that makes me think about a $SIG{__DIE__} handler which not only says harshly "Can't do method foo in context bar in file quux line 1024" or such, but prints the 3 lines above and below the error as well...
      don't talk nonsense at blah.pl line 23. 21 learn('nothing'); 22 sub blah (\[&]) { 23 warn "don't talk nonsense"; > 24 $_[0]->(); 25 } 26 sub learn { 27 my $self->teach(shift); Can't use string ("bar") as a subroutine ref while "strict refs" in us +e at blah.pl line 24.

      I discovered this playing with your code, btw. Thanks!

      cheers,
      --shmem

      #!/usr/bin/perl use strict; $SIG{__DIE__} = sub { if(my ($d) = $_[0] =~ /line (\d+)/) { seek DATA,0,0; while(<DATA>) { if($. == $d) { warn '> '.$..' '.$_; } else { warn ' '.$..' '.$_ if ($. > $d - 4) && ($. < $d + 4); } } } }; my $foo = 'bar'; blah($foo); learn('nothing'); sub blah (\[&]) { warn "don't talk nonsense"; $_[0]->(); } sub learn { my $self->teach(shift); warn "got it"; } __END__
      hmm.. why does it succeed to compile and run whilst calling blah() with a scalar and not a subref?

      _($_=" "x(1<<5)."?\n".q/)Oo.  G\        /
                                    /\_/(q    /
      ----------------------------  \__(m.====.(_("always off the crowd"))."
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

        Ok, I played with your code and came up with a modification of my own:

        local $SIG{__DIE__} = sub { my ($d) = ( $_[0] =~ /line (\d+)\.$/ ); unless ($d) { print STDERR $_[0]; return; } my $context = 3; #number of context lines seek DATA,0,0; while(<DATA>) { next if $. < ($d-$context); #cycle until context starts warn ($. == $d ? '>' : ' ') #mark line if it contains the error .sprintf('%4d ',$.) #use 4-place line numbers (alignment) .$_; #show code on line last if $. > ($d+$context); #move on once we've finished context } };

        The actual run-time efficiency on long code will be helped by the last if.. line: there's no reason to keep doing I/O once your context has been exhausted.

        The other modifications are largely maintenance-minded:

        1. variable for number of context lines makes it easier to change your mind about context later;
        2. using the (?:) syntax allows me to have all formatting done in one place, making it easier to change the format of printed lines at will;

        I also fixed one potential bug in your regex: you would have matched any 'line \d+' in the string -- I could break your code by die('I had a problem reading the data file at line 12'). You'd see the context of your code around line 12, but the relevant code might be around line 60 or something. The new regex takes the match at the end of the message.

        Updates:

        • 2006-06-26 : trailing paren crept in, removed -- thanks to shmem for noticing

        <radiant.matrix>
        A collection of thoughts and links from the minds of geeks
        The Code that can be seen is not the true Code
        I haven't found a problem yet that can't be solved by a well-placed trebuchet

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://557033]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (6)
As of 2021-05-17 17:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Perl 7 will be out ...





    Results (158 votes). Check out past polls.

    Notices?