[Python-Dev] PEP 3103: A Switch/Case Statement

Talin talin at acm.org
Wed Jun 28 10:04:31 CEST 2006

Josiah Carlson wrote:
> Talin <talin at acm.org> wrote:
>>My version of this is to add to Python the notion of a simple 
>>old-fashioned subroutine - that is, a function with no arguments and no 
>>additional scope, which can be referred to by name. For example:
> I don't like the idea of an embedded subrutine for a few reasons.  One
> of them is because you need to define the case -> sub mapping
> dictionaries in each pass, you are getting no improvement in speed
> (which is a motivating factor in this discussion).  Even worse, the
> disconnect between case definition and dispatch makes it feel quite a
> bit like a modified label/goto proposal.  The ultimate killer is that
> your proposed syntax (even using def) make this construct less readable
> than pretty much any if/elif/else chain I have ever seen.
>  - Josiah

The case -> sub mapping doesn't need to be defined every time - that's 
the point, you as the programmer decide when and how to construct the 
dictionary, rather than the language trying to guess what it is you 
want. EIBTI.

For example, if I wanted to emulate the "dict on first use" semantics, 
all I would have to do is something along the lines of:

    d = None
    def MyFunc( x ):
       global d

       sub ... etc...

       if d is None:
          d = dict( ... )

       do d[ x ]

You could also define the switch in an outer function that contains an 
inner function that is called multiple times:

    def Outer():
       sub S1:

       sub S2:

       sub S3:

       dispatch = {
          parser.IDENT: S1,
          parser.NUMBER: S2,
          parser.COMMENT: S3

       def Inner( x ):
          do dispatch[ x ]

       return Inner

There is also the possibility of building the dict before the function 
is run, however this requires a method of peeking into the function body 
and extracting the definitions there. For example, suppose the 
subroutine names were also attributes of the function object:

    def MyFunc( x ):
       sub upper:
       sub lower:
       sub control:
       sub digit:

       do dispatch[ x ]

    # Lets use an array this time, for variety
    dispatch = [
       MyFunc.upper, # Yes, 2 and 3 are the same as 0 and 1

(Note that we still enforce the rule that the 'do' and the 'sub' 
statements have to be in the same scope - but the construction of the 
dispatch table doesn't have to be.)

With regards to your second and third points: sure, I freely admit that 
this proposal is less readable than a switch statement. The question is, 
however, is it more readable than what we have *now*? As I have 
explained, comparing it to if/elif/else chains is unfair, because they 
don't have equivalent performance. The real question is, is it more 
readable than, say, a dictionary of references to individual functions; 
and I think that there are a number of possible use cases where the 
answer would be 'yes'.

I also admit that what I propose offers less in the way of syntactical 
sugar than a switch statement - but in return what you gain is complete 
absence of the various 'surprise' behaviors that people have been 
arguing about.

Note, for example, that in the above example you are free to use 
constants, variables, attributes, or any other kind of value in the 
dictionary, as long as its a valid dictionary key. There's no fussing 
about with 'const' or 'static' or whether or not you can use local 
variables or compiler literals or whatever. You don't have to worry 
about whether it works in module scope (it does), or in class scope 
(well...it works as well as any other executable code does.)

(Not that 'const' and 'static' et all aren't valid ideas, but I want to 
avoid creating a syntactical construct in Python that requires going 
against Python's inherent dynamism.)

I think that language features should "just work" in all cases, or at 
least all cases that are reasonable. I don't like the idea of a switch 
statement that is hedged around with unintuitive exceptions and strange 
corner cases.

-- Talin

More information about the Python-Dev mailing list