Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

Regex Or Die!

by pileofrogs (Priest)
on Sep 27, 2006 at 00:01 UTC ( #575044=perlquestion: print w/replies, xml ) Need Help??
pileofrogs has asked for the wisdom of the Perl Monks concerning the following question:

This is a best practices question.

I'm not supposed to use unless. So what's the best way to do this:

while (<>) { unless (/^(foo|bar)/) { die "I can't handle this crap! '$_'\n"; } my $dumb_example = $1; .... .... }

I think:

if ( $_ !~ /^(foo|bar)/ ) { die "What the heck?!\n"; }
looks like poop.

Replies are listed 'Best First'.
Re: Regex Or Die!
by liverpole (Monsignor) on Sep 27, 2006 at 00:11 UTC
    Hi pileofrogs,

    How about ...?

    /^(foo|bar)/ or die "What the heck?\n";
    That's fairly succinct, isn't it?

Re: Regex Or Die!
by polettix (Vicar) on Sep 27, 2006 at 00:19 UTC
    I'm not supposed to use unless.
    I'd say you can use it whenever you want :) Even if I mildly agree with PBP for this issue, I loved Perl also because of unless (even if I use it only as statement modifier, another thing that PBP discourages). Continuing on PBP, why don't you simply negate the if?
    if (! /^(foo|bar)/) { die "in pain"; }
    Or use the statement modifier (suitable for this one-instruction case)?
    die "whatever" unless /^(foo|bar)/;

    perl -ple'$_=reverse' <<<ti.xittelop@oivalf

    Don't fool yourself.
      die "whatever" unless /^(foo|bar)/;

      I like that it's hard to miss a die with this method. It's the first word on the line, the die jumps out and screams "This condition is important!"

      Which also means that this style can get distracting if you're doing a lot of sanity checks inline. So, that's a good reason to encapsulate your sanity checks in subroutines.

      $user_number = &validate_user_number($input)

      is cleaner than

      die "Numbers only please." unless ($input =~ /[0-9]+/); $user_number = $input;

      Plus, with a subroutine, you can add more checks without making the usage of that sub any harder to understand.

      I agree with frodo72 in favour of unless, using !~ just because you want to avoid unless, is a most hidious practice.

      !~ is even far more obscure than unless, and you should most definitely not start using it for frivolous reasons. Is there something in PBP about it? If it isn't, I'd add a Best Practices rule of my own:

      Don't use !~
Re: Regex Or Die!
by ChrisCantrall (Sexton) on Sep 27, 2006 at 00:18 UTC

    Flip it around.

    if ( /^(foo|bar)/ ) { my $useful_code; } else { die "What the heck?!\n"; }
      I downvoted this, it's a common but poor way of programming. You should deal with the errors up front, as close as possible to the test, then let your 'normal' case proceed:
      if ( ! /^(foo|bar)/ ) { die "What the heck?!\n"; } my $useful_code; ...
Re: Regex Or Die!
by friedo (Prior) on Sep 27, 2006 at 02:56 UTC
    I'm not supposed to use unless.

    With all due respect to TheDamian, that's a load of crap. There's nothing wrong with unless, and the one problem with PBP is that Damian has let a few of his personal opinions slip in there amongst the vast majority of stuff that's just common sense.

    There's nothing wrong with avoiding unless if it offends your personal sense of style or gives you the willies. But don't jump through hoops just because something is written in PBP.

      There's nothing wrong with unless
      Sure there is. And I spent a page and a half in PBP explaining precisely what was wrong with it. In summary:
      • unless is fine for simple conditionals.
      • But it makes compound conditionals harder to understand (because, in general, people are relatively poor at applying de Morgan's law correctly).
      • In particular it makes conditionals that include partial negations very much harder to comprehend.
      • Even conditionals that start out simple, don't always stay simple; extra subconditions are often identified and handled during maintenance or extension of code

      The result is that (as PBP points out):

      unless and until are inherently harder to maintain. In particular, whenever a negative control statement is extended to include a negative operator, it will have to be re-cast as a positive control, which requires you to change both the keyword and the conditional....Not only is that extra effort, it's error-prone effort. Reworking conditionals in that way is an excellent opportunity to introduce new and subtle bugs into your program....This kind of mistake is unfortunately common, but fortunately very easy to avoid. If you never use an unless or until, then you'll never have to rewrite it as an if or while. Moreover, if your control statements are always "positive", your code will generally be more comprehensible to all readers, regardless of the complexity of its logical expressions...

      I don't proscribe unless because it's never appropriate. I recommend against it because it's often eventually inappropriate. Because, in all but the simplest cases, it ultimately makes comprehension and maintenenance harder and provides an opportunity for bugs to creep in as code is extended.

      Now, you may not agree with that arguments or my conclusion, and that's fine. But it's not accurate to assert that I'm merely letting:

      personal opinions slip in there

      or to imply that I did not have carefully thought-out reasons for my advice.

      Indeed, it's easy to demonstrate that the deprecation of unless was not just personal opinion. If you examine the source code of my modules that predate PBP, you will find many instances of unless. So, until I sat down to examine and codify Perl best practice my personal opinion was apparently that unless was fine. It was only after I reviewed the arguments for and against, discussed the issue (vigorously and at length ;-) with my many reviewers, examined the mistakes that I and many of my clients had made using unless, and thought about the long-term implications of deploying the construct, that I concluded it should not be used.

      Of course, that still is a personal opinion—just like everything else that everyone else ever says—but it a personal opinion based on reasoned argument and extensive professional and pedagogical experience.

      On the other hand, your subsequent point that blind acceptance of my advice is contrary to the spirit of the book is perfectly valid. I spent the first chapter asking people to think about these issues, to evaluate my arguments, and then to decide for themselves. However, not everyone has the time, the will, or the capacity to do that, which is why I tried to make the advice as careful and conservative as possible, so that those who do adopt it wholesale will be unharmed by the suggestions I made.

      By the way, to answer the original poster's original question, my suggestion would be:

      while (my $line = <>) { croak "I can't handle this crap! '$line'\n" if $line !~ m{\A (foo|bar) }xms; my $dumb_example = $1; .... .... }
        • unless is fine for simple conditionals

        I disagree, but the reason is rather subtle and my experience shows that most people just won't buy the explanation until they've personally been burned by it. I've seen quite a few people get burned by it by now, and I'm quite convinced.

        The "not" that is implicit in "unless" is subtle enough that it can get "lost" when you are looking at code. I've seen several people (including myself) stare at code over and over trying to figure out what is going on because they mentally misplaced the too-subtle "not". The code does exactly the opposite of what they expect and they can look at it and break it down over and over and still not recover the missing "not".

        Just a couple of days ago, someone asked one of those head-slap questions in the chatter box to which I responded "because 48 *is* less than 50". They had looked at this very simple code (one simple statement with one simple comparison) over and over and couldn't figure out what was wrong. In this case they hadn't even used "unless", but had started to use "unless" and then changed their mind and used "if" instead. The distinction between the two is so subtle that even after repeated attempts, they failed to notice their mistake.

        This shows that not only shouldn't you use "unless" even for simple conditionals, but shouldn't even consider using "unless". (:

        - tye        

      I, personally, would rather avoid using unless. It's a bit of a mind-twist as I grew up with C. Essentially it is
      if ( ! condition )
      and, for me, it is often simpler to explicitly present the not.

      In fact the very posting of this question obviates the fact that unless isn't straightforward to understand for some users.

      Although I accept there are rare occasions when unless might make sense it is a keyword that is best avoided when aiming for maximal maintainability.

        Oh, I agree that some people find it unclear, and that's fine. Personally, I prefer unless to if-not.

        I was just objecting to the dogmatic interpretation of PBP, which seems to be antithetical to the book's point.

Re: Regex Or Die!
by ikegami (Pope) on Sep 27, 2006 at 00:19 UTC
    There's also
    if ( !/^(foo|bar)/ ) { die "What the heck?!\n"; }

    ( doh! Frodo beat me by mere seconds. If only he was as quick at getting to Mount Doom. )

Re: Regex Or Die!
by mreece (Friar) on Sep 27, 2006 at 00:43 UTC
    i say, just use unless. and cuddle your elses. the rest of PBP is gospel. :)
Re: Regex Or Die!
by perrin (Chancellor) on Sep 27, 2006 at 02:40 UTC
    The "poop" looks like a nice clear way to write it to me, except I'd probably use something like $line instead of $_.
Re: Regex Or Die!
by chromatic (Archbishop) on Sep 27, 2006 at 23:22 UTC
    if ( $_ !~ /^(foo|bar)/ ) { die "What the heck?!\n"; }

    I don't see what's so difficult to read about that. It only has several more punctuation symbols (hey, all one character wide visually, so they're harder to pick out than a six-character English keyword!) than the equivalent:

    die "What the heck?!\n" unless /^(foo|bar)/;

    I mean, you're basically insulting a natural bodily function here.

Re: Regex Or Die!
by Arunbear (Parson) on Sep 28, 2006 at 23:00 UTC
    unless you object to using a module, how about this:
    use Carp::Assert; while (<>) { assert( /^(foo|bar)/ ); my $dumb_example = $1; .... .... }
Re: Regex Or Die!
by xorl (Deacon) on Oct 02, 2006 at 15:21 UTC
    I'm not supposed to use unless.
    You're not supposed to use unless?? Let me guess, this is homework right?

    Any number of the answers you've gotten already will work.

    Personally if I'm not going to use unless, I prefer

    if (whatever_the_test_for_the_condidtion_is) { die("A complete and total disaster happened"); } # proceed with your code here
    Note I don't include the useful code inside of an else since that's an extra bracket you've got to keep track of and another layer of indentation which could get screwed up. Of course that's just me, others will prefer to have this extra stuff. Unless it is unless use whatever (assuming there aren't other silly restrictions).
Re: Regex Or Die!
by Anonymous Monk on Oct 04, 2006 at 13:55 UTC
    while (<>) { goto survived_another_round if /^(foo|bar)/; die "I can't handle this crap! '$_'\n"; survived_another_round: my $dumb_example = $1; ... }
Re: Regex Or Die!
by Anonymous Monk on Oct 02, 2006 at 12:20 UTC
    die if ! /^(foo|bar)/;

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://575044]
Approved by polettix
Front-paged by kwaping
and monks are getting baked in the sun...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (7)
As of 2017-01-20 23:28 GMT
Find Nodes?
    Voting Booth?
    Do you watch meteor showers?

    Results (180 votes). Check out past polls.