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


in reply to Avoiding silly programming mistakes

missingthepoint,
A lesson learned as a result of being bitten sticks much more readily than one learned as a theoretical precaution. Here are two cases in point:
sub foo { my $arg = shift; # ... } vs sub bar { my ($arg) = @_; # ... }

I started using the second construct because adding additional parameters only requires me to change the LHS. I had got bitten enough times to warrant the change.

if ($foo == 0) { # ... } vs if (0 == $foo) { # ... }

The reason some people recommend the latter is because if you accidently type the == equality operator as the = assignment operator, you will get an error (not so for the former). Since I vary rarely get bitten by this, I still use the former.

In a nutshell, there is no substitute for experience. The gray area becomes how much needs to come from your own personal experience or how much you can learn from someone else's experience. I recommend reading Re: Refactoring a large script and adopting any advice there that you don't currently use. Share what common mistakes you make and ask around what methods others use to avoid them. Share what you have come up with on your own so that others can benefit.

Cheers - L~R

Replies are listed 'Best First'.
Re^2: Avoiding silly programming mistakes
by missingthepoint (Friar) on Aug 21, 2008 at 11:27 UTC

    Thanks, L~R. That first trick seems useful... I'll work hard to adopt it.

    I've come across the second before as I have some C experience. Initially, I found it useful. After using it for a few months I realised I'd gotten into the habit of writing

    if (constant == variable)

    ... so I deliberately switched back to writing

    if (variable == constant)

    ... and I haven't made the 'one-equals' mistake since. For me it was a good mental training exercise.

    Oh, and I'm reading the refactoring post now. Ta.


    email: perl -e 'print scalar reverse map { chr( ord($_)-1 ) } split //, "ufo/hojsfufqAofc";'
Re^2: Avoiding silly programming mistakes
by JavaFan (Canon) on Aug 20, 2008 at 13:35 UTC
    {if (0 == $foo) vs if ($foo == 0)} The reason some people recommend the latter is because if you accidently type the == equality operator as the = assignment operator, you will get an error (not so for the former). Since I vary rarely get bitten by this, I still use the former.

    That's a C thing; that is, a practise that was used among C programmers long before Perl programmers started coding.

    It's not really necessary to do so in Perl; with warnings on, if you mistake the operator, Perl will warn (Found = in conditional, should be == at ...). I think some C compilers (like gcc) will warn if you have an assignment in a conditional as well; which can be disabled by using an additional set of parenthesis.

      JavaFan,
      It's not really necessary to do so in Perl...

      Probably why I have never adopted it. That doesn't mean that there aren't people out there recommending it. For those following along at home, perl doesn't always issue a warning with the assignment operator in a conditional:

      #!/usr/bin/perl use strict; use warnings; if (my $foo = foo()) { print "No warning\n"; } if (my @asdf = (1..5)) { print "No warning here either\n"; } if (my $bar = {one => 1}) { print "Look Ma, no warning\n"; } while (my $rec = <DATA>) { # ... } sub foo { return 42; }

      Of these, the only suspect one is the first and perl assumes you know what you are doing. Writing it with the operands reversed would have generated an error (assuming no lvalue attributes) but I agree, this is a stretch.

      You have re-inforced my two points. A lesson learned the hard way is learned best and there is no substitute for experience but figuring out how much of other's experience to rely on is tricky.

      Cheers - L~R

        If you even declare a variable, it would be nonsensical to warn when you assign to it. It's more the other way round:
        if (my $x) { ... }

        (variable declaration in a conditional without assignment) could actually warn, because it will never be true. (But perl intentionally doesn't have such warnings, some people like stuff like if (0) { ... }).

        All your example have a declaration in the test; so it seems more likely you want to do the assignment than the comparison.

        However, Perl doesn't warn on

        if ($foo = foo()) {...}
        This is actually a common idiom, so it would be wrong for Perl to warn. Note that swapping the arguments around won't help you either:
        if (foo() = $foo) {...}
        may be valid (if foo() returns an lvalue). And whether it's valid or not is something you only know at run time - at compile time Perl cannot know whether foo returns an lvalue or not. So at best, you get a run-time error.

        And if you want to compare two variables, there's no defense against mistyping '==' as '=', as both if ($foo = $bar) and if ($foo == $bar) is common.

      Some compilers do. Some compilers do not tell you a thing "'cause you should use lint". Get used to the former and if you happen to come across the other you end up wasting hours of time. Luckily it did not take me so long when I was asked to make some changes while doing the "Unix and C I." exam several years ago after only ever using Borland C for a bit. The fact that there was just a single plain old textmode terminal with vi or pico to do anything with did not help a bit.

      I like the if ( 0 == $foo ) construct over if ( $foo == 0 ) because the s/==/=/ typo is an error in the first but not the second.

      Can't modify constant item in scalar assignment

      I'd rather have that than some mere warning.