Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"

Re: Saving data to file

by davido (Archbishop)
on Apr 08, 2014 at 04:57 UTC ( #1081461=note: print w/replies, xml ) Need Help??

in reply to Saving data to file

Update2: Related threads where the OP has been encouraged (with more benevolent patience, apparently to no effect) to spend a little time figuring out lexicals, and the hows and whys of 'strict': Arrays and Push, Array storage issue.

My first thought was that if you're going to fall into bugs as a direct result of abusing package globals to avoid the alarms that strict sets off, even though people have warned you about the practice, you aren't going to benefit from our help, and I may as well not bother. But if you're willing to sit through a little rant that is intended to proverbially knock some sense into you, perhaps there is hope. So....

First, my rant:

Don't abuse package globals in an attempt to avoid learning how to use lexical variables. And if you must continue, be honest enough with yourself to discontinue using strict. Yes, I'm advocating for not using strict until you are committed to learn why it should be used. It is doing you no good the way you are using it now anyway.

What really should happen is this: spend an hour with perlsub, my, and strict, and another hour or so with a book like Modern Perl, or Learning Perl, so that you can come to a better understanding of why you should be using lexicals, how to use them, and why strict 'vars' is a useful means of encouraging safe practices. However, right now, the way your code includes use strict; but side-steps it is like leaving your seat belt clicked all the time so that you won't be disturbed by the "ding, ding" alarm, and then sitting on top of it because it's too hard to slide under it when it's already fastened.

Now for the problem you are asking about:

Your bug is on line 12; this line: &output($main::data[$main::i]);

The reason that's a bug is because $main::data holds an array reference, but you are acting as though @main::data holds an array, which it doesn't. @main::data doesn't even exist. The simplest fix involving minimal keystrokes is to change that line to this: output($main::data->[$main::i]); This error would have been caught at compile-time if you hadn't been using fully qualified package globals in order to circumvent strictures! Had @data been a lexical, strict 'vars' would have complained about using a variable that wasn't pre-declared. How ironic that your insistence on avoiding learning how to use lexicals so that you might benefit from use strict 'vars'; has now cost you more time than it would have taken to learn to use them.

Even the use warnings; is trying to help, by telling you that the variable you're referring to in line 12 contains an undefined value, which is a red flag.

There's another problem, but it doesn't rise to the level of bug: scalar @{\@{$main::data}} is outright silly. Why not scalar @{\@{\@{\@{$main::data}}}}? What you are doing is taking an array ref ($main::data), dereferencing it with "@{...}", taking a reference to that with \, and then dereferencing that reference with scalar @{...}. That's an onion that needs to be peeled: scalar @{$main::data}.

Then there's another problem, which again doesn't rise to level of bug: Inside your for loop, you are opening and closing the same file repeatedly. Why? Open it outside of the loop, write to it inside the loop, and close it when the loop finishes. If you know you're going to be writing to it repeatedly, and not reading from it in the meantime, save the overhead and complexity of opening it repeatedly.

Here is how I would write that code:

use strict; use warnings; my @data = qw( 1 0 1 2 3 4 5 6 7 8 9 11 2 2 3 34 5 6 7 8 81 ); open my $fh, '>', 'output.txt' or die $!; print $fh "$_\n" foreach @data; close $fh or die $!;

Update: Other trivia which I will mention only briefly, because they are not directly causing problems, but are also either risky behavior (not checking return values of system calls), or non-idiomatic: This isn't C; you don't need to pre-declare your subroutines. This isn't Perl4; Drop the ampersand on your subroutine calls -- it will get you into trouble someday because it changes the calling semantics in a subtle way that you shouldn't have to deal with unless you really need that behavior. Make sure that your system calls are guarded by checking their return values for errors; open and close can fail, and should not fail silently. This isn't C; use range-based foreach loops to your advantage. You almost never need for( $i; $i != $n; ++$i ) {... in Perl (but very occasionally it is useful enough to be included in the language).


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1081461]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (7)
As of 2017-05-23 04:09 GMT
Find Nodes?
    Voting Booth?