in reply to Re^2: unquoted string error??!!
in thread unquoted string error??!!

Here is my (humble) opinion on why it is best to avoid bareword file handles...(Update: except for STDIN, STDERR, DATA, ARGV, and the like...)

While it doesn't matter in a situation as simple as in the OP, in a non-trivial situation, if you use a lexical file handle (and 'use strict'), you can avoid the following bug:

#!/usr/bin/perl use strict; use warnings; my $file = "file.txt"; CreateFile($file); system frobnicate => $file; sub CreateFile { my $f = shift; open(OUTPUT_FILE, ">$f") or die "Err: $!"; for (1..100) { print OUTPUT_FILE "$_\n"; } # blah, blah, blah... close OUTPUT_FH }
This exact sort of thing happened here@work, where there is a serious lack of lexical file handle use, and took a non-zero amount of time to debug. It also failed to influence anyone's decision in choice of file handle type :-(

Replies are listed 'Best First'.
Re^4: unquoted string error??!!
by JavaFan (Canon) on May 05, 2011 at 11:04 UTC
    Here is my (humble) opinion on why it is best to avoid bareword file handles...
    Yeah, let's avoid reading from STDIN, or avoid writing to STDOUT or STDERR. Or make use of the magical handles DATA or ARGV.

    As long as the three most important filehandles (important enough that by default (at least on Unix), all processes will have them) are bare file handles, I cannot stop thinking "uttered by someone with limited knowledge of Perl" when hearing advice like "is best to avoid bareword file handles".

    As for you example bug; first of all, your use of warnings would have caught any typos in filehandle names - close OUTPUT_FH generates the warning Name "main::OUTPUT_FH" used only once: possible typo at: .... Furthermore, the above does have a serious bug: it's not checking the return value of closed. If it did, it would have notices the failure of closing a handle that wasn't opened.

      Yeah, let's avoid reading from STDIN, or avoid writing to STDOUT or STDERR.

      Oh, c'mon. Oversight due to generalization, updated post.

      And to your other points: Yes, warnings are easy to notice in programs with very little output. And as noted elsewhere, there may or may not have been only a 'used once' warning in the actual code. And whether or not you catch the error in closing a handle that's already closed, it's better to catch the error at 'compile' time rather than runtime. Also note, "IT'S NOT MY CODE", and I consider myself lucky if others check the return value of open and include $! in the error message. If they start checking the return value of close, I might die of shock.

Re^4: unquoted string error??!!
by tchrist (Pilgrim) on May 04, 2011 at 17:31 UTC
    If you willfully ignore all warnings and meaningful return values, then of course you should expect to have inherently buggy code:
    % perl -Mautodie /tmp/buggy Name "main::OUTPUT_FILE" used only once: possible typo at /tmp/buggy l +ine 16. Can't close filehandle 'OUTPUT_FH': 'Bad file descriptor' at /tmp/bugg +y line 19
    Did you somehow expect something else? Perl gives you the tools to diagnose and debug such buggery. Do not blame Perl if you ignore its prudent advice.

    PROOF: Lexicals Filehandles Aren’t

    I have a problem with this whole “lexical filehandle” folderol. That problem is that the name does not fit the thing.

    • This is not a lexical filehandle:
      use vars qw($fh); undef $fh; open($fh, "> /tmp/data.$$") || die "can't open /tmp/data.$$: $!"); print $fh "I am so NOT a lexical filehandle.\n"; close($fh) || die "can't close /tmp/data.$$: $!";
    • This is a lexical filehandle:
      my $fh = *STDOUT; print $fh "I am SO TOO lexical filehandle.\n";

    I therefore submit that the thing you are talking about is not “lexical filehandles”, and to call them what they are not is to risk introduction of bugs in one’s mental model.

    I believe what you are referring to is not “lexical handles”, but instead autovivified anonymous handles, which may — or may not —happen to be stored in lexical variables.

      Ok, you're right, there is a warning here. I think though that the actual code closed another handle that was already closed from some other function. And if there was a warning, it would have been in a log file with lots of other output (though probably at the top of the file). And autodie may caught it also, but we're using 5.8.8, so autodie is not in core, but since we tend to trap and email errors, that would probably require eval, and if you think I have trouble getting people to use lexical handles (or AAH's which happen to be stored in lexical variables...), just watch me try to get anyone to use eval.

      So sure, there are lot's of ways to catch this bug, but I think the simplest way to catch it dead in it's tracks at 'compile' time would have been to use a lexical handle.

      OR, say the subroutine had 2 handles, and you closed one of them twice. The other would be closed when the sub exited, so you'd still have 'bad' code, but no bug.

        And if there was a warning, it would have been in a log file
        It's a frigging compile time warning! You mean, you're even skipping the "see whether it compiles" step before shipping?
        OR, say the subroutine had 2 handles, and you closed one of them twice. The other would be closed when the sub exited, so you'd still have 'bad' code, but no bug.
        So, your claim is that you ought to be using "lexical filehandles" because if you are in the habit of ignoring warnings (including compile time warnings), ignoring return values from close because there may be a situation where Perl does the thing you wanted it to do at the right time? Sounds like a pretty weak argument to me.
        If you don’t check return values, don’t blame Perl for errors in your code. Same with C.

        Also, if you close a file twice, then that is also an error. You should have checked the return value from close both times — and every time.

        Who closes files without checking to see whether it worked? That’s just begging for catastrophe.