|P is for Practical|
Re: Uninitialized value in reverseby davido (Cardinal)
|on Apr 24, 2020 at 21:10 UTC||Need Help??|
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:
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:
The documentation provides this example:
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:
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.