Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Perl 5.10 given/when tricks and caveats

by mr_mischief (Monsignor)
on Sep 04, 2008 at 21:08 UTC ( #709120=perlmeditation: print w/replies, xml ) Need Help??

In perlsyn you can find the words 'You can use the "continue" keyword to fall through from one case to the next'. You can also find this example:
given($foo) { when (/x/) { say '$foo contains an x'; continue } when (/y/) { say '$foo contains a y' } default { say '$foo contains neither an x nor a y' } }
Now, I'm not primarily a C programmer, but what I took "fall through" to mean is not what happens there. The "continue" doesn't skip the implicit break in the case, but means to actually continue testing cases.

That means this Perl code:
#!/usr/local/bin/perl use feature qw{ switch }; use strict; use warnings; sub match { my $i = 0; my $foo = shift; given ( $foo ) { when ( 1 ) { $i++; continue; } when ( 2 ) { $i++; continue; } when ( 3 ) { $i++; continue; } when ( 4 ) { $i++; } } print "$foo: "; print "4!" if 4 == $i; print "\n"; } match 1; match 2; match 3; match 4; match 5;
which prints:
1: 2: 3: 4: 5:
is not equivalent to this C code:
#include <stdio.h> #include <stdlib.h> int match ( int foo ) { int i = 0; printf( "%d: ", foo ); switch ( foo ) { case 1: i++; case 2: i++; case 3: i++; case 4: i++; break; } if ( 4 == i ) { printf( "4" ); } printf( "\n" ); } int main ( int argc, const char **argv ) { match( 1 ); match( 2 ); match( 3 ); match( 4 ); match( 5 ); exit( 0 ); }
which prints:
1: 4 2: 3: 4: 5:

However, it means you can do neat tricks like this:

#!/usr/local/bin/perl use feature qw{ switch }; use strict; use warnings; sub match { my $i = 0; my $foo = shift; print $foo . ': '; given ( $foo ) { when ( /^Just / ) { $i++; continue; } when ( /another / ) { $i++; continue; } when ( /[Pp]erl / ) { $i++; continue; } when ( /hacker\.?$/ ) { $i++; } } print 'Me too!' if 4 == $i; print "\n"; } match 'Just another Perl hacker'; match 'Just another Perl slacker';
which prints:
Just another Perl hacker: Me too! Just another Perl slacker:
So don't forget that you'll have to give up a little bit of convenience you might be used to with straight fall through. Happily, though, you end up with a good deal more convenience by being able to restart the switch and having the smart match applied again to the remaining cases.

Unfortunately, this feature of continuing through the tests and having a default in the same switch statement are not really that smart a combination. Try giving that example from perlsyn the value x for $foo, and you get:

$foo contains an x $foo contains neither an x nor a y
... which makes very little sense.

Replies are listed 'Best First'.
Re: Perl 5.10 given/when tricks and caveats
by sasdrtx (Friar) on Sep 05, 2008 at 00:40 UTC
    I think your first example would be more useful if you just printed the value of $i on every iteration. I don't have perl 5.10 handy myself.

    This does seem like odd behavior. No switch/select I'm familiar with (I admit that's not many) tries to match multiple cases/whens. Obviously in C the limitations of case tests to simple constants would make that behavior silly.

    A switch group is generally used as a prettier form of a series of if/elsif/.../else statements. The Perl implementation of continue seems to just change the next elsif to a plain if. And in that case, why not just use a plain if?

    I'd like to see an example of how this behavior was expected to be used.


      The real trick is that C's switch statement can be compiled down to a jump table in the assembly, which is the main reason it's so constrained. We had a discussion on this a long while back.

      "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

      You may be right about the presentation of that example. I arrived at the code showing the differences through a bit of a convoluted process. I was playing with the differences in a few directions for myself to decide just what to show. I think the code I posted before shows as much about that process as about the resulting idea for the post. Hopefully your idea presents it more clearly to those of you whose voices are outside my head. ;-)

      Here's the new C and Perl code and their output:

      Perl code:

      C code:

      And here's the new output for the Perl:

      1: 1 2: 1 3: 1 4: 1 5: 0
      And the C:
      1: 4 2: 3 3: 2 4: 1 5: 0
Re: Perl 5.10 given/when tricks and caveats
by pjf (Curate) on Sep 08, 2008 at 07:56 UTC
    $foo contains an x $foo contains neither an x nor a y

    ... which makes very little sense.

    That particular piece of documentation in perlsyn is wrong, and is corrected by patch 33488 which will be included in Perl 5.10.1.

      Thanks for submitting that to the list and for pointing it out here.

      The continue still means that the default cannot be used to say that there is no 'x'. This possible in C and most other languages with 'fall through' semantics for switch statements. Perhaps the 'fall through' portion needs to be clarified rather than just tweaking the example code.

      Clearing up the misleading code sample is one thing, but actually making it clear why the default case cannot say anything at all about the case that is continued is another.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://709120]
Approved by moritz
Front-paged by moritz
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2017-08-18 00:26 GMT
Find Nodes?
    Voting Booth?
    Who is your favorite scientist and why?

    Results (294 votes). Check out past polls.