Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re^4: fall through switch/case in perl

by etcshadow (Priest)
on Sep 07, 2004 at 02:52 UTC ( [id://388915]=note: print w/replies, xml ) Need Help??


in reply to Re^3: fall through switch/case in perl
in thread fall through switch/case in perl

The eval is necessary if you want to fully emulate the C semantic of not dieing if there is no matching case. Really, the full-on computed goto method (I should have just written this into my top-level response) is this (I think):
{ eval { goto "CASE$var" } or goto DEFAULT; CASE10: print "a"; CASE9: print "b"; CASE8: print "c"; CASE7: print "d"; CASE6: print "e"; CASE5: print "f"; CASE4: print "g"; CASE3: print "h"; CASE2: print "i"; CASE1: print "j"; DEFAULT: }
Which, admittedly, is not very different from Aristotle's. The only real difference being the outter braces. The purpose of them is to avoid polluting the label name-space. (Also, I prefer the "goto X or goto DEFAULT" over the "goto X; goto DEFAULT" purely for aesthetic reasons. :-D)

I sort of wonder why this isn't given as one of the ways of achieving C-like switch statement behavior in the perl docs? Oh, well... it's probably horribly inefficient or something (apart from just being too C-ish or something).

------------ :Wq Not an editor command: Wq

Replies are listed 'Best First'.
Re^5: fall through switch/case in perl
by BrowserUk (Patriarch) on Sep 07, 2004 at 04:10 UTC

    Hmm. I think what your saying is that the eval is necessary to avoid a warning if $var doesn't contain a value for which there is a label defined?

    If so, then it still doesn't handle the case where $var is undefined.

    That can be handled by using a do BLOCK construct to disable warnings and adding a CASE0:

    for my $var ( undef, 1 .. 10, 'fred' ) { goto 'CASE' . do{ local $^W; $var + 0 }; CASE10: print "a"; CASE9: print "b"; CASE8: print "c"; CASE7: print "d"; CASE6: print "e"; CASE5: print "f"; CASE4: print "g"; CASE3: print "h"; CASE2: print "i"; CASE1: print "j"; print "\n"; CASE0: }
    I sort of wonder why this isn't given as one of the ways of achieving C-like switch statement behavior in the perl docs? Oh, well... it's probably horribly inefficient or something (apart from just being to C-ish or something).

    C-ish it may be (though that's not a good reason in my book if it is clearer), but inefficient it is not:

    P:\test>388915 ?> 1..10 Testing for vals [1..10] Rate if_cascade and_cascade goto_do goto_eval + goto if_cascade 11395/s -- -2% -11% -26% + -26% and_cascade 11627/s 2% -- -9% -24% + -25% goto_do 12845/s 13% 10% -- -17% + -17% goto_eval 15389/s 35% 32% 20% -- + -0% goto 15423/s 35% 33% 20% 0% + -- ?>

    Benchmark/results


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
      Hmm. I think what your saying is that the eval is necessary to avoid a warning if $var doesn't contain a value for which there is a label defined?
      No, I'm saying that goto $label dies if the label has not been defined. That is not how it works in C. In C, if you have not provided a case that matches your switch value, it jumps to the default case. That's why there's an eval, to prevent the die (not warning).
      [sstone@granite sstone]$ perl -le 'print 1; goto "FOO"; print 2' 1 Can't find label FOO at -e line 1. [sstone@granite sstone]$
      As far as preventing a warning on undef, well... I'd imagine that that should fit into whatever scheme you are using around undefs: warn if you have undef warnings on, else not. And there's nothing about stringifying $var that changes that semantic, so all seems well and good with my method.
      ------------ :Wq Not an editor command: Wq

        Fair enough, but in TimToady's original, he had 'CASE'.($var+0) which avoids dieing.

        P:\test>perl -le" print 1; $var = 'foo'; goto 'CASE'.($var+0); CASE0: +print 2;" 1 2

        And that allows CASE0: to become the default.

        The only situation this doesn't cover is when $var is undef'd; but then none of the other solutions handle that (except the do{ local $^W; $var + 0 }; I suggested).


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
        goto qw [CASE1 CASE2 CASE3 CASE4 CASE5 CASE6 CASE7 CASE8 CASE9 CASE10] [$var - 1] || "default"; CASE10: print "a"; CASE9: print "b"; CASE8: print "c"; CASE7: print "d"; CASE6: print "e"; CASE5: print "f"; CASE4: print "g"; CASE3: print "h"; CASE2: print "i"; CASE1: print "j"; print "\n"; default:

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://388915]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (8)
As of 2024-04-19 08:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found