Hello Lee,

On Mon, 24 Jun 2013 07:36:26 +0200
lee <l...@yun.yagibdah.de> wrote:

> 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'?
> 

How so?

last MYLABEL if $x == 5;

does exactly the same as:

if ($x == 5) {
        last MYLABEL;
}

Similarly:

print "Hello\n" if $x == 5;

does exactly the same as:

if ($x == 5) {
        print "Hello\n";
}

Where do you see that last is treated different by if?

> >> > 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.

Well, I don't understand you here.

> 
> 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.

How so?

> 
> 
> [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?

I just gave you one. I had:

for ( LOOP() )
{
        for (OTHER_LOOP() )
        {
                x = LOOKUP_BASED_ON_OTHER_LOOP();
                .
                .
                .
                if ( COND1() )
                {
                        continue OTHER_LOOP;
                }
                .
                .
                .
                if ( COND2() )
                {
                        continue OTHER_LOOP;
                }

                PRODUCTION_STUFF_HERE()
                
        }
}

And it became:

for ( LOOP() )
{
        x = LOOKUP_BASED_ON_LOOKUP_TABLE();
        .
        .
        .
        if ( COND1() )
        {
                continue OTHER_LOOP;
        }
        .
        .
        .
        if ( COND2() )
        {
                continue OTHER_LOOP;
        }

        PRODUCTION_STUFF_HERE()
}

Only in this case, continue was a standalone keyword and I didn't see that
OTHER_LOOP disappeared and so it did it for the main «for ( LOOP() )»

> 
> >> 
> >> 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.

The code:

[CODE]
print "Hello" if ($foo) {
        print $bar;
}
else {
        print $test;
}
[/CODE]

Won't work either. last is not special in the treatment of a trailing if
statement modifier - you can put any single statement you want there.

> 
> >> 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 :)
> 

See:

http://perl-begin.org/tutorials/bad-elements/#open-function-style (a link of a
site I maintain).

> > 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?

Well, in general the ternary operator should be used to return either of two
values (to an assignment, or the return value of a subroutine), not call
function such as print, or do assignment itself, which is better reserved for
if/else.

> 
> >> 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 ...

Not in Perl 5, where they are considered a block. Perl 6 is a different matter.

> 
> > 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.

Yes. My personal style is to usually avoid statement modifiers, except in
command line one-liners/etc. 

Regards,

        Shlomi Fish

-- 
-----------------------------------------------------------------
Shlomi Fish       http://www.shlomifish.org/
Parody of "The Fountainhead" - http://shlom.in/towtf

The apple completely supplanted the tree.
    — http://www.shlomifish.org/humour/Summerschool-at-the-NSA/

Please reply to list if it's a mailing list post - http://shlom.in/reply .

--
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