[Python-Dev] switch-based programming in Python

Thomas Wouters thomas@xs4all.net
Thu, 8 Nov 2001 11:50:18 +0100


On Wed, Nov 07, 2001 at 04:23:32PM +0100, M.-A. Lemburg wrote:

> Currently, dispatching of execution based on the value of
> one variable is usually implemented by having some dictionary
> of possible values and then calling method which implement the
> different branches of execution. This works well for code which
> uses medium sized methods, but fails badly for small ones such
> as code which is often used in method callback based parsers.

Why does it not work well for small-sized methods ? And how do you define
'well' ? Would a lengthy if/elif/elif/else construct work better ? Why ? And
if not, what _would_ work better ? Or did you mean 'small numbers of
methods' ?

> The alternative is using lengthy 
> 	if x == 'one': ...
>       elif x == 'two': ...
>       elif x == 'three': ...
>       else: ...default case...
> constructs.

> Wouldn't it make sense to enable the byte code compiler to take 
> the above construct and turn it into a dictionary based 
> switch statement ?

Frankly, no, it wouldn't make sense. Not only do we not know the type of 'x'
at compile time, but we also don't know how often 'x' changes type when you
start comparing it with any kind of object. What _might_ work is something
like:

x_key = str(x)
if x == 'one': ...
[etc]

But that would require a type inference mechanism first, and a
is-str-being-masked-or-has-builtins-been-modified check. I think your best
bet for adding those is in an external (python-written) bytecode-optimizer
with complicated flow analysis.

If the problem with dict-based switches is the clumsiness of declaration,
maybe something like this would improve matters:

   disp = dispatcher.dispatcher(
	one=lambda x: ...
	two=lambda x: ...
	three=lambda x: ...
	four=func_for_four
	five=lambda: pass)

   disp.dispatch(x)

Or maybe you'd prefer using strings containing code fragments and exec'ing
them. I'm not sure what you want the if/else to actually do. Personally, I
either need a function call in there (in which case a dispatch table calling
the function directly, sometimes with apply() or lambda-wrapper tricks, does
fine) or some kind of variable assignment, in which case a simple dict
lookup works just as fine. Then again, I don't write that much Python code.

> I'm not talking about adding syntax to the language, it would
> just be nice to have the compiler recognize this kind of code
> (somehow; perhaps with some extra help) and produce optimized
> code for it, possibly using new opcodes for the switching 
> operation.

I personally wouldn't be adverse to a switch-like syntax, as long as we
define it like a dict dispatch (the argument is evaluated once, it should be
hashable, and all the 'cases' should be hashable -- preferably even
compile-time constants.) I like the idea, I'm just not sure if there's
enough use for it. 

-- 
Thomas Wouters <thomas@xs4all.net>

Hi! I'm a .signature virus! copy me into your .signature file to help me spread!