Consider this: while(<DATA>) is about the same as while(defined($_ = <DATA>)). We should be able to agree that there are two pieces of magic going on here. The first is the implicit assignment to $_, and the second is the implicit defined test. perlop can help shed some light. The implicit assignment is interesting:

If and only if the input symbol is the only thing inside the conditional of a while statement (even if disguised as a for(;;) loop), the value is automatically assigned to the global variable $_

That explains one of the bugs in your code. You have more than just the input operator in your while(...) construct. Therefore, there is no implicit assignment to $_. Your loop's body expects there to be a useful value in $_, but there isn't, because it's not being assigned to.

Next consider reverse. Perl's reverse is actually a rather bizarre operator in how it handles context. The context of a conditional expression in a while(COND) construct is scalar context. Therefore, you get this behavior, as described in reverse:

reverse LIST ... in scalar context, concatenates the elements of LIST and returns a string value with all characters in the opposite order.

The documentation provides this example:

print scalar reverse "dlrow ,", "olleH"; # Hello, world

All the lines get concatenated together, and then everything is reversed. So if you resolved the first bug, you would have the second; that instead of getting the lines in reverse, you get the entire slurped in file's characters in reverse.

The third bug is a little harder; Since you're pulling in the entire file in one fell swoop, your loop body will only execute once. On the second pass <DATA> will return undef.

Your goal, I believe, is to read each line in reverse order. There are two reasonable ways to do this, based on how big the input file is. If the file doesn't ever grow too big, just slurp the whole thing in: my @lines = reverse <DATA>. This invokes reverse in LIST context, so that it leaves the character order for each line in tact, and just reverses the order of the lines. But if the file could possibly grow large enough that memory is a consideration, use File::ReadBackwards. This example is a little awkward since File::ReadBackwards isn't really designed for reading the __DATA__ segment. But it should convey the simplicity of using this module:

#!/usr/bin/env perl use strict; use warnings; use FindBin qw($Bin); use File::Spec::Functions qw(catfile); use File::ReadBackwards; my $bw = File::ReadBackwards->new(catfile($Bin,$0)) or die "Can't read $0: $!\n"; while( defined(my $line = $bw->readline) ) { last if $line =~ m/^__(?:END|DATA)__/; print $line; } __DATA__ 1234 5678 9ABC DEFG

This produces:

DEFG 9ABC 5678 1234

The File::ReadBackwards module reads the file in chunks of 8192 bytes, seeking from the end upward. Therefore, it never needs to hold the entire file in memory at once.


Dave


In reply to Re: Uninitialized value in reverse by davido
in thread Uninitialized value in reverse by Nordikelt

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.