Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Re: unless vs. bare block

by eyepopslikeamosquito (Archbishop)
on May 10, 2012 at 02:35 UTC ( [id://969727]=note: print w/replies, xml ) Need Help??


in reply to unless vs. bare block

unless (open (QTREES, $file)) { print STDERR "WARNING: get_qtrees() can't open $file for filer $fi +ler!\n"; return; };
As a matter of technique, I would write that as:
open my $QTREES, '<', $file or die "WARNING: get_qtrees() can't open ' +$file' for filer $filer!: $!\n";
First, note the addition of $! in the error message to tell you why the open failed.

Rather than returning with a warning, I have used die. Using die is usually preferable to printing a warning and continuing because if the open fails, there is usually little point in continuing (aka fail fast). Note that die throws an exception, so you can always catch that and not exit the program by wrapping the subroutine call in an eval block in the rare case that you want to continue after the open fails. As an alternative, you could first check via -f $file that the file exists and return with a warning if it does not exist and die only if it exists yet the open fails (update: see below and How portable are common $! error codes? for a race-condition-free alternative).

Using lexical file handles (i.e. my $QTREES above) is better style because:

  • They are local variables and so avoid the generally evil programming practice of keeping state in global variables.
  • They close themselves automatically when their lexical variable goes out of scope.
  • They avoid the confusion of barewords. IMHO, barewords are an unfortunate Perl feature and should be avoided (except when writing poetry).
Oh and be sure to start your programs with "use strict;" (just in case you are not doing that already).

Finally, note that I used the three-argument form of open. As for why the three-argument form of open is preferred, the old two-argument form of open is subject to various security exploits as described at Opening files securely in Perl.

Replies are listed 'Best First'.
Re^2: unless vs. bare block
by JavaFan (Canon) on May 10, 2012 at 05:48 UTC
    They are local variables and so avoid the generally evil programming practice of keeping state in global variables.
    Generally, avoid the evil practice of being too general. There are lots of cases where it doesn't matter at all, or where other trade offs can be made. Remember, people could have used lexical filehandle references since 5.000, but it wasn't until they autovivified that people actually started to use them on a larger scale. The world didn't burn up in flames in the mean time.
    They close themselves automatically when their lexical variable goes out of scope.
    Yeah, and so will "bare word" handles. You can even limit their scope by using local.
    They avoid the confusion of barewords. IMHO, barewords are an unfortunate Perl feature and should be avoided
    Wait. You're saying we should write &foo and "Module::Foo"->new instead of foo and Module::Foo::->new, because they're barewords, and unfortunate? You're sure you mean this?
    As for why the three-argument form of open is preferred, the old two-argument form of open is subject to various security exploits
    You've no idea where the second argument is coming from. For all we know, there's no problem. Don't scare people.

      Wait. You're saying we should write &foo and "Module::Foo"->new instead of foo and Module::Foo::->new, because they're barewords, and unfortunate? You're sure you mean this?
      No I didn't mean that. My characterization of all barewords as "unfortunate" was inaccurate and I thank you for pointing that out. To be more specific, I detest bareword strings, for example $x = Hello, except when playing golf and writing poetry (when I adore them). Thankfully, "use strict" disallows this particular use of barewords.

      I also dislike bareword file handles, endorsing the point of view expressed in Why the Modern Perl Book Avoids Bareword Filehandles.

      I prefer not to teach beginners about local and dynamic scope, at least not initially. OTOH, I do teach them about my and lexical scope in the very first lesson.

      For an example of the confusion that can be caused by bareword file handles see: Bareword "FILE" not allowed while "strict subs".

      For similar reasons, I feel that beginners should learn three argument open first: there are fewer gotchas and I don't want to overwhelm the beginning Perl user with many different ways to do the same thing. Rather, I prefer to teach them first what is usually the best way of doing something. I am aware that there are strong differences of opinion on this matter as indicated by this long P5P thread.

      Update:

      Don't scare people.
      Don't bully people. :) In his reply, the OP stated: "I haven't had any experience with the three-argument version" followed by "Thanks, I'll check it out". So the net result of my pointing out three-argument open was not to "scare" the OP but rather to improve his Perl knowledge and skill by encouraging him to read about three-argument open and to learn about the specific problems it solves in security-sensitive environments.

        I feel that beginners should learn three argument open first
        That's all fine and dandy that you feel that way, but that doesn't mean that if someone has a question about unless and block, you should treat their use of 2-arg open as if it contains security problem, just because it's 2-arg open.

        It looks to me that the OP has already past the point of "learn 2-arg open or 3-arg open first". He *knows* 2-arg open. From his post, we cannot deduce the state of his knowledge of 3-arg open (nor of a gazillion other Perl constructs).

        I prefer not to teach beginners about local and dynamic scope, at least not initially. OTOH, I do teach them about my and lexical scope in the very first lesson.
        I'd like to point out that the poster came here with a specific question, and didn't come here with "Heh, I don't know any Perl -- who is going to give me my first lesson".

        I also think that your use of terms like 'evil programming practice' when describing the efforts of someone who in your opinion still needs to get their first lesson isn't very constructive.

Re^2: unless vs. bare block
by chayashida (Acolyte) on May 10, 2012 at 19:03 UTC

    Thanks for your reply. Typically, I've been using the open or die syntax, but other admins have asked that the code continue even when a file is missing. Though I didn't post the surrounding code, it gracefully handles a null return value for the function.

    I haven't looked at the open command in a while, so I haven't had any experience with the three-argument version. I have been using the strict pragma and tainting input (out of habit, from when I first started learning Perl with HTML.

    I guess I haven't checked on it to see if there's a better way to do things now. Thanks, I'll check it out.

      I guess I haven't checked on it to see if there's a better way to do things now. Thanks, I'll check it out.

      Might as well check out the free Modern Perl book, a loose description of how experienced and effective Perl 5 programmers work....You can learn this too.

Re^2: unless vs. bare block
by Anonymous Monk on May 11, 2012 at 07:55 UTC

    As an alternative, you could first check via -f $file that the file exists and return with a warning if it does not exist and die only if it exists yet the open fails.

    But that is a race condition :) The file could become exist after you check with -f

    use Errno ;

    open ... or do { if( $!{ENOENT} ){ warn "Uh oh '$file': $!" ; return; } die "Uh oh, unexpected '$file': $!"; }

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (5)
As of 2024-04-19 02:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found