in reply to Re: Control Structures
in thread Control Structures

Really? Thats an interesting observation, I always found both forms useful for minimizing noise and making flow control clearer. I find unless in either form (block or modifier) somewhat more inclined to be difficult, but the modifier if, and even unless coupled with loop control statements like next and last to be very useful in enhancing readability.

When I see something like

next if $condition;

it allows me to think "condition is prohibited past this line", i dont have to worry that later on the block ends and !$condition is still possible. For instance in the following code if at a later I point I forget the importance of the next, or possible restructure code so it doesnt fire sometimes something bad could happen after the block and I might not even notice it until debugging. The statement form doesnt allow such complexity so it sort of red-flags itself as being "mess with this and the code below has to be completely reconsidered."

if ($condition) { ... next; } # !$condition stuff can happen here
---
$world=~s/war/peace/g

Replies are listed 'Best First'.
Re^3: Control Structures
by perrin (Chancellor) on May 10, 2005 at 15:08 UTC
    Trailing if() leads to this incredibly hard to debug problem, which I have seen in production code. So, you could say that trailing if() would be fine except that perl has bugs with it, but that doesn't really help the current situation.
      I disagree - that's not a problem with the trailing if(). That's a problem with how my() is implemented as both a compile-time and run-time actor. The trailing if() is doing exactly what it's supposed to do, which is execute the statement at run-time if the conditional is true.

      The reason it's counter-intuitive is because my() is the only statement that affects the current scope with both compile-time and run-time actions. If you use a standard if-block with {}, you create a new scope and everything acts as expected.


      • In general, if you think something isn't in Perl, try it out, because it usually is. :-)
      • "What is the sound of Perl? Is it not the sound of a wall that people have stopped banging their heads against?"
        Try explaining that to a mid-level perl developer or an experienced programmer who is still learning perl and watch their eyes glaze over. The problem goes away if you don't use trailing if() statements.

      Ah, that error. Well i thought 5.8.x was supposed to warn when this happened but based on the tests I just did it doesnt. Maybe its 5.10 when its supposed to happen. But I do agree with dragonchild that its a bit hard on if() to consider it a bug when in fact the error is in the my(). :-)

      Anyway, it is a good thing to keep in mind. If you want to do conditional initialization as part of the declaration of a lexical you should always use the ternary operator and not a modifier. I guess I have this lesson so hammered into my head that I find it hard to see it as an error, which of course it is.

      ---
      $world=~s/war/peace/g

      Seems like a classic case of "doctor, it hurts when I do this".

      I'd consider myself a mid-level Perl programmer, it's never even occured to me to try my $foo if $bar, simply because "conditional declaration" isn't a concept that makes sense to me. I understand the linked explanation, I'm just saying I would never have arrived at that construct on my own, so it seems unlikely to cause trouble for new programmers.

      If people feel the need to abuse the side effects of an implementation bug in production code, well, that's not a problem with the language design.

        If you think it's that obvious, you're not getting it. Here's some code that demonstrates how this can bite you:
        sub sticky { my $arg = shift; my $object = Some::Package->new() if $arg; $object ||= Other::Package->new(); }
        The first time you run it with $arg = 0, you will get the expected result. The second time through with $arg = 0, you will find the Other::Package object from last time in $object and it will not get a fresh Other::Package object assigned to it. So, if you never put anything in $object when the conditional is false, you won't actually see the bug.

        I have personally seen people lose days debugging problems caused by this, and have heard stories about it happening in other companies too. It's hard to see, it's very hard for people to fully understand, and it really happens in production code.