Hello. A question of style...

What is your preferred method of line-breaking conditional expressions (assuming they're long enough to warrant line breaking, unlike my examples below)? (I'm ignoring the "where does the curly brace go" issue here :)

Some examples:

# The operator goes at the end if (A && B && C) # The operator goes at the beginning if (A && B && C) # My editor won't do this one for me automatically if ( A && B && C)
I use the first two examples above under different conditions, but I haven't identified what makes me choose one or the other, yet.



Update: Lately I've been using operator-first notation. I almost always indent all of my perl the way Emacs perl-mode wants it indented, so most of the time I don't spend much time thinking about it.

Replies are listed 'Best First'.
Re: Logical expression style
by dws (Chancellor) on Jul 12, 2002 at 16:52 UTC
    When making on-the-fly decisions on breaking lines, I try to consider readability and recognizability. They're different beasts, though they're often conflated. Readability is about being able to grok the entire expression. Recognizability is the ability to classify the expression when doing a quick scan through the code. When scanning quickly, my eyes focus to the left.

    Consider the fragment:

    if ( A && B )
    This is certainly readable, but to recognize what the expression is (i.e., is it a conjunction, disjunction, or a hybrid) requires reading to the end of the line. If it's a long line, this slows down my scanning pattern by making me read further to the right.

    Now consider

    if ( A && B )
    Equally readable, but easier, in my opinion, to recognize when quickly scanning code.

    Formatting for recognizability also forces a non-obvious change in indentation style. I'll write

    if ( A && B ) { ... }
    if the expression is short enough to fit on one line, but will write
    if ( A && B ) { ... }
    if the expression needs to be broken across lines. The reason? It's easier to quickly pick out the scope when scanning code. If I were to be consistent, and format the fragment as
    if ( A && B ) { }
    it would still be readable, but a bit harder to quickly recognize.

Re: Logical expression style
by Abigail-II (Bishop) on Jul 12, 2002 at 15:57 UTC
    I mostly use the "operator goes at the end" style, although I do sometimes make an exception for or die. As a condition for an if or while, I always put the operator at the end, unless it wouldn't fit the line, and there's other decent way of breaking the line (my number 1 rule for formatting code is "a line shall never exceed 80 characters").

    It is important though that operators that are on the same "level" are lined up vertically. (I'm a big fan of lining up similar things in columns).


Re: Logical expression style
by FoxtrotUniform (Prior) on Jul 12, 2002 at 16:13 UTC

    I use the "operator goes at the end" style, which for some reason just seems more natural to me. (ISTR someone else in the monastery claiming that the trailing operator signals "this isn't done yet"; works for me.) I do this with long expressions in general, not just logical expressions in conditionals:

    my $str = &long_function_name_foo() . " some literal string or other " . &long_function_name_bar();

    I know a number of people who religiously break up long conditionals or subroutine calls, but are perfectly happy to leave 250-column string concatenations in their code. That blows my mind every time I see it.

    The hell with paco, vote for Erudil!

(tye)Re: Logical expression style
by tye (Sage) on Jul 12, 2002 at 17:04 UTC

    I don't like any of them (I've been trying (off and on) and failing to find a good standard for this type of thing for a long time). But I really don't like hiding the operators on the end. And I don't like adding extra parens just to "show precendence" (my eye can't match nested parens nearly as well as it can notice variations in spacing).

    So now I try to line things up by precendence with the operator in front. I always put two spaces around logical expressions so I can put single spaces within them.

    if( defined $settings && ! $setttings->{hidecode} and $codtype{ $node->{nodetype} } or $node->{code} || containscode( $node->{doctext} ) # ^1 ^2 ^3 ) {
    So the 'arguments' to 'and' line up above "^1", the arguments to 'or' above "^2" and the arguments to '||' above "^3". I think I've finally found a standard for this that I like. (:

            - tye (but my friends call me "Tye")

      I think I do about the same thing, but isn't this slightly misleading? Since the or binds least tightly, if I were to show precedence, I'd do:

      if ( defined $settings && ! $settings->{hidecode} and $codtype{ $node->{nodetype} } or $node->{code} || containscode( $node->{doctext} ) ) { # ...
      In other words, I'd line up the horns of the or at the outermost level, and then the and, etc.

      Or did I miss the point you were trying to make? (No pun intended ;-)

      This is similar to how I indent SQL where clauses:

      where EXISTS (select 1 from users where users.user_id = acct.user_id or (acct_id is null and user_id = 0)

        Yes, it was a contrived example and I did it wrong. ):

                - tye (but my friends call me "Tye")

      I think I would go cross-eyed trying to read that! Just looking at it gives me that "all over the place" feeling.

      I tend to use the operator at the end method.

      Omigod! My eyes! I looked directly at the code!
      if ( ( defined $settings && ! $settings->{hidecode} ) && ( $codetype{ $node->{nodetype} } ) || ( $node->{code} || containscode( $node->{doctext} ) ) ) {

      A few extra parens makes it much more readable in my opinion.

Re: Logical expression style
by John M. Dlugosz (Monsignor) on Jul 12, 2002 at 16:48 UTC
    Operator at the beginning is better for end-of-line comments--I wan't those immediatly after the thing being commented upon, not after enclosing syntax elements.

    Think about column addition:

    +45 -12 + 3
    That makes for readable code:
    $x= $principle # last month's value +$interest # interest between last payment and today -$payment # current remittence ;
    That works for booleans sometimes, too.

      "Think about column addition:"

      Is that because we learnt math long hand? :) I wonder if it will change as students learn math more and more on the calculator or computer...

      Until you've lost your reputation, you never realize what a burden it was or what freedom really is. -Margaret Mitchell

        No, a grocery list, TODO list, and expense/income list are all instictivly written in a column. We still do that when making a spreadsheet.

        I think it's our bias to put the +/- before the item; it works just as well after:

        17.00 Credit 20.89 Debit ...
        But the common thing is that the operator and its operand are on the same line. In the infix notation used by Perl and most common languages, that means putting it on the left. In RPN-style calculators, it means putting it on the right.

(jeffa) Re: Logical expression style
by jeffa (Bishop) on Jul 12, 2002 at 17:27 UTC
    I opt for a style such as:
    if ( A && # condition A B && # condition B C # condition C ) { # do stuff }
    However, i really try to avoid these situations by relying on hashes instead. In fact, i have been getting into the habit of using this style for just about everything i do in Perl. It's a derivative of how i code a sub:
    sub foo { # blah blah blah }
    Defining a hash:
    my %hash = ( foo => 'bar', baz => 'qux', );
    Defining an array with long elements:
    my @array = qw( foofoofoofoofoofoofoofoofoofoofoofoo barbarbarbarbarbarbarbarbarbarbarbar );
    A subroutine call:
    print checkbox_group( -name => 'words', -values => [qw(eenie meenie minie moe)], -defaults => [qw(eenie minie)], );
    The idea is to have each 'thing' on it's own line (with trailing commas where applicable), and line up the closing bracket or paren directly under what opened it.


    (the triplet paradiddle with high-hat)
      Same here. I regard parens and curly braces as pretty much the same thing. If the inner block is short, the whole thing goes on the same line. Otherwise, the opening (paren|curly) is at the end of the first line, the block inside it indented on the following lines, and finally the closing \1 follows outdented on the next line. I place closing and opening parens/curlies back to back on the same line, but do not cuddle else's.
      if( $very_long_expression_written_out_here && $another_long_expression_in_this_line && $yet_more_following_here ) { do_whatever(); } else { do_something_else(); }
      These are not absolutely inflexible rules though; if large and small blocks intermingle, I break one or another rule in order for the parts to stand out from each other. The first and foremost rule is that I should have no trouble picking up the exact structure of the source while scrolling, even when the text is moving too fast to actually read it. That augments both the legibility of the code as well as my efficiency, because I can navigate large bodies of code purely visually.

      Makeshifts last the longest.

(zdog) Re: Logical expression style
by zdog (Priest) on Jul 12, 2002 at 16:52 UTC
    My style is probably closest to your "operator goes at the beginning". I do stick the operators in front of the expressions, but I usually indent slightly more:

    if (A [too, short, lets, add, something] && B [too, short, lets, add, something] && C [too, short, lets, add, something])

    Why? Well, it's sorta like saying why one color is better than another (at least to me). For one, the extra indention that puts B and C below A helps clarify (again, "to me") that B and C are part of A's expression. Second, the &&'s sorta act like bullets listing the B and C expressions. :-) And finally, in my head, the &&'s apply more to B and C rather than A and B.

    Maybe those aren't very good reasons, but I just like it like that, and in the same way: "Blue rules!" ;-)

    Zenon Zabinski | zdog |

Re: Logical expression style
by hsmyers (Canon) on Jul 12, 2002 at 17:49 UTC
    I try and avoid thinking about it! Actually what I do is run things through perltidy and live with the results. For instance, the code:
    if ($a or $b or $c or $d or $e or $f or $g or $h or $i or $j or $k or +$l or $m or $n) { }
    when run through perltidy comes out like:
    if ( $a or $b or $c or $d or $e or $f or $g or $h or $i or $j or $k or $l or $m or $n ) { }
    Skipping lightly over endless arguments about just where the "damn curly brace"™ should go gives me extra time to realize that the silly thing is missing or the like!


    "Never try to teach a pig to sing…it wastes your time and it annoys the pig."
Re: Logical expression style
by greenFox (Vicar) on Jul 13, 2002 at 03:54 UTC

    I tend to go for the operator at the end style though I tend to agree with those who have pointed at that a trailing comment will mask the operator.

    I am wondering if style in this instance at least is partly a function of how you read code- if you skim down the code by focussing on the line beginnings you might want the operator there so you can immediately recognise it as part of the previous line. If (this is what I tend to do) you skim by focussing on the beginning and the end of the line (without paying too much attention in between) having the operator on the end makes sense, it allows evaluation of the line to take place without reading the next line or tells you "nope more to come on this".

    I think I have a built in regexp that looks for ";" or "{" or an operator on the end of the line and reports a bug if it doesn't find one :) - since I don't often work on any-one else code it's not too much of a problem :)

    Until you've lost your reputation, you never realize what a burden it was or what freedom really is. -Margaret Mitchell

Re: Logical expression style
by dada (Chaplain) on Jul 18, 2002 at 12:02 UTC
    that's how I do it (I know it isn't perlstyle, it's just how I do it):
    if( A and B and C ) { # ... } # I drop the extra space when doing 'or': if(A or B or C ) { # ... } # I super-indent when booleans are composite: if( A and ( B or C ) and D ) { # ... }
    I *always* leave parentheses on a line by its own, because too often I have to add an 'or C1' that I didn't thought of.

    this also goes for lists, BTW. I *always* leave the last dangling comma (many, many times I wish I could do it in C):

    my @array = ( $one, $two, $three, );
    __END__ $_=q,just perl,,s, , another ,,s,$, hacker,,print;
Re: Logical expression style
by rayg (Initiate) on Jul 15, 2002 at 00:41 UTC
      Thats close to what i do too:
      if ( AA && ( BB || ( CC && DD ) ) ) { # ... }