[Python-Dev] switch-based programming in Python

Thomas Wouters thomas@xs4all.net
Thu, 8 Nov 2001 16:24:25 +0100


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.

> > 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.

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:

  def whatis(x):
      switch(x):
      case 'one': print '1'
      case 'two': print '2'
      case 'three': print '3'
      else: print "D'oh!"

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 ? :)

-- 
Thomas Wouters <thomas@xs4all.net>

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