Shlomi Fish <shlo...@shlomifish.org> writes:

> Hi Lee,
>
> On Sun, 23 Jun 2013 04:43:58 +0200
> lee <l...@yun.yagibdah.de> wrote:
>
>> James Alton <jamesalton...@gmail.com> writes:
>> 
>> > lee,
>> >
>> > You have a post statement if and then a code block. You can only use one of
>> > two forms:
>> >
>> > print "test" if $color eq "blue"; #no parenthesis required
>> > if($color eq "blue"){print "test";}
>> 
>> And I can't have 'last if $color eq "blue" print "test\n";'?  That would
>> be something quite natural and a logical thing to do ...
>
> Do you want something like:
>
> if ($color eq "blue")
> {
>       last;
> }
> else
> {
>       print "test\n";
> }
>
> Because I cannot parse the meaning of your other statement.

It would be like:

if($color eq "blue") {
  print "test\n";
  last;
}

An 'if' is an 'if', and when putting 'last' in front of it changes it to
something else, why isn't there a keyword for it like 'lastif'?

>> > As far as last, http://perldoc.perl.org/functions/last.html
> [...]
>> > What they're saying here is that it breaks out of a loop. Its not like a
>> > return where it breaks out of a subroutine, it just continues beyond the
>> > loop.
>> 
>> Yes, I looked at that and found it rather confusing.  Now I guess it
>> breaks out of the current (innermost) loop unless a label is being used
>> which would allow to break out of whatever loop the label refers to,
>> like:
>> 
>> 
>> BREAK: while($loop_1) {
>>          # do something with $color and $loop_2
>>          while($loop_2) {
>>            last BREAK if $color eq "blue";
>>            print "not blue\n";
>>            # do something with $color and $loop_2
>>          }
>>        }
>>        print "broken\n";
>> 
>
> Yes, Perl Best Practices recommends to always use a label with "last", "redo"
> or "next" to avoid problems where you add or remove more inner loops. I agree
> with it here:
>
> http://perl-begin.org/tutorials/bad-elements/#flow-stmts-without-labels

It seems to me that adding another loop can break the code no matter
whether you use labels or not.  Consider above example and let's add
another loop, which then looks like this:


BREAK: while($loop_1) {
         # do something with $color and $loop_2
         while($loop_2) {
           # added some stuff here
           while($foo) {
             # added some more stuff here
             last BREAK if $color eq "blue";
             print "not blue\n";
             # do something about $foo
           }
           # do something with $color and $loop_2
         }
       }
       print "broken\n";


Assume you overlooked the label.  Now after a while of programming or
maybe even days later you find that your code doesn't work as
expected. You come back to it and either you still overlook the label
and have trouble figuring out what's going on, or you will be asking
yourself what you actually wanted to do.

The label only makes sure that the script will break out of a particular
loop, and that may be the one you want it to break out of or not.  The
assumption that "later on, one may modify the code to insert a loop in
between the innermost loop and the flow control statement, which will
break the code"[1] can be true or not, no matter whether labels have
been used or not.

When we were still programming in BASIC, the using of 'goto' statements
was considered very bad style.  The using of labels in perl like this
doesn't seem to be any different.  Sure it can be useful, but if I had
to use a label like this, I'd feel that I should put big fat warnings
about it into a comment /because/ it is more likely to break the code
when changes are made than not using a label like this is.


[1]: http://perl-begin.org/tutorials/bad-elements/#flow-stmts-without-labels

> Yesterday, I introduced a bug or two in my C code (which were luckily caught 
> by
> the tests) because I removed a loop and as result a few C "continue" 
> statements
> (which is equivalent to Perl 5’s "next") terminated the more previously outer
> loop. It is possible that the C compilers of
> http://en.wikipedia.org/wiki/GNU_Compiler_Collection and 
> http://en.wikipedia.org/wiki/Clang have extensions for doing that similar to
> what Perl has, but I couldn't find them yet.

Spaghetti code in C? ;)  Maybe I'm overlooking something; do you have a
good example where using a label prevents you from breaking the code?

>> 
>> The really confusing part is/was what the 'last' statement actually does
>> when used in conjunction with an 'if'.  Apparently it re-defines the
>> meaning of 'if' --- or there are multiple versions of 'if' in perl:  
>
> No, it does not.

It does:

while($test) {
  if($foo) {
    print $bar;
    last;
  }
  else {
   print $test;
  }
}

That would work, and

while($test) {
  last if($foo) {
    print $bar;
  }
  else {
   print $test;
  }
}

doesn't work.  (The 'else' branch is redundant and may be wanted for
better readability.)  Prefixing 'last' to an 'if' clearly modifies the
'if' to something that cannot do what an 'if' does.  Otherwise, the
second example would work as expected.

>> One
>> version is the "usual" one like 'if(condition) { foo; } else { bar; }'.
>> The other one is some sort of appendix which is logically prepended
>> to the statement and, unfortunately, lacks the ability to do something
>> besides the statement it is appended to.  Maybe '$color eq "blue" ?
>> print "test" : print "red\n" if $color eq "red";' ...
>> 
>
> Actually, it is appended instead of prefixed, and you can do any single
> statement inside that, like:
>
> $x = $y if COND();
>
> print "Hello\n" if COND();
>
> etc.

That's because it's logically prefixed though it's syntactically
appended.  It's like writing instructions for making fried potatoes, and
only at the end of the instructions you tell the reader that they were
supposed to skin the potatoes and to cut them into slices before they
started frying them ;)

> See http://perldoc.perl.org/perlsyn.html#Statement-Modifiers

Hm, 'open(FOO) ? () : die "Can't open $FOO: $!";' is kinda cute :)

> Also, please don't use the ternary conditional operator for side-effects, see:
>
> http://perl-begin.org/tutorials/bad-elements/#ternary_operator_instead_of_if_else

What is considered as 'side effects'?  Should one use it without effects?

>> So how about:
>> 
>> 
>> {
>>   print "123\n";
>>   print "456\n";
>> } if $color eq "blue";
>> 
>> 
>> That doesn't compile, so this preappended 'if' is like implemented only
>> half way in both directions :/
>
> A trailing if applies only to one statement (by design).

That's inconsistent design since statements in such brackets are
effectively one statement ...

> You can use:
>
> do {
>       print "123\n";
>       print "456\n";
> } if $color eq "blue";
>
> but in this case I believe a normal conditional with the condition at the
> beginning would be preferable.

I agree --- the whole concept of syntactically appending stuff that is
logically prefixed seems a bit questionable.  But then, nobody forces
anyone to use it.


-- 
"Object-oriented programming languages aren't completely convinced that
you should be allowed to do anything with functions."
http://www.joelonsoftware.com/items/2006/08/01.html

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to