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

doing some debugging of some accounting code yesterday i tossed in a statement like this:
my $counter; foreach my $elem ( keys %users ) { $counter++ and print "found $users{$elem} if ( $users{$elem}{sales +} - $users{$elem}{payments} > 0; }
the counter would increment, but the print never occurred.

return status of  print is always 1, and the return value of  $counter++ should have been 1, because the counter was incremented ( as evident after the loop. so why would i get a counter increment and not a print?

Replies are listed 'Best First'.
Re: idiom question
by Paladin (Vicar) on Jan 17, 2004 at 19:03 UTC
    If $counter is initially 0, then the print won't get executed, because the post-increment $foo++ operator takes the value of $foo first, then increments it, so your code ends up as:
    0 and print "..." if ...
    If you change it to ++$counter, which increments, then takes the new value, it will probably do what you think it should.
      you know, i should have remembered that. but i didn't.

      pre-increment would have DWIM.

Re: idiom question
by Roger (Parson) on Jan 18, 2004 at 01:35 UTC
    I see your question has been answered by Paladin. The alternative solution without worrying about side effects: if you want to increment counter as well as print, just replace and with a comma (,):
    my $counter; foreach my $elem ( keys %users ) { $counter++, print "found $users{$elem}" if ($users{$elem}{sales} - + $users{$elem}{payments} > 0); }

      to get past the issue i just ended up with the usual if () {} block. i needed to see the values only to verify information in the DB at the time. the 'balance due' didn't look like it was adding up, so i wanted to verify my accounting methods.

      and i'm also glad i'm not an accountant.

Re: idiom question
by davido (Cardinal) on Jan 18, 2004 at 05:30 UTC
    Paladin is correct. Here's the issue:

    "and" (the logical short-circuit operator) only evaluates the right hand side, if the left hand side is "true". That's because, if the left hand side is false, the entire statement can't possibly be true, so there's no point in evaluating the right hand side. That's part of what makes it a "logical" operator. It follows a path of logic. Test left hand side. If left hand side evaluates to true, test right hand side. If it evaluates to true also, the entire chain is true.

    So on the first iteration, $counter is zero, which happens to be one value that Perl considers to be "false".

    But you're incrementing $counter, with ++... why is it false? Because trailing ++ executes after the expression has been evaluated. Perl also allows for leading (versus trailing) ++ (autoincrement) operators. You could write the expression like this, and you'll find it works like a charm:

    ++$counter and print "found $users{$elem} if ( $users{$elem}{sales} - +$users{$elem}{payments} > 0 );


    Dave

Re: idiom question
by dd-b (Pilgrim) on Jan 17, 2004 at 18:53 UTC

    I see an unclosed double-quoted string, beginning just before "found". I'm guessing this would be a syntax error if submitted to Perl; so presumably this code snippet isn't exactly what you're really trying to run?

    Guessing that the close quote is supposed to go before the "if"...

    I think you have a precedence problem. Trying to use the "and" to string two statements under control of the if statement-modifier always makes my head hurt when I try it, so if I actually want to control two statements, I use a real if. I'll bet if you do that, it does what you expect.

      yes, the missing quote was just a typo. the real code is at work. i was going from memory.
Re: idiom question
by thor (Priest) on Jan 18, 2004 at 16:17 UTC
    return status of print is always 1
    ..for certain values of always. :-) print can return a non-successful status for a number of reasons. What if you try to print to a file that resides on a filesystem that is full? What if you're trying to print to a socket whose endpoint has crashed? print will tell you about all of these and more.

    thor

      point taken.

      print to STDOUT rarely, if ever, fails. and that's all i was doing.