http://www.perlmonks.org?node_id=575276


in reply to Re^2: Regex Or Die!
in thread Regex Or Die!

  • 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        

Replies are listed 'Best First'.
Re^4: Regex Or Die! (!unless)
by BrowserUk (Patriarch) on Sep 28, 2006 at 02:44 UTC

    I don't see why people have this trouble?

    Which is clearer?

    • Don't speak unless you're spoken to.
    • Don't speak if not you're spoken to.

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      • I could care less.
      • Irregardless.

      • Don't speak unless you're spoken too.
      • Don't speak if not you're spoken too.

      Well, the second one would be "Don't speak if you're not spoken to." I'm not advocating that people use improper Perl grammar. And, in proper English, they both seem pretty equally understandable. Many would prefer the former (especially if you drop the "you're", which would also make your second line clear and hence probably explains why you added it) simply because it is an oft-repeated phrase.

      Even clearer would be "Only speak when spoken to." In Perl, that would be something like:

      if( SpokenTo() ) { Speak(); }

      which doesn't quite have the same meaning as the English phrase, at least stand-alone. A closer match would be:

      sub Speak { return unless SpokenTo(); # ... }

      which I don't find as clear as

      sub Speak { return if ! SpokenTo(); # ... }

      As I said, it is subtle. Jumping into a different language isn't likely the best way to try to understand it.

      Certainly, I don't give much weight to a measurement of how likely a poor translation of a Perl construct into pidgin English is to sound like proper English. Programming constructs being similar to English can lower the learning curve in some ways, but if the people maintaining your code try to understand it by translating it word-for-word into English and then trying to understand that, then you've got worse problems than whether or not they use "unless". Only fairly trivial programming constructs make good sense when translating into English. That's why we use tools like charts and tables.

      The "if" of most programming languages is similar to the "if" of English, but not identical, so conclusions drawn from one don't perfectly apply to the other. But there is significantly more difference between the "unless"es of Perl and English. And your choice of examples illustrates this nicely. Let's translate your sentences into Perl code:

      DontSpeak() unless SpokenTo(); DontSpeak() if ! SpokenTo();

      You see, I've never seen a subroutine / method named something like "DontSpeak". Most programming languages don't work that way. So I'll take a small detour on the route to explaining why and showing what that has to do with "unless".

      The "if" of Perl is simply "if <present condition> then <do action (now)>" (though "present condition" could include "remembered state of past conditions"). The "unless" of English is most often used like "unless <potential future condition> don't <take action (future)>". But the "unless" of Perl is "unless <present condition> then <do action (now)>". And it doesn't really fit.

      Tell someone "Speak unless spoken to" and you'll probably be able see their mental cogs spinning as they try to figure out what you really meant.

      So, writing return unless SpokenTo(), then translating to English as "return unless spoken to" can easily beome, in your head, "don't return unless spoken to", because that is how "unless" is normally used in English.

      If you could write:

      unless( SpokenTo() ) dont { Speak(); }

      Then "unless" might be less of a problem. But that pretty fundamentally goes against the way Perl works (it might work in a declarative language like Prolog).

      The implied "not" in "unless" is subtle and there is also a customary second "not" that is subtle but missing from the Perl "unless". So when use "unless" in Perl code it is too easy to switch it to "if" in your head to avoid this dissonance or to add a "don't" to the action. And when you do this, it can be a long and frustrating process to find your back.

      - tye        

        Lets not don't go there, ok?
      use Acme::don't;
      don't { print "This won't be printed\n" }; # NO-OP
      How about the TheDamian writes another one ;-)
      use Acme::not_do; not_do { print "This won't be printed\n" }; # NO-OP

        What a wonderful idea! I can add to my huge tally of cpan modules by uploading Acme::Ifn't.

        Then we can all become PBP complient and never use unless again.

        die "'eh up lad! Summat's wrong." ifn't $It'sAlright;

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re^4: Regex Or Die! (!unless)
by shmem (Chancellor) on Oct 02, 2006 at 16:27 UTC
    The "not" that is implicit in "unless" is subtle enough that it can get "lost" when you are looking at code.

    I never had that problem. For me, the "not" cannot be lost, because without it it's not unless any more.

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

    No, it does not. That's an undue generalization. You may not advocate the banishment of a language construct as a general rule just because "quite a few" got "burned by it now". There's no count of those which never got burned by using 'unless', and which are quite comfortable using it as a statement modifier or a control construct in the sense perlsyn states:

    "if" executes the statement once if and only if the condition is true. "unless" is the opposite, it executes the statement unless the condition is true (i.e., if the condition is false).

    Subtleties in the english language regarding 'unless' are irrelevant and must not be stressed to daemonize it's use. After all, we're programming perl, not writing english statements.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

      I'm not banishing unless from Perl. But I have a collection of 'best practices' for writing highly maintainable code and not using unless is one of those.

      I never had that problem.

      And I said that my experience is that people won't "get it" if they haven't seen it. You don't have to try to learn from my experience of having done this and having seen other people do it several times. I didn't see the problem with unless until... I personally saw the problem with unless. (Well, I, like many of us, quickly saw that unless should be avoided in many situations; but I didn't initially see the problem with using it with very simple expressions.) The problem is subtle but the effect is maddening.

      No, it does not. That's an undue generalization.

      You dropped my smiley. Unwad your panties.

      Subtleties in the english language regarding 'unless' are irrelevant and must not be stressed to daemonize it's use. After all, we're programming perl, not writing english statements.

      I wasn't the one who brought the English language into the argument. The English language was used to justify the use of unless in Perl and I countered that argument. You can't banish the use of the English language in an argument about a programming language whose keywords are mostly English words. Besides, the problem with unless have much to do with the use of "unless" in English. Really. So you can tell me that I "must not" make my argument and thus demonstrate that you didn't understand my argument, but I will continue to try to express this difficult-to-express point whether you think my methods should be banned or not. I explained why it is relevent. You can declare that "it is irrelevent" but you'll have to back up such a declaration with more than "we aren't writing English statements". My argument never hinged on being confused that I thought we were writing English statements. My argument is about the word "unless" and subtle ways that it impacts comprehension (by English-speaking programmers) of code that uses that word.

      You must not use emotionally charged words like "daemonize" to mischaracterize my educating people about my experiences and attempting to explain my best practices.

      There's no count of those which never got burned by using 'unless', and which are quite comfortable using it

      I counted as one of those. Now I know better. The people I've seen burned by this were quite surprised when it happened. It took a while to even realize that there was a pattern to this. I don't think that there are two types of people in the world, those who understand unless and have no problem using it and those who have difficulty understanding it. It isn't even in the same ballpark as rocket surgery to understand that, in Perl, "unless" just means "if not".

      Anyway, in case you didn't notice, I got a chuckle out you responding to my use of "shouldn't" (in one sentence with a smiley attached) with declarations that I was trying to "banish" and then you using phrases like "you may not" and "must not". I forbid you take this so seriously, henceforth. q-:

      - tye        

        Duh! take two of them :-) :-)

        It might be due to me not being a native english speaker that I can't grasp what's the problem with 'unless'. So I looked up the term and... aha: 'unless' translates to 'if not' and 'except if'. Is that the root of the problem? Thinking 'unless' as 'except if' and dropping the 'except'?

        You must not use emotionally charged words like "daemonize" to mischaracterize my educating people about my experiences and attempting to explain my best practices.

        You're right, I must not use the word 'daemonize' when I mean 'deprecate'. But you may be wrong in thinking that your experiences serve other people to educate themselves, if you don't expose these experiences. I would highly appreciate some pointers to how people got hit by using 'unless', some 'real code' examples showing the whole process of tripping into the trap, getting hurt, licking wounds and healing towards using 'if not'. Surely those examples would give an insight into yet another weird corner of english thinking (you can't learn a language properly if you don't give in to think in that language). As I already stated, 'unless' for me is nothing but 'if not', and if the keyword in perl wasn't 'unless' but 'nif', it would be the same for me.

        I forbid you take this so seriously, henceforth. q-:

        I hardly do so ever, honest. But sometimes I indulge in grave sounding. *sigh* that discussion about 'to unless or not to unless' is going some time now, and I see neither an end nor any benefit coming from it.

        cheers,
        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}