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

Ron Adam rrr at ronadam.com
Tue Jun 27 20:54:09 CEST 2006

Guido van Rossum wrote:
> On 6/27/06, Ron Adam <rrr at ronadam.com> wrote:
>> I use dict base dispatching in a number of my programs and like it with
>> the exception I need to first define all the code in functions (or use
>> lambda) even if they are only one line.  So it results in a three step
>> process, define functions,  define dict,  and then call it.  And I need
>> to make sure all the function calls use the same calling signature. In
>> some cases I'm passing variables that one function doesn't need because
>> it is needed in one of the other cases.
>> So modeling the switch after dictionary dispatching more directly where
>> the switch is explicitly defined first and then used later might be good
>> both because it offers reuse in the current scope and it can easily be
>> used in code that currently uses dict style dispatching.
>>     switch name:
>>        1:
>>           ...
>>        TWO:
>>           ...
>>        'a', 'b', 'c':
>>           ...
>>        in range(5,10):
>>           ...
>>        else:
>>           ...
>>     for choice in data:
>>        do choice in name:    # best calling form I can think of.
> It looks like your proposal is to change switch into a command that
> defines a function of one parameter. Instead of the "do <expression>
> in <switch>" call you could just call the switch -- no new syntax
> needed. Your example above would be
>  for choice in data:
>    name(choice)          # 'name' is the switch's name

I thought of using a function call so it would be more like using a 
generator, but also ruled it out because it does create a new scope and 
I think closures may complicate it or it would require also passing all 
the names needed for each case which would get old quick if it is 
required every time.  One of the things I want to be able to avoid in 
dict based dispatching for cases with only one or two lines of code.

So my intent was that it use the local scope and not use the function 
call signature which implies a new scope to the reader and a returned 
value, thus the 'do choice in name' calling form.  No returned value is 
needed because it has full access to local name space.

for example you wouldn't write...

    return if x: 42 else: 84

but would instead...

    if x:
      y = 42
      y = 84
    return y

The 'do' is used in the same context an 'if' is used.

    switch a:
      True: y=42
      else: y=84

    do x in a:
    return y

> However, early on in the switch discussion it was agreed that switch,
> like if/elif, should  not create a new scope; it should just be a
> control flow statement sharing the surrounding scope. The switch as
> function definition would require the use of globals.
> Also, it would make sense if a switch could be a method instead of a 
> function.

There's no reason why it couldn't be put "in" a method.  If the switch 
uses the surrounding name space you have that flexibility.  I'm not sure 
if the select definition could be put in the body of a class and have 
the do's in a method. That would be like having an if in the body of the 
class and the else to it in a method, so I would think it wouldn't be 
allowed.  So they both would need to be in the same name space and the 
select will always need to be defined before the 'do' is executed.

> I realize that by proposing a new invocation syntax (do ... in ...)
> you might have intended some other kind of interaction between the
> switch and the surrounding scope. but exactly what you're proposing
> isn't very clear from your examples, since you don't have any example
> code in the case suites, just "...".

What was intended probably would be more closely related to constructing 
a switch with BASICS gosub command.

    one:              # in basic these do not have their own scope
      print 'one'
      return          # return from subroutine not function here

      print 'two'

      print 'three'

    data = ('one', 'two', 'three')
    for choice in data:
        if choice == 'one': gosub one
        elif choice == 'two': gosub two
        elif choice == 'three': gosub three

Which would be better expressed as..

    switch choices:
        'one':  print 'one'
        'two':  print 'two'
        'three':  print 'three'

    for choice in ('one', 'two', 'three'):
        do choice in choices

Each case label expression would be evaluated when the switch block is 
executed, ie... in order it appears in the program, but the code for 
each case would be skipped until a (do choice in choices) line. Each 
switch case block would not fall through but return to the next line 
after the 'do' line by default.

The whole thing could be put in a separate function or method if it's 
desired to get the single function call form you suggested along with a 
separate name space.

    def switcher(choice):
        switcher roo:
           1: a = 42
           42: a = 1
           else: raise ValueError

        do choice in switcher:
        return a

    switcher(1)   ->   42
    switcher(42)  ->   1
    switcher(100) ->   raises exception


More information about the Python-Dev mailing list