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

Conditional style (if, &&) query

by traveler (Parson)
on Oct 17, 2001 at 02:34 UTC ( #119274=perlquestion: print w/replies, xml ) Need Help??

traveler has asked for the wisdom of the Perl Monks concerning the following question:

If I have the logic "if expr is true call function b" (where expr is some expression), which of the following is preferred as the "most readable" style? Is there another good reason to choose one over the other?
expr && b(); # Short circuit operator b() if expr; # if clause if ( expr ){ # "traditional" if b(); }
What is the collective wisdom here?

--traveler

Replies are listed 'Best First'.
Re: Conditional style (if, &&) query
by George_Sherston (Vicar) on Oct 17, 2001 at 03:00 UTC
    I shouldn't like anyone to think I'm an expert, but my /50 is that it's nice to make the code read as much like English as possible. When I'm writing prose, I try to put the most important bit of the sentence in the most prominent place. So, say there are two buttons, a read and a blue one, and the red one is the ejector seat. If I'm writing to somebody who knows that one of the buttons will blow you out of your seat, I'd write
    if you press the red button, the ejector seat will launch
    But if I was writing to somebody who knew the red button was a bad idea but didn't know exactly what was bad about it, I might write
    the ejector seat will launch if you press the red button
    So my choice between B and C is
    if (the condition is more significant than what I do if the condition +is met) { use option C; } elsif (what I do if the condition is met is the interesting bit) { use option B; } else { probably use C on the same basis as [bjohnso]; }
    You notice that here I used C, since we all know what the different options are, and what's at issue is under what conditions we use them.

    George Sherston
      This comment is dead on, to extend the metaphor

      # check for a pilot action if ($red_button_pressed) { eject_seat(); } eject_seat() if $massive_failure; # check for exceptional behavior # sub returns true/false if the seat was ejected return $red_button_pressed && $massive_failure && 1; # fixed to put th +e && 1 on the end, in the original it was at the start
      The '1' is a perl-ism. Perl will return the value of the last true value in the boolean. To prevent people from taking shortcuts and expecting the sub to return false or the value of $red_button_pressed or $massive_failure we return one. Sooner or later it will no longer return what they think it does, and their code will melt (see also bitrot).

      -jackdied

        Your last bit of code confused me....
        return 1 && $a && $b;
        is identical to
        return $a && $b;
        is identical to
        return 1 && 1 && 1 && $a && $b
        So I don't follow your last paragraph...

        Update
        Were you perhaps thinking of:

        return $a && $b && 1;
        which will "coerce" all TRUE responses to be 1 instead of the value of $b?

        -Blake

      I have to admit that after 30 years of seeing Basic and Cobol programs structured
      if (cond) do something else do something else
      It may be prejudice that makes me prefer this structure. But I do think there is good reason too.

      George_Sherston's comment about the relative importance of the things_to_do is a good one and I take this into account by making free use of unless() {}, but there's another issue here, for which I will put on my tester's hat. It is important that we see clearly that it is a condition. From the perspective of a test designer, the presence of a condition is more important that what it does. And since I think better code gets written if everyone who comes into contact with it thinks about it from a tester's perspective, that makes "C" style a clear winner for me.

      BTW SInce I was using the "C" style a long time before C was invented, I find it hard to accept the phrase "traditional C style"!!

Re: Conditional style (if, &&) query
by dragonchild (Archbishop) on Oct 17, 2001 at 02:47 UTC
    Unless you're really being charged for whitespace, don't use choice A. Of course, if you're doing a whole bunch of these and they're in a regular pattern within a while, for example, try it out and see.

    I personally use B, simply because it's succinct and easy to read, but doesn't bring in lesser-known quantities of the application.

    If you're going to be working with less-skilled people, use C every time. The idea is to work with them, not show them how much you know (though demonstrating nicely new techniques is always reccomended ... especially for those times when you end up being charged for whitespace. *grins*)

    ------
    We are the carpenters and bricklayers of the Information Age.

    Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

Re: Conditional style (if, &&) query
by hopes (Friar) on Oct 17, 2001 at 02:58 UTC
    I think as dragonchild
    Option B is "more readable" for me, but there are situations in which I use option C.
    I use option C if expr is long or complicated.
    I use option C also if there is one possibility to need one else now or later.
    I think I am a little fussy, cause I don't like
    unless (a()){ b(); }
    I prefer
    b() unless a();
    because I find that really more readable.
    Err, I think
    not use 'option_A' unless golf() or advanced_programmer();
    :-)
    Hopes
Re: Conditional style (if, &&) query
by demerphq (Chancellor) on Oct 17, 2001 at 03:14 UTC
    Well to me the first one is 'cute' and I wouldnt use it except in a few situations (such as one line closures and the like) where it is in some way isolated and obvious. (obfus as well :) There is a second reason that I sometimes end up using this form, and that would be when i need to an 'if' to the left side of a modifier, like for or while. Its not good coding practice in general but it still can be readable in some situations:
    $_ eq $target && last foreach @value;

    The second I like especially if the 'function' is a flow control keyword like next,last or redo or return. Also where there is no else and the if is expected to most often succeed, or on the contrary where I want to stylistically emphasize something. Like

    die "Whoa! Bad Majo" if $bad_mojo;
    The third I would do if I thought there was the slightest possibility I would need to have an else or multiple statements. Having said that, generally if there is no need for an else block my reasoning for using the second form usually already applies.

    Oh yeah, if IIRC this type of stuff is covered in perlstyle quite nicely I thought.

    HTH

    Yves
    --
    You are not ready to use symrefs unless you already know why they are bad. -- tadmc (CLPM)

Re: Conditional style (if, &&) query
by Hutta (Scribe) on Oct 17, 2001 at 06:01 UTC
    I tend to only use the first option in the following situation

    $debug && print "Some debugging output.\n";
    Works for me because I see the "$debug" and mentally disregard that line from the regular functionality of the code.

    print "Some debugging output.\n" if $debug;
    ...doesn't stand out as much as debugging because I tend to scan code down the left side.

    if ($debug) { print "Some debugging output.\n"; }
    ...that way just eats up way too much room when there's a lot of debugging output.

    And of course these are all for smaller scripts where a more complete debugging output solution isn't needed.

      Good point you make here but let me mention one thing in the context of debugging in this way. If you make $debug a constant then you don't get any runtime speed penalty for these kind of tests. They are optimised away at compile time:

      use constant DEBUG => 1; DEBUG && print "printing debug info...\n"; print "printing other info ...\n";

      Of course, you no longer have the option of specifiying your debug level on the command line. Sean M. Burke has a nice article about constants in perl (including this usage) here at The Perl Journal. We also had some discussion about that topic here at PM, e.g. in inlined DEBUG constant versus $DEBUG.

      -- Hofmator

Re: Conditional style (if, &&) query
by Toodles (Monk) on Oct 17, 2001 at 07:28 UTC
    In general, I personally find C to be the most readable and easy for everyone to grasp. When I come across A (expr && b()), I have to do a quick doublecheck in my head about whether b(); gets run if expr is true or false. Meat time is expensive. Also, shouldn't we use the 'and' and 'or' operators instead of && and ||? When I come across these, I also have to take a moment and evaluate if whether you meant a logical AND or conditional AND or bitwise AND. Seeing the word 'and' instead whould make it easier for people to read and mean the same thing.

    Option B is clean, but doesn't translate to English as clean as I would prefer. In general, I prefer the 'if' and 'unless' clauses after the statement only under rare circumstances. Because the statement is in front of the condition, the statement appears more important to the human mind. So, only use it when it is very likely that the code block WILL be run. For example:

    print "Welcome, Mr. President." if from_whitehouse.gov(); instead of launch_nukes() if found_file("/bin/laden");
    This same idea goes for unless and or: Remember, 'unless' is much more readable to most new coders than 'if(!$a)'
    run_program() unless user_is_idiot(); open_file() or die;
    Never put the conditional after the code block if the code block is more than one statement....
    print "Welcome, Mr. President" { launch_nukes(); send_ground_troops(); enjoy_a_milkbone_in_a_commie_free_world(); } unless password_failed(); #This can be bad. You have to read so many lines, get #confused, then go back and figure out where the block #began. Pain in the patukis.
    Although it is a subset of answer C, my personal prefered method of seeing this is:
    if (expr) {b()}
    Since the actual expression and the block to be executed are small, put them on one line; Easy to read, translates cleanly to mental English, and easy to add 'else' and other statements in the future. It also doesn't hog 3 lines with mostly whitespace.

    Again, keep in mind that this is all a matter of personal preference, and no one is right and wrong. Make your own code and goes with what makes the most sense to use. From my understanding of corporate coding jobs, their guidelines will take all that guess work out for you. :)

    Toodles

      I don't think its even valid to do a simple "BLOCK unless". However "do BLOCK unless" is valid.
      do { blah; blah; blah; } unless 0;

      -Blake

Re: Conditional style (if, &&) query
by bjohnso (Sexton) on Oct 17, 2001 at 02:46 UTC
    I've been accused of writing VERY C looking perl code. But once you get in to a programming style, I've noticed it's pretty tough to change.

    I personally find it a LOT easier reading the traditional C style if statements. They just make code look SO much cleaner and easier to follow.

    My other gripe is comments. The more comments the better. I personally hate coming back to my code after 6 months and having to remember what assumptions I made when I wrote it.

    So I guess my vote is for:
    if (expr) { b(); }
      The more comments the better?

      I strongly think not, and that is a gripe of mine.

      Don't get me wrong. I use comments, and on the whole I have quite a few of them. But to me comments are something which has to be done right or else it is worse than useless, and I would prefer to see completely uncommented code to overly verbosely commented code.

      For a thread that outlines my personal commenting style and the reasons for it at some length, I would suggest reading Re (tilly) 2 (disagree): Another commenting question,. (Note that behind the scenes we traded a series of /msgs that were more friendly than the discussion there.) After reading that, if you think that I really need more comments than I use, or that my points about how comments can be a problem are off-target, please give me feedback.

      I beg to disagree with the statement "The more comments the better.".
      Personally I state and restate:
      "Any programmer of the language in question is supposed to understand what the code does."
      "OTOH, you must document why the code does it."

      This is especially important when the code makes assumption about the behaviour of external libraries or when the code depends on (more or less documented) side effects.

      f--k the world!!!!
      /dev/world has reached maximal mount count, check forced.

Re: Conditional style (if, &&) query
by tommyw (Hermit) on Oct 17, 2001 at 02:50 UTC

    It's your choice: that's the beauty of Perl.

    That said, I don't think I've ever seen the first version in use (although it's common with or aka ||). Of the other two, it depends on the complexity of the expression, the function call, and which you think is "more important", and you'd therefore like to read first in your code.

Re: Conditional style (if, &&) query
by chipmunk (Parson) on Oct 17, 2001 at 05:57 UTC
    I've used each of the above, at different times. (Actually, I use expr and b(); rather than &&.) Which one I prefer at any given time depends on the actual expr and b(), the surrounding code, and the intended audience.

    expr and b(); is good when the expr is more significant than the call to b(), or when you're emulating a switch statement.

    b() if expr; is good when the call to b() is more significant than the expr, such as b() if $DEBUG;.

    if ( expr ) { b(); } is good because it has the clearest structure, especially for people familiar with other languages.

Re: Conditional style (if, &&) query
by DamnDirtyApe (Curate) on Oct 17, 2001 at 05:55 UTC
    Personally, I would avoid the first choice whenever possible. What about when your code looks like this:
    --$option > ($i - 1) && $a = shift;
    Not the most complex logic in the world, but IMHO you've already lost a lot of readability. As for the other two, I like the b() if expr; when there's only one expression to do, and the traditional if block any other time. Also, I personally find Stroustoup-style indenting/bracketing the most readable, ie.
    if ( expr ) { b() ; }
    I'm aware that this bracketing isn't the convention in Perl (if anything is a convention; TMTOWTDI), but it's my personal preference. What do others think?
Re: Conditional style (if, &&) query
by petdance (Parson) on Oct 17, 2001 at 08:04 UTC
    Everything depends entirely on the specific context. That's the beauty of TMTOWTDI.

    I usually try to sound as English-like as possible, and keep in mind what I'm trying to emphasize: the test or the action? There's no One Right Way, even within the same program or even the same block of code. Go with what makes the most sense for the specific piece of code.

    Also, consider the surrounding code. Something as simple as conditionally printing a phone number can depend greatly on why it's doing it. The "standard" way might be:

    if ( $obj->show_phone ) { $obj->print_phone_number; }
    Here's some code where that probably is best:
    # Validate the phone according to basic U.S. rules if ( $phone =~ s/^(1-)?(\d\d\d-?\d\d\d-?\d\d\d\d)$/ ) { $phone = $2; $phone =~ s/-//g; # Strip dashes $obj->set_phone( $2 ); } else { $obj->error( "Invalid phone number" ); } if ( $obj->show_phone ) { $obj->print_phone_number; }
    We check the phone number, and make sure it's a valid format, and then when we're done, we might print the phone number. Whether we print or not is incidental to the rest of the block.

    But consider this instance where the context is entirely different.

    $obj->print_name; $obj->print_address; $obj->print_phone_number if $self->showphone; $obj->print_email_address;

    Here, it's more appropriate to show that we're printing a bunch of information, and the phone number is optional. Writing it the "old way", with the phone number block taking three lines, would break up the visual flow, like so:

    $obj->print_name; $obj->print_address; if ( $obj->show_phone ) { $self->print_phone_number; } $obj->print_email_address;
    Blech.

    I think rule two of Perl, after TMTOWTDI, should be "It all depends."

    xoxo,
    Andy
    --
    <megaphone> Throw down the gun and tiara and come out of the float! </megaphone>

Re: Conditional style (if, &&) query
by rrwo (Friar) on Oct 17, 2001 at 14:19 UTC

    I would say what is most readable has to do with the "flow of thought" as to what you're doing. Perl is an "expressive" language in that you can say the same thing many ways.

    My rule of thumb: It's readable if a person with a decent knowledge of Perl who is going bleary eyed debugging the program for the last 12 hours can still make sense of the code and not mis-read it, and if the code is clear enough that it requires minimal comments.

    I usually avoid short-circuit expressions because they are often easily misread.

Re: Conditional style (if, &&) query
by Maclir (Curate) on Oct 17, 2001 at 19:22 UTC

    I would tend to go with option c (the traditional if structure) for the following reasons:

    1. The vast majority of programmers - even non-perl programmers can (or should be able to) understand your intent.
    2. If at some future time, you need to add some additional processing, you can slip another statement in without restructuring the code:
      if ( expr) { a(); # why didn't they think of this before? b(); }
    3. (Updated)You can easily slip an else clause in there when someone realises that is required as well.
Re: Conditional style (if, &&) query
by willdooUK (Beadle) on Oct 17, 2001 at 14:32 UTC
    I think the most important thing is consistency. You can use whichever style is most appropriate, as long as you're consistent throughout your code.

    Then when someone else is looking through your code they can get used to your style no matter how alien it is to them.

    It's like accents - you can very quickly adjust to someones accent when they speak, but if their accent were to change every 10 seconds, you'd get lost.


    Wow. I just read that back and I think I need more coffee... :)

    willdooUK
    --------------
    "Home is a castle you built in my mind; I'm home anywhere, anytime."
    Donny Hathaway
Re: Conditional style (if, &&) query
by Biker (Priest) on Oct 17, 2001 at 15:40 UTC

    I frequently tend to use 'A', because I like it.
    TIMTOWTDI !

    f--k the world!!!!
    /dev/world has reached maximal mount count, check forced.

(jeffa) Re: Conditional style (if, &&) query
by jeffa (Bishop) on Oct 31, 2001 at 04:09 UTC
    Way late on the post again, jeffa comes in with TIMTOWTDI (and places vote on style 'B' as long as more choices won't be added).

    Consider this nasty block:

    my $arg = shift; if ($arg eq 'one') { do_stuff() } elsif ($arg eq 'two') { do_other_stuff() } elsif ($arg eq 'three') { do_even_more_other_stuff() } else { do_yet_even_more_other_stuff() }
    To this, much nicer block:
    my $arg = shift || 'DEFAULT'; my %lookup = ( one => \&do_stuff, two => \&do_other_stuff, three => \&do_even_more_other_stuff, DEFAULT => \&do_yet_even_more_other_stuff, ); $lookup{$arg}->();
    Who even needs if? :D (um, sarcasm)

    jeffa

Re: Conditional style (if, &&) query
by barndoor (Pilgrim) on Oct 17, 2001 at 19:15 UTC
    I personally go for B or C depending on what the condition is.
    Some conditions read better using B and some using C.
    I've never bothered using A.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://119274]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (3)
As of 2020-10-30 02:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My favourite web site is:












    Results (277 votes). Check out past polls.

    Notices?