[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