in reply to Eek! goto?

There is a module that emultates switch on CPAN. However, the equivalent would be something like:
if ($len == 11) { $c+= $k[10]<<24; }elseif ($len == 10) { $c+= $k[9]<<16; } elseif ...

Replies are listed 'Best First'.
Re: Re: Eek! goto?
by pfaut (Priest) on Feb 11, 2003 at 23:57 UTC

    This isn't the same thing as the base node. There were no breaks inside the switch so it would keep falling through from the matched value to the bottom. Yours would be right if there were a break after each statement.

    --- print map { my ($m)=1<<hex($_)&11?' ':''; $m.=substr('AHJPacehklnorstu',hex($_),1) } split //,'2fde0abe76c36c914586c';
      Point taken. I guess there is a reason I stick with Perl: my C always did suck.

        Not just your C; C sucks in general. As a case in point, the C case statement is next-to-worthless, because fallthrough is not usually what you want. There are cases for it, but they're the exception rather than the rule. As a result, you end up needing to insert break statements at nearly every case, at which point you have barely less typing to do than with a nested if structure. Perl's elsif is actually an improvement on this.

        The case statement in Inform (and even SELECT CASE in BASIC) is much more useful. If Perl ever gets a case, I hope the breaks are implied; otherwise I'll end up never using it.

        Most of the cases where you want the fallthrough, it's because what you want is actually not a case statement, but some other structure. This is a perfect example. What it's doing is not really unique to each case; there are some minor variations, but what you really want is a loop.

        Others have done efficient things (and I particularly like the pack solution), but I'll add my own translation, on the grounds that it is straightforward and legible...

        { my @shiftby = (0, 8, 16, 24, 0, 8, 16, 24, 8, 16, 24); my $l; foreach $l (reverse 1 .. $len) { if ($l>8) { $c += $k[$l-1]<<$shiftby[$l]; } elsif ($l>4) { $b += $k[$l-1]<<$shiftby[$l]; } else { $a += $k[$l-1]<<$shiftby[$l]; } } }

        I've reduced the number of += operations to three, and it is easy to see where the similarities and the differences are. The if/elsif/else makes it stand out when you are incrementing a different variable. (When I first looked at the thing, I thought the same variable was being incremented ten times.) Even better, it is clear how @k is being used; before, you had to look at each line and compare the index to @k with the case number, if you wanted to know if there were any deviations from the pattern; here it's clear there are none; $l-1 is always $l-1.

        @shiftby could probably also be replaced with an arithmetic expression, but I'm not sure that would improve clarity.

         --jonadab

      Which is exactly why the original goto suggestion is about the only one that works and is concise enough to read. I don't see any other obvious ones. I'd often hash something like this but that wouldn't allow for easy emulation of the fall throughs in the C code.