[Python-Dev] Simple Switch statement

Ron Adam rrr at ronadam.com
Sun Jun 25 04:06:33 CEST 2006


Raymond Hettinger wrote:
>>From what I can see, almost everyone wants a switch statement, though perhaps 
> for different reasons.
> 
> The main points of contention are 1) a non-ambiguous syntax for assigning 
> multiple cases to a single block of code, 2) how to compile variables as 
> constants in a case statement, and 3) handling overlapping cases.
> 
> Here's a simple approach that will provide most of the benefit without trying to 
> overdo it:

Looks good to me.


>     switch f(x):          # any expression is allowable here but raises an 
> exception if the result is not hashable
>     case 1: g()           # matches when f(x)==1
>     case 2,3 : h()        # matches when f(x) in (2,3)
>     case 1: i()           # won't ever match because the first case 1 wins
>     case (4,5), 6: j()    # matches when f(x) in ((4,5), 6)
>     case "bingo": k()     # matches when f(x) in ("bingo",)
>     default:   l()        # matches if nothing else does
> 
> Though implemented as a hash table, this would execute as if written:
> 
>     fx = f(x)
>     hash(fx)
>     if fx in (1,):
>         g()
>     elif fx in (2,3):
>         h()
>     elif fx in (1,):
>         i()
>     elif fx in ((4,5), 6):
>         j()
>     elif fx in ("bingo",):
>         k()
>     else:
>         l()
> 
> The result of f(x) should be hashable or an exception is raised.
> Cases values must be ints, strings, or tuples of ints or strings.
> No expressions are allowed in cases.
> Since a hash table is used, the fx value must support __hash__ and __eq__,
> but not expect multiple __eq__ tests as in the elif version.
> 
> I've bypassed the constantification issue.  The comes-up throughout Python
> and is not unique to the switch statement.  If someone wants a "static" or
> "const" declaration, it should be evaluated separately on its own merits.

Yes, I agree.


> When the constants are mapped to integers instead of strings, it is no
> burden to supply a reverse mapping like we already do in opcode.py.
> This commonplace setup also makes it easy to write fast switch-case suites:
> 
>     from opcode import opmap
> 
>     def calc_jump_statistics(f):
>         reljumps = absjumps = 0
>         for opcode, oparg in gencodes(f.func_code.co_code):
>             switch opmap[opcode]:
>                 case 'JUMP_FORWARD', 'JUMP_IF_FALSE', 'JUMP_IF_TRUE':
>                     reljumps +=1
>                 case 'JUMP_ABSOLUTE', 'CONTINUE_LOOP':
>                     absjumps += 1
>                   . . .
> 
> So, that is it, my proposal for simple switch statements with a straight-forward
> implementation, fast execution, simply explained behavior, and applicability to
> to the most important use cases.

Just what I was looking for! +1

I happen to like simple modular code that when combined is more than 
either alone, which I believe is the case here when using mappings with 
switches.  This type of synergy is common in python and I have no 
problem using a separate lookup map to do early and/or more complex 
evaluations for cases.

Cheers,
    Ron



> Raymond
> 
> 
> P.S. For the sre case, we get a great benefit from using strings.  Since they 
> are
> all interned at compile time and have their hash values computed no more than
> once, the dispatch table will never have to actually calculate a hash and the
> full string comparison will be bypassed because "identity implies equality".
> That's nice.  The code will execute clean and fast.  AND we get readability
> improvements too.  Not bad.




More information about the Python-Dev mailing list