[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,
MyFunc.lower,
MyFunc.upper, # Yes, 2 and 3 are the same as 0 and 1
MyFunc.lower,
MyFunc.control,
MyFunc.digit,
]
(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