[Python-Dev] Split switch statement

Eric Sumner kd5bjo at gmail.com
Tue Jun 27 22:36:43 CEST 2006


One of the big problems here seems to be that an optimized switch
statement requires some code to be evaluated fewer times than the rest
of the switch statement, and there isn't any good way to make that
happen with a single statement.  Thus, I propose two statements: a
'dispatcher' statement and a 'switch' statement.  The dispatcher
statement defines the available cases, and generates a dispatcher
object, and the switch statement specifies code to be run for each
case.

---------

#Sample 1: Primary dispatcher syntax
dispatcher myEvents on e:
    on e:
         case None: Idle
     on getattr(e, 'type', None):
         from globalEvents: *
         case 42: myEvent      # or whatever the user event code is
#EOF

A dispatcher statement contains a sequence of 'on' blocks.  Each 'on'
block specifies an expression and a set of cases.  The expression is
stored as a lambda inside the dispatcher which is applied whenever the
switch is run.  Inside a 'on' block, there are two kinds of
statements.  'case' evaluates its expression immediately, and
associates it with a label; 'from' imports tests and labels from
another dispatcher.  If the result of any case expression is
unhashable, an exception is raised.

----------

#Sample 2: Shorthand dispatcher syntax
dispatcher globalEvents:
    case pygame.KEYDOWN: KEYDOWN
    case pygame.KEYUP:   KEYUP
    ...
#EOF

Because dispatching on the switched value directly is so common, any
'from' or 'case' statements outside an 'on' block are considered to be
applied to be inside an "on <switched_value>" block.  The name for the
switched value can be omitted if it's not needed.

----------
#Sample 3: Using a dispatcher
while True:
    ...
    switch events on pygame.event.poll():
    case KEYUP, KEYDOWN: ...
    case myEvent: ...
    case Idle: ...
    else: ...
#EOF

Internally, each switch statement has some unique identifier.  Each
dispatcher object maintains a list of the switch statements it has
previously serviced.  If this switch statement is new to this
dispatcher, the dispatcher verifies that it might generate all of the
cases that are specified in the switch.  Otherwise, an exception is
raised.

If the test passed (or was skipped due to previous experience), each
of the 'on' expressions in the dispatcher is executed (in order) and
their results are checked against the stored values.  If no case (from
the switch, not the dispatcher) matches, the switch's 'else' block is
executed, if present.  If more than one case (from the switch)
matches, an exception is raised.  Otherwise, the code from associated
case block is executed.

  -- Eric Sumner

PS. Yes, I know that's not how pygame handles idle events; it makes a
better sample this way.


More information about the Python-Dev mailing list