Another stab at a "switch/case" construct (for Python 3000):

damien morton morton at dennisinter.com
Thu Mar 28 14:37:14 EST 2002


You could go a lot further with this case statement

First thing is to allow for variable length list unpack:

(a, b, *c) = (1,2,3,4,5,6,7)
a <- 1
b <- 2
c <- (3,4,5,6,7)

Second thing is to allow non-binding literals in a list unpack:

(1, a, b) = (1, 2, 3)  matches/unpacks with a=2, b=3
(1, a, b) = (2, 3, 4)  fails
('fred', a, b) = ('fred', 'was', 'here') matches/unpacks with a='was',b='here'
('fred', a, b) = ('joe', 'was', 'here') fails
 
Then, introduce a simple case statement:

case var:
    20:
        print 'var is 20'
    30:
        print 'var is 30'
    else:
        print 'we have fallen though'
        
        
A slightly more complex case statement:
        
        
case:
    if var < 20:
        print 'var is < 20'
    if var = 25:
        print 'var is 25'
    if var > 30:
        print 'var is > 30'
    else:
        print 'we have fallen though'
        
        
An even more complex case statement:
        

case someobject:
    (X, Y):
        print 'macthes any list/tuple of length 2'
        print X, Y
    (X, Y, *Z) if X<32 and Y=="abc" and len(Z)>4:
        print 'would match (1,"abc",3,4,5,6,7)
        print 'X <- 1'
        print 'Y <- "abc"'
        print 'Z <- (3,4,5,6,7)'
        print X, Y, Z
    (X, Y, *Z):
        print 'matches any list/tuple of length 3 or more'
        print X, Y, Z
    X if isinstance(X, file):
        print 'matches any file object'
        print X
    else:
        print 'final condition matches anything'
        
        
translated into current python:

(assuming that variable list unpack is included in the python core)

try:
    (X, Y) = someobject
except ValueError:
    try:
        (X, Y, *Z) = someobject
    except ValueError:  
        X = someobject
        if isinstance(X, file):
            print 'matches any file object'
            print X
        else:
            print 'final condition matches anything'        
    else:
        if X<32 and Y=="abc" and len(Z)>4:
            print 'would match (1,"abc",3,4,5,6,7)
            print 'X <- 1'
            print 'Y <- "abc"'
            print 'Z <- (3,4,5,6,7)'    
            print X, Y, Z
        else:
            print 'matches any list/tuple of length 3 or more'
            print X, Y, Z
else:
    print 'macthes any list/tuple of length 2'
    print X, Y



"Ken Peek" <Ken.Peek at SpiritSongDesigns.comNOSPAM> wrote in message news:<3ca33c88 at news.mhogaming.com>...
> Well-- OK, my new ISP doesn't have a news server, but I found one
> that I could use to post this with.  If you reply to my email, do
> the 'nospam' thing first to my email address...
> 
> I really am interested in what people think about this.  I have
> looked at all the other c.l.py posts on this construct, but I
> don't think anyone proposed this format.
> 
> BTW-- the 'until' thing in the original letter was already posted,
> so please disregard that part of this post- (I left it in for
> accuracy.)
> 
>   -----Original Message-----
>   From: Guido van Rossum
>   Sent: Thursday, March 28, 2002 04:45
>   To: Ken.Peek at SpiritSongDesigns.NOSPAM.com
>   Cc: Marc-Andre Lemburg
>   Subject: Re: PEP 0275
> 
>   If you really want to discuss this, it's better to post to c.l.py.
> 
>   --Guido van Rossum (home page: http://www.python.org/~guido/)
> 
>   -----Original Message-----
>   From: Ken Peek [mailto:Ken.Peek at SpiritSongDesigns.NOSPAM.com]
>   Sent: Thursday, March 28, 2002 01:05
>   To: Marc-Andre Lemburg
>   Cc: Guido van Rossum
>   Subject: PEP 0275
> 
>   How about:
> 
>   match some_object:
> 
>       ("I dream of Jeanie",):
>           print "with the light brown hair"
> 
>       (1,3,5,7):
> 
>           print "some odd numbers"
> 
>           # 'break' leaves the entire match structure
>           if (time_to_leave): break
> 
>           # 'continue' jumps to the first
>           # statement in the next clause
>           continue
> 
>       (123,456,789):
> 
>           print "some bigger numbers too"
> 
>       (19,56,22):
> 
>           print "some random numbers"
> 
>       (1001,2002,3000):
>           # YES! It IS possible we want to do NOTHING!
>           pass
> 
>       any:
>           print "we got here because there were no matches"
> 
>   This is kind of a neat construct because you can put multiple
>   tests on one line, and it doesn't look too messy (like C's
>   'switch' would look.)  Also-- we are not limited to matching up
>   only integers.  This is very clean code compared to a long string
>   of "if/elif/elif/elif/else" clauses...  I like READABLE code--
>   which is why I like Python!
> 
>   Note that the aggregate of the tuples must have unique values and
>   types-- (this allows for efficient implementation, and for future
>   optimization.)  A match is found only when BOTH the type and
>   value are the same.  'some_object' can be any object, but it
>   would be wise to not use floating point numbers or other things
>   that do not guarantee a valid '==' compare.  I suppose these
>   ambiguous types could be flagged with an error from the compiler,
>   but I would hate to see a run time check (which would slow things
>   down, just to accommodate a bad programmer.)
> 
>   The match clauses do not 'fall through' automatically like a "C -
>   switch" statement-- (this is the source of many errors in 'C'.)
>   A clause can be forced to 'fall through' with the use of a
>   'continue' statement, which jumps to the first statement in the
>   next match clause (because 'falling through' IS useful
>   sometimes.)  I suppose the interpreter/compiler could flag an
>   error "UnreachableCode" (or 'BadIndentation') if 'continue' was
>   used by itself, and there were statements after it at the same
>   indentation level...
> 
>   The 'any' keyword could be changed to 'else' I suppose, but I
>   think the word 'any' "just plain sounds better when you say it",
>   and I like the 'match' keyword better than anything I have seen
>   or can think of...
> 
>   =================================
> 
>   I have also been mulling over a new 'until' keyword-- it works
>   the same as 'while', but the body of the loop is executed first
>   before the conditional test is made the first time, and the sense
>   of the test is opposite (ie- the test must be FALSE for the body
>   of the loop to be executed again.)  'continue' jumps directly to
>   the conditional test, and 'break' jumps out of the loop (as expected):
> 
>   until something_becomes_true:
> 
>       print 'here we are in the body of the loop'
>       print 'which was executed at least once'
>       print "before the 'something_becomes_true'"
>       print 'test was made.'
> 
>       # we can skip to the test now with a 'continue':
>       if bad_programming_practice == TRUE: continue
>       print 'nope-- no continue'
> 
>       # we can get out of the loop with a 'break':
>       if another_bad_programming_practice: break
> 
>       # we probably need to stop the loop someday:
>       something_becomes_true = do_some_check()
> 
>   =================================
> 
>   I doubt if any of this will ever make it into Python (well--
>   maybe Python 3000)-- but it's fun to think about.
> 
>   Well, what do you think?
> 
>   --Ken Peek
>   Ken.Peek at SpiritSongDesigns.NOSPAM.com
>   (This letter is released to the public domain-- KP.)



More information about the Python-list mailing list