<?xml version="1.0" encoding="windows-1252"?>
<node id="709120" title="Perl 5.10 given/when tricks and caveats" created="2008-09-04 17:08:56" updated="2008-09-04 13:08:56">
<type id="120">
perlmeditation</type>
<author id="62512">
mr_mischief</author>
<data>
<field name="doctext">
In [doc://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:

&lt;c&gt;
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' }
}
&lt;/c&gt;

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.

&lt;p&gt;
&lt;readmore&gt;
That means this Perl code:

&lt;c&gt;#!/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;
&lt;/c&gt;

which prints:

&lt;c&gt;
1:
2:
3:
4:
5:
&lt;/c&gt;


is not equivalent to this C code:

&lt;c&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

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 );
}
&lt;/c&gt;
which prints:

&lt;c&gt;
1: 4
2:
3:
4:
5:
&lt;/c&gt;
&lt;/readmore&gt;

&lt;p&gt;
However, it means you can do neat tricks like this:

&lt;c&gt;#!/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';
&lt;/c&gt;

which prints:

&lt;c&gt;
Just another Perl hacker: Me too!
Just another Perl slacker:
&lt;/c&gt;

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.

&lt;p&gt;
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 [doc://perlsyn] the value &lt;c&gt;x&lt;/c&gt; for &lt;c&gt;$foo&lt;/c&gt;, and you get:

&lt;c&gt;
$foo contains an x
$foo contains neither an x nor a y
&lt;/c&gt;

... which makes very little sense.
</field>
</data>
</node>
