http://qs321.pair.com?node_id=608788

Just downloaded 5.9.4 and love the new switch statement (especially the smart matching that comes with it). A notable difference from C traditions is that you do not need to break out of the block to avoid falling through to the next </code>case</code>.
given($data) { when (1) { say 'one' ; }; ## no "break" needed when (2) { say 'two' ; }; default { say 'something else'; }; }
The Perldoc states that you can still fall through to the next when using continue. It should probably point out that this is fundamentally different from falling through in C, because the following condition(s) are still being checked.
# this code does not work ! # it will say "something else" given($data) { when (1) { continue; }; when (2) { say 'one or two' ; }; default { say 'something else'; }; }
Of course, above example makes not much sense, but a straight port from C code would probably end up like that. The Perl way to write it (using smart matching) is more like
# this works, is shorter and easier to read given($data) { when ([ 1, 2]) { say 'one or two' ; }; default { say 'something else'; }; }
The Imp of the Perverse still wonders if it is possible to directly "goto" (maybe that's a hint right there...) the next block, skipping the when check.

Replies are listed 'Best First'.
Re: Falling through Perl 5.10 switch statement
by betterworld (Curate) on Apr 07, 2007 at 15:03 UTC
    The Imp of the Perverse still wonders if it is possible to directly "goto" (maybe that's a hint right there...) the next block, skipping the when check.

    Well, goto itself won't work in my perl 5.9.4:

    use feature qw(say switch); my $data = 1; given($data) { when (1) { say 'one'; goto two; } when (2) { two: say 'two' ; } default { say 'something else'; } }

    This prints:

    one panic: goto at /tmp/test line 5.

    Interesting error message though.

      Thats because your trying to goto a block that looks like it would be optimized out of existance. Since $data is a constant the optimizer components that look at switches are probably smart enough to notice that only the when (1) case will run and will replace the whole switch in the op tree with simply say 'one'; goto two;.

      Disclaimer: I don't claim to have intimate knowledge of how switches are implemented in the optree or how the optimizer treats them. Take this explanation with a grain of salt, it may sound good, but it may also be flat out wrong.

        I'd maybe buy your argument if the code was

        given (1)

        but I've never known perl to optimize lexicals away, even if those who always hold the same constant value. The following two optrees should be identical if perl optimized constant lexicals away:

        >perl -MO=Concise -e"my $data = 1; print $data;" a <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v ->3 5 <2> sassign vKS/2 ->6 3 <$> const[IV 1] s ->4 4 <0> padsv[$data:1,2] sRM*/LVINTRO ->5 6 <;> nextstate(main 2 -e:1) v ->7 9 <@> print vK ->a 7 <0> pushmark s ->8 8 <0> padsv[$data:1,2] l ->9 <-- It uses the lexical, -e syntax OK not a constant. >perl -MO=Concise -e"print 1;" 6 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v ->3 5 <@> print vK ->6 3 <0> pushmark s ->4 4 <$> const[IV 1] s ->5 <-- This is a constant. -e syntax OK

        Perl 5.8.8

        Update: Here's another example using code more similar to the OP's:

        >perl -MO=Concise -e"my $data = 1; if ($data) { print 'moo' }" c <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v ->3 5 <2> sassign vKS/2 ->6 3 <$> const[IV 1] s ->4 4 <0> padsv[$data:1,4] sRM*/LVINTRO ->5 6 <;> nextstate(main 4 -e:1) v ->7 - <1> null vK/1 ->c 8 <|> and(other->9) vK/1 ->c <-- "if" not optimized away. 7 <0> padsv[$data:1,4] s ->8 <-- Lex not optimized away. - <@> scope vK ->- - <0> ex-nextstate v ->9 b <@> print vK ->c 9 <0> pushmark s ->a a <$> const[PV "moo"] s ->b -e syntax OK >perl -MO=Concise -e"if (1) { print 'moo' }" 6 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 3 -e:1) v ->3 - <@> scope vK ->6 <-- "if" optimized away. - <0> ex-nextstate v ->3 5 <@> print vK ->6 3 <0> pushmark s ->4 4 <$> const[PV "moo"] s ->5 -e syntax OK
        Thats because your trying to goto a block that looks like it would be optimized out of existance.
        That sounds like a nice explanation; however, the following script panics with the same message if there is a "1" in the command line:
        use feature qw(say switch); for my $data (@ARGV) { given($data) { when (1) { say 'one'; goto two; } when (2) { two: say 'two' ; } default { say 'something else'; } } }
      Still a problem in bleadperl @ 30869.
        Time to rollback :p