Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

A matter of style: how to perform a simple action based on a simple condition?

by muba (Priest)
on Sep 26, 2010 at 03:26 UTC ( [id://862038]=perlquestion: print w/replies, xml ) Need Help??

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

After having written a couple of programs in a not very well known programming language that usually employs a style of some_variable && some_subroutine() to run a subroutine only when some_variable holds a true value, I find myself doing the same in Perl often lately.

But then I realised that Perl also has the some_subroutine if $some_variable syntax, and of course the filled with line noise version, if ($some_variable) { some_subroutine }.

All of these have pros and cons, I think.

One
$var && subroutine: this one follows the way you formulate logic propositions: it is immediately apparent that subroutine() is only called when $var is true. However, readability might suffer a bit as it appears a bit "cryptic", especially compared to snippet two

Two
subroutine if $var: flows like natural language, woohoo! However, the fact that subroutine() is called when $var is true is only revealed at the end of the statement.

Three
if ($var) { subroutine }: has the advantage of snippet one (condition first, consequence next), but is filled with line noise. ( ) { } just for a really simple 'IF this THEN that' kind of construction.

Obviously, the TIMTOWTDI principle applies here but what I've come to ask is which of these styles do you prefer, and why? Just out of curiousity.

Replies are listed 'Best First'.
Re: A matter of style: how to perform a simple action based on a simple condition?
by GrandFather (Saint) on Sep 26, 2010 at 04:02 UTC

    (almost) Never One - it requires too much brain work to figure out what's going on when scanning through code.

    Never three - all that is seen is the condition; the action gets lost.

    Most often Two. The action is obvious and generally the most important thing. If the condition is really important I'd:

    if ($var) { sub (); }

    to make the condition obvious and the action easy to find.

    As a general rule stuff at the end of a long or complicated line will tend to be ignored. If it's important it be seen don't stick it on the end of a line.

    True laziness is hard work
Re: A matter of style: how to perform a simple action based on a simple condition?
by Tux (Canon) on Sep 26, 2010 at 10:32 UTC

    As the others already mentioned, it is about personal taste. But maybe more: it is how the people that maintain the code prefer to read it. If you are the only one, do what you prefer best. If it is a team, please follow the guidelines of the team and be consistent in that.

    I never use the func () if $expr; syntax, because that is - for my mind - exactly the wrong way around.

    I also never use && and || to do so, because it then doesn't differ enough with expressions:

    $expr1 && $expr2 and action (); $expr1 || $expr2 or action ();

    And if it gets more complicated, go to Three. Whenever in doubt, use parens:

    if ($expr1 && $expr2 or $expr3 && ($expr4 || $expr5)) { action1 (); action2 (); }

    So, I never ever use Two (and in our team when we see code like that it is immediately rewritten to One or Three).

    Side note: I have one colleague that just cannot cope in his mind with unless. Not all people think alike, certainly when mixed languages (peoples languages, not computer languages) are involved.

    Three has the ((very) big) advantage of being able to insert new code when the condition meets without changing the rest of the code.


    Enjoy, Have FUN! H.Merijn
Re: A matter of style: how to perform a simple action based on a simple condition?
by eyepopslikeamosquito (Archbishop) on Sep 26, 2010 at 04:21 UTC

    This is discussed in Chapter 6, "Control Structures" of Perl Best Practices. See the "Use block if, not postfix if" and "Reserve postfix if for flow-of-control statements" items in that chapter. Conway argues that postfix if does not scale as well as block if, and is harder to comprehend (except in simple cases).

    As for using && and || for flow of control, you should always prefer the low precedence and and or operators. A common example of preferring or to || is:

    open(my $fh, '<', $file) or die "error opening '$file': $!";
    Reserve && and || for logical expressions, not flow of control, for example:
    if ($x > 5 && $y < 10) ...
    This is discussed in Chapter 4, "Values and Expressions" of PBP in the "Don't mix high- and low-precedence booleans" item.

Re: A matter of style: how to perform a simple action based on a simple condition?
by JavaFan (Canon) on Sep 26, 2010 at 10:45 UTC
    I'd say, understand what all three do (because no matter what, you'll encounter all three styles if you're going to read other peoples code), and do whatever you find more natural at the time of writing.

    I've used all three, probably option two the most. Option three is somewhat slower, as it creates a scope (and creating and tearing down a scope takes some time). But this should only matter in a tight loop.

Re: A matter of style: how to perform a simple action based on a simple condition?
by TomDLux (Vicar) on Sep 26, 2010 at 04:25 UTC

    Using the and && is too much about the implementation. Use it in shell programs where you're grateful for a concise alternative to if{} blocks.

    Use the if{} if you are going to do several things within the block, or if you are also going to use the else clause.

    If what is being done is significant, the suffix if focuses on what is being done, rather than why. If the what is minor, the reason is still notable, while far more compact.

    What I mean is, if you are processing a config file, you want to skip empty lines, ignoring space characters, and ignoring comment lines.

    LINE: while ( my $line = <config> ) { chomp $line; next LINE unless $line =~ m{\S}; next LINE if $line =~ m{\a\s*\#}xms; # process line }

    As Occam said: Entia non sunt multiplicanda praeter necessitatem.

Re: A matter of style: how to perform a simple action based on a simple condition?
by dasgar (Priest) on Sep 26, 2010 at 04:43 UTC

    For me personally, I prefer the third syntax primarily for two reasons. First, it's what I'm more familiar with seeing and using.

    Secondly, I personally find the 'condition' then 'action' syntax more 'natural' to how I think about things as opposed to 'action' then 'condition'. In my mind, if a condition has to be met before an action is to take place, it doesn't make sense to list the action before the condition.

    I'm not advocating that this is 'best' method, but it's what feels more natural for me and is the easiest for me to follow when quickly scanning code.

      I agree that the second approach is the one that usually seems best, but I do have an additional restriction as to when to not use this approach: there can be no line breaks. If anything about this makes the the code too long to fit on a single line then I switch to the third approach.

      - doug

Re: A matter of style: how to perform a simple action based on a simple condition?
by BrowserUk (Patriarch) on Sep 26, 2010 at 22:38 UTC

    I find all of the justifictions in support of option 3 over option 2 utterly bogus.

    • The condition is more important than the action.

      Rubbish. The program doesn't work if the action isn't taken when it should be; nor if it is, when it should not.

    • People "won't notice the condition stuck on the end".

      Then they should not be programmers.

      In my experience, the reverse is far more frequent. People read the condition, and assume the action conditional upon it.

      There is no excuse for not reading the code properly. Like reading "To be or not to be...", but never reading on.

    • That it is "quicker to modify" if the action needs to expand.

      If the time required to revert a post-fix condition, to prefix with block is a significant part of the time taken to make the change, then I suggest insufficient thought has been applied to considering the change in the first place.

    • (English) speech patterns favour option 3.

      "Beat that if you can"; "Try that if you dare"; "Help yourself if you're hungry"; "Get in if you're coming".

    Justifictions all.

    Personally, I use option 1 when I have a simple condition/action pair with a postfix for or while in performance critical loops.

    Otherwise I use option 2.

    I see no advantage in option 3, beyond the need for a else. And I'm, as likely as not to code that as:

    condition and action1() or action2();

    But then, I've been used to postfix conditions and loops--including nested postfixes, which I was pleased to see made it into Perl6--since Basic Plus days, 25+ years ago.

    I wouldn't mandate them upon anyone, but I abhor them being demonised.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: A matter of style: how to perform a simple action based on a simple condition?
by Your Mother (Archbishop) on Sep 26, 2010 at 17:36 UTC

    What GrandFather said. I use Perl because it's not all those other construct limited languages that force you to reason like a 50s robot. The length and complexity of the code will change what is easiest to read but in general, this is what I'd say for all simple clauses, so this is what I understand the most easily–

    Go shopping later if you can. Take out the trash if it's full. Open the windows if it's too hot.

    The inverted statements are sensible of course but they begin to put a lot of weight on the conditional and make you think harder about the potential interpretation(s) of the statement. I also think postfix unless is much easier to follow than the block version.

    Go dancing unless you're tired.

    Though being Perl, I don't mind seeing the other constructs and don't blame anyone for preferring them. :)

      The condition heavily weighs it's position quite often. Compare with:

      If you need milk, go and buy some If the trash is full take it out If it is too hot, open the window

      In the first, the condition is now more important than how to meet it. (At least in my perception. In the latter two, I just switched and personally think it is clearer that way. Note that English is not my native tongue and that I am very well aware that not all people think alike. That is why I love perl5: it is very easy to write it as it best fits your mind while still not too hard to read when others wrote it the way they think is best.

      In the third example it is also important to realize the number of options on either side of the and/or/if/unless.

      If it is too hot, turn down the heating If it is too hot, open the window If it is too hot, turn on the air conditioning If it is too hot, go out for some fresh air

      Of course this also goes the other way: there may be a number of reasons to open the window (other than to throw out ... from the 13th floor).


      Enjoy, Have FUN! H.Merijn

        You sort of describe what I see as the main reason to prefer the postfix. “If it is too hot,” just for one example has a dozen, if not nearly infinite, possible remedies, as you note. Drink cold water, take sleeping pills to remain unconscious through it, buy a swamp cooler, shoot yourself to end your misery, fill the oceans with iron powder… The action matters far more than the condition. The condition initiates extra mental effort when it comes first. It creates a theoretical, if not actual, decision tree. You can race ahead to what you think the action should/will be.

        It's also, as noted by many, noisier and generally multiline, to do if blocks which also increases apprehension impedance. Again, in my view. It's Perl, we can do what we wish. I think most of the above replies in favor of the block are more about justifying one's comfort zone, a valid thing to care about, versus actually considering what might be easier to write and read in the simple case (I would never advocate postfix for a logic tree or situations with several actions and conditions in the statement).

        It's funny you mentioned native languages because the same thing occurred to me. I am curious if the SVO order of English—or even lazy idiomatic regionalisms of which I'm the victim—have any bearing in the perception of which is “easier.”

Re: A matter of style: how to perform a simple action based on a simple condition?
by Anonymous Monk on Sep 26, 2010 at 03:39 UTC
    To me its all the same, although i prefer and/or to && and ||
    $blah and blah(); $blah or blah();
Re: A matter of style: how to perform a simple action based on a simple condition?
by halfcountplus (Hermit) on Sep 26, 2010 at 17:02 UTC

    I don't recall ever using the first one:

    $var && sub();

    But I don't have any problems with it -- it's clear enough.

    Generally I prefer to use the second one wherever possible, tho from habit I always put parentheses around the condition:

    sub() if ($var);

    The only time I use the third one all on one line is for stuff like:

    foreach (@ray1) { push @ray2,$_ if ($_<0) }

    Or if there is an else beginning the next line.

    I don't understand how having the condition to the right of the action could confuse someone -- I don't think about a line's complete meaning until I've read the whole thing anyway, and it's completely commonplace and normative in natural languages to use subordinate clauses which qualify the previous phrase (ie, your mind should not have difficulty with this). However, I'll admit I'd just as soon do this:

    if ($var) sub();

    Which is normative in most other languages that I use, such as C, but perl does not allow it.

    I presume Larry Wall, linguist and C programmer, had some real reason for this "action before condition" structure in perl and I would doubt it has to do with interpreter internals, so perhaps he saw it as adding something meaningful. Which it does: you can tell something about the nature of this statement because of it's limitations:

    action if condition

    Namely, that action and condition are both singular and there can be no else clause involved. In other words, having the condition terminate the line indicates that nothing further depends upon it's evaluation. So, instead of adding ambiguity or confusion, I would say number two is (potentially) the opposite: it reduces possible ambiguity because the conditions of it's use are more specific. I guess that "potential" depends on how you choose to respond to it.

      foreach (@ray1) { push @ray2,$_ if ($_<0) }
      doesn't seem to be the best example to use since it is probably better expressed with a map like
      push @ray2, grep { $_ < 0 } @ray1
Re: A matter of style: how to perform a simple action based on a simple condition?
by sundialsvc4 (Abbot) on Sep 27, 2010 at 14:11 UTC

    To me, the only consideration is that:   the code must be obvious and consistent.   Every “shop” will develop “accepted practices,” and the most important thing that you must do is to follow them.   Source code size is not a consideration.   The computer is blisteringly fast.   Disk space is unlimited.   If you can’t type, hire a typist.

    Anyone who looks at your code must be able to understand at a glance what it is doing, and their “glance” must be correct.   Remember that people see what they expect to see, as demonstrated by this old chestnut:

    PARIS IN THE THE SPRING
    PARIS IN THE SPRING,” right?   Look again.

    So, “the correct style” is to first find out how your shop is writing such things now, and then to proceed to do it in exactly the same way.   Otherwise, find what is the most abundantly clear way to write it... which is usually not the most brief.

    Finally, always consider changes.   The code that you write will one day be changed, probably in a hurry, probably not by you.   Does “a slight change” to your code “break it?”   Especially... does it “break it” in such a way that it no longer works as intended, but also does not produce a syntax-error?   The consequences of any such change can be disastrous.

      Anyone who looks at your code must be able to understand at a glance what it is doing, and their “glance” must be correct.

      Would you expect a non-musician to be able to work out how a piece of music will sound, from "a glance" at the score?

      Or your mother to know the function of a circuit, from a "glance" at a circuit diagram?

      Or a butcher where to cut you, from "a glance" at your head x-ray plate?

      Hopefully, that's taken care of the "anyone" bit.

      Musicians practice endlessly, even when playing a piece they've played hundreds of times before.

      Give a circuit diagram to the most qualified electronics engineer, and ask him what it does, and he'll likely want minutes, if not weeks of deliberation and inspection before he'll offer an opinion.

      And nobody wants a brain surgeon rushing into their head, after "a glance" at the x-ray.

      Beyond the most trivial, computer programs are at least as complicated as all of those. When will programmers stop devaluing their own skills, in the expectation that just anyone should be able to understand the product of hours or days of their effort, "at a glance".

      Source code size is not a consideration.

      This is another obvious sounding aphorism that simply isn't true. Disk space may be dirt cheap, and computers very fast, but computers don't write or modify code. Human beings do. And human beings have limited resources.

      We have limited recall. And limited vision. And one of the effects of that, is that the more spread out the code, the harder it is to grasp an overview of that code. It is this very thing that makes high level languages easier to read, write and maintain than assembler.

      The long, narrow source code layout of assembler with one op-code per line, makes it extremely difficult to maintain a knowledge of what variables are "in scope". And nigh impossible to gain and maintain an overview of what the code is doing. High level languages operate by hiding dozens or even hundreds of op-codes behind each individual line. Thereby allowing the programmer to see the wood for the trees.

      Laboriously and verbosely spreading out the individual elements of a program's structure in the vain ideal that it will make it easier for the uninitiated novice to understand, is like putting big, grippy handles on a scalpel, in the hope that it will make surgery easier for the local car mechanic.

      Programming is hard. It requires learning, skills and practice. It should not be devalued as a blue-collar skill that can be acquired by any walk-in after a 3 day orientation.

      It's a well documented fact that the best programmers are anything from 3 to 10 times as productive as the average. But that productivity does not come from them being able to type at 10x the speed. It comes in large part because they do more with each line of code they write.

      And that has the knock on effect that during maintenance, there is less code to read. It is easier to form the overview, because each screen-full embodies more of the overall picture. Each line enacts one, complete logical step of the high-level algorithm, rather than that logical step being spread out across 5 or 10 lines.

      Yes, each line may require more than "a glance" to understand. But because more logical steps of the full algorithm are visible, the overall flow becomes obvious more quickly.

      And your own example makes the point as clearly as any other. If you write your old chestnut as a single line, rather than spreading it out down the page:

      PARIS IN THE THE SPRING

      The flaw ("bug"), becomes obvious.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        /me applauds

        In my perception one of your best answers ever.

        It reminded me of a joke I recently heard (shortened):

        mechanic: why do you pay me $40/hour for fixing your car and you earn $400/hour for fixing a limb? We both deal with internals and complex systems. We both take it apart and put it back again so that it works. brain-surgeon: did you ever try to do so with a running engine?

        Enjoy, Have FUN! H.Merijn
Re: A matter of style: how to perform a simple action based on a simple condition?
by sundialsvc4 (Abbot) on Sep 27, 2010 at 19:15 UTC

    Actually, I can speak to the bit about “a musician” with respect to, “at a glance.”

    When you are scoring a piece of music, especially for performance by a union-scale studio musician, then there are definitely a set of visual standards that the copyist must adhere to.   These very highly-paid individuals look at music all day long and for the most part they are able to “sight read” it, be-cause (in addition to their dazzling musical skills) they know in advance what to expect.   If your score doesn’t meet the accepted norms, it will slow them down (and, probably, piss them off, along with the conductor), and either way, that costs money.   The clock is running.

    So, yeah ... and without trying to piss anyone here off, by the way ... I’ll stick by my point.   When people have looked at enough code, at a particular “shop,” they do build up a set of expectations concerning the next piece of source code that they will look at.   They might not read that source-code thoroughly.   If they make an error, it is possible that a syntax-error (“crash”) will not be generated.   When that unfavorable alignment of the planets occurs (and, from time to time, it will), precious hair follicles will be emptied quickly.

    Hence, “style” is a serious concern in day-to-day practice, if for purely human reasons.   The computer really does not care too much either way.   But avoidable and expensive mistakes will occur when this is neglected.

    And actually, BrowserUK, I think that this is really what you are saying, too.   You have very definite expectations, e.g. “a complete thought on a single page.”   Adherence to those principles is very important to you, and your arguments cannot be denied.   It would be very important, then, that all of the code that you see should be written consistently with those principles ... whether you or any of your co-workers actually wrote it.   Deviation from what is, to you, in your shop, your “accepted norm,” disrupts you and greatly increases the probability of error (not to mention “pissed off”).   You are right.   I would not disagree with you.   Everyone, I think, comes to feel that way, even though the “accepted norms” may vary considerably from one shop to the next.   We do an exacting, high-pressure, error-prone job.   Details matter greatly.   “Variety” is not wanted.

    “Because it matters to the Romans, that’s why.   (They’re the really big fellows with the really big, sharp swords.)”

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://862038]
Approved by GrandFather
Front-paged by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (7)
As of 2024-03-19 02:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found