[Python-Dev] switch-based programming in Python
M.-A. Lemburg
mal@lemburg.com
Thu, 08 Nov 2001 16:45:07 +0100
Thomas Wouters wrote:
>
> On Thu, Nov 08, 2001 at 12:32:39PM +0100, M.-A. Lemburg wrote:
> > Thomas Wouters wrote:
>
> > > Would a lengthy if/elif/elif/else construct work better ? Why ?
>
> > Yes, because it doesn't involve calling methods, no execution
> > frames have to be setup, no arguments need to be passed in,
> > state can be managed in local variables, etc.
>
> > > 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.
>
> > You don't ?
>
> Is that sarcasm ? :) No, I don't. My actual job, the part I get paid for,
> doesn't (yet) involve writing Python. It's part C and Perl, part system
> design, and part administration. So Python is just a hobby.
You should change that ;-)
BTW, how did you get XS4ALL into funding the www.python.org traffic,
if they don't heavily depend on Python ?
> > > 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.
>
> > That's the idea.
>
> > There's enough need in it for my applications, so I'd go through
> > the trouble of writing the code for it, provided I get the OK
> > and help from python-dev.
>
> The writing part would be very tricky. I don't think you can do it without
> syntax support, at least not reliably, even if 'without syntax support' is
> some kind of directive statement to signal that a particulare
> if/elif/elif/else chain should be converted to a jump table behind the
> scene.
Well, I tried to avoid syntax changes for two reasons:
1. new keywords are a problem (even though I like your proposed syntax
very much)
2. old code should be able to benefit from the new feature
I think that Skip's proposal would go a long way (sketching here
a bit):
It should be possible for the compiler to detect an if-elif-else
construct which has the following signature:
if x == 'first':...
elif x == 'second':...
else:...
(ie. LHS always the same variable, RHS some hashable immutable
builtin type)
The compiler could then setup a perfect hash table, store it
in the constants and add some opcode which triggers the following
run-time behaviour:
At runtime, the interpreter would check x for being one of the
well-known immutable types (strings, unicode, numbers) and
use the hash table for finding the right opcode snippet.
> For new syntax, I'd imagine something like this:
>
> switch EXPR:
> case CONSTANT:
> [suite]
> case CONSTANT:
> [suite]
> ...
> else:
>
> EXPR is a normal Python expression. CONSTANT should be a hashable constant
> (with a persistant hash value, duh) so we don't have to re-hash all the
> cases when entering the switch. The 'else' would function like a 'default:'
> case in C's switch. I'm not sure on the naming of 'switch' and 'case', nor
> about the indentation-level of the 'cases'. And what to do about
> fallthrough? It's commonly accepted (or at least argued :) as a design flaw
> that C's switch() defaults to fallthrough. Bytecodewise it should probably
> turn something like:
I think you missed some indents in your example. I added them again,
removing the parens around x and tweaked the formatting a bit (also
note the addition of a few breaks).
def whatis(x):
switch x:
case 'one':
print '1'
break
case 'two':
print '2'
# fall through
case 'three':
print '3'
break
else:
print "D'oh!"
Turns out that this look very Pythonic :-)
> Into (ommitting POP_TOP's and SET_LINENO's):
>
> 6 LOAD_FAST 0 (x)
> 9 LOAD_CONST 1 (switch-table-1)
> 12 SWITCH 26 (to 38) # or maybe 'SWITCH <table-index>'
>
> 14 LOAD_CONST 2 ('1')
> 17 PRINT_ITEM
> 18 PRINT_NEWLINE
> 19 JUMP 43
>
> 22 LOAD_CONST 3 ('2')
> 25 PRINT_ITEM
> 26 PRINT_NEWLINE
> 27 JUMP 43
>
> 30 LOAD_CONST 4 ('3')
> 33 PRINT_ITEM
> 34 PRINT_NEWLINE
> 35 JUMP 43
>
> 38 LOAD_CONST 5 ("D'oh!")
> 41 PRINT_ITEM
> 42 PRINT_NEWLINE
>
> >>43 LOAD_CONST 0 (None)
> 46 RETURN_VALUE
>
> Where the 'SWITCH' opcode would jump to 14, 22, 30 or 38 depending on 'x'.
> PEP, anyone ? :)
Sure smells like PEP-time :-)
If I get some more positive feedback on this, I'll start
looking into this.
--
Marc-Andre Lemburg
CEO eGenix.com Software GmbH
______________________________________________________________________
Consulting & Company: http://www.egenix.com/
Python Software: http://www.lemburg.com/python/