in reply to Please critique this script -- Read emails and write URLs into bookmarks

Modern Perl assumes you're already decent at programming, so it elides some basic stuff in favor of explaining how Perl works from philosophy to programming in the large. Learning Perl assumes you've never programmed before, so it spends more time on the basics, covers less of the language, and doesn't explore the philosophy of Perl in as much detail.

-- chromatic (author of Modern Perl) comments on the philosophy behind his book

Given this is your first Perl script, you have demonstrated that you are an accomplished programmer, who is new to Perl. Accordingly, I feel Modern Perl is more appropriate for you than Learning Perl. Modern Perl is free and very quick to read. If you have more time, and want to get inside the head of the language designer, Programming Perl is also good.

As for good "second" books on Perl, I suggest:

In particular, Perl Best Practices, Chapter 4, "Values and Expressions" in the "Don't mix high- and low-precedence booleans" item, discusses a stylistic point already raised in this thread.

For flow of control, 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) ...

Replies are listed 'Best First'.
Re^2: Please critique this script -- Read emails and write URLs into bookmarks
by Anonymous Monk on Oct 12, 2016 at 08:41 UTC

    Thank you for the book recommendations.

    "For flow of control, prefer the low precedence and and or operators. A common example of preferring or to || is:"
    "Reserve && and || for logical expressions, not flow of control, for example:"

    I'm inclined not to follow this. I don't like to rely on subtle precedence rules.

    Is there any reasoning to not always use parentheses instead? (Not that I did that in the versions you know.)

      Is there any reasoning to not always use parentheses instead?
      Yes, clarity and readability.

      While I certainly do not endorse memorising the precedence table, I feel non-casual programmers should know the precedence of very commonly used operators. To illustrate, if you follow the "always use parentheses" rule, you'd be obliged to write:

      ( my $x ) = ( $y + 42 );
      which I feel is borderline obscene. This is surely more clearly written, without the clutter of parentheses, simply as:
      my $x = $y + 42;
      BTW, I would similarly object to parentheses here in C or in any language where assignment is an operator.

      In Perl, I place the ultra low precedence and and or operators in the same category as the = operator, at least for non-novice Perl programmers. Being very low precedence makes them especially well-suited to flow of control, and I agree with Conway that reserving them exclusively for that purpose, for example:

      open(my $fh, '<', $file) or die "error opening '$file': $!";
      or:
      $meaning == 42 or next;
      is idiomatic Perl and makes the code clearer and more enjoyable to read.

      I'm inclined not to follow this. I don't like to rely on subtle precedence rules. Is there any reasoning to not always use parentheses instead?

      (This is a quite generic question, applying not only to Perl, and so the answer does not only apply to Perl.)

      There might be reasons, I guess the most common ones are avoiding typing and cleaner code.

      And I think both do not apply, for exactly the reason you gave: "I don't like to rely on subtle precedence rules."

      Treating operators as having completely random precedence, except for parentheses and the "multiplication and division before addition and subtraction" rule definitively prevents nasty surprises with operator precedence. Adding parentheses does not hurt, the compiler or interpreter should need just a few CPU cycles to handle them. Parentheses clearly indicate the programmer's intended order of evaluation, without forcing the next programmer to memorize precedence rules.

      Example:

      if (a && b || c && d || e) // wtf? Don't make me guess what you intend +ed! if ((a && b) || (c && d) || e) // clear if (a && (b || c) && (d || e)) // as clear, but a very different condi +tion if (a && (b || (c && (d || e)))) // a different condition if ((((a && b) || c) && d) || e) // another different condition

      My current job is developing embedded software for medical and aerospace devices. We have a very strict rule that parentheses are required whereever code might be ambiguous. The first example would never get through the obligatory code review; you will never find that in production code.

      And by the way: If you are working with several languages, as I do, you will notice that precedence rules vary from language to language. Most copy or inherit from C, but some are very different. MUMPS evaluates strictly from left to right, unless parentheses are used. In MUMPS, WRITE 1+2*3 writes 9, not 7. WRITE 1+(2*3) writes 7.

      Of course, redundant parentheses are rubbish:

      if ((((((((a && b))) || (((c)))))))) // make extra-sure that parenthes +es have precedence ;-)

      Some times, lots of parentheses are required, adding some white space and indention clearly helps:

      if ( ((a == A_MAGIC_1) || (a == A_MAGIC_2)) && ((b == B_MAGIC_1) || (b == B_MAGIC_2)) && ( (c == C_MAGIC_1) || ((c == C_MAGIC_2) && (a == A_MAGIC_2) && (b == B_MAGIC_2)) ) )

      Yes, this will make the C compiler "waste" about thirty precious CPU cycles eating up all of that redundant white space and braces. Just think how long that takes at 3 GHz! And it gets worse, because all of the source code "wastes" CPU cycles. So compiling the enitre project takes 1.5 msec more time than needed. Flashing into the target takes 20 +/- 2 seconds. Deciphering source code "optimized" for better compile times takes minutes per line, hours per file, every time a change is required. This is a real waste of time and money. Computers and compilers become faster every day. A modern desktop runs circles around old super computers even with crap components. "Optimizing" source code for compile time is ridiculous, except in very rare high-performance cases.

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)