Yet Another Switch-Case Syntax Proposal

Steven D'Aprano steve at pearwood.info
Wed Apr 2 21:06:06 EDT 2014


On Thu, 03 Apr 2014 08:50:47 +1100, Chris Angelico wrote:

> On Thu, Apr 3, 2014 at 1:53 AM, Lucas Malor <3kywjyds5d at snkmail.com>
> wrote:
>> For example, in a "switch x" statement, the code "case iterable: " is
>> identical to "if x in iterable: " (or elif etc). So if you want to
>> perform the same case block for more than one value, you have only to
>> specify a tuple, a range etc. I would suggest to add an exception for
>> non-iterable variables, so that you don't have to write "case var, : "
>> but simply "case var: " and it will be identical to "if x == var: ".
>> It's a bit tricky but the alternative is ugly.
>>
>>
> This is sounding like a nasty special case. I'm ambivalent on the
> overall proposal (want to see some real-world usage examples and how
> they read), but I don't like the "iterable vs non-iterable" distinction.

If we're going to add "switch" and "case" keywords, how about we also add 
"of"? Then we can write:

switch x case of a, b, c:
    # x equals one of a, b or c
case of d, e, f:
    # x equals one of d, e or f
case in g, h, i:
    # g, h and i must be iterable, and x is in one of them
else:
    # none of the above match


That means we can cleanly match the common use-case where we want to 
match something by equality, comparing against a list of 1 or more 
(usually) scalar values:

case of 1, 2, [23, 42], 99:
    assert x == 1 or x == 2 or x = [23,42] or x == 99

while also supporting the more complex case where we're matching against 
one or more sequences:

case in (1, 2, 99), [23, 42]:
    assert x == 1 or x == 2 or x = 99 or x == 23 or x == 42


Of course, in practice the second case is likely to be given dynamically, 
not as literals:

case in LIST_OF_KEYWORDS:
    ...


Another option is to say that the cases being tested ought to be quite 
small in number. If you're trying to do this:

case in range(100000000):
    ...

you're doing it wrong. That being the case, we only need to match by 
equality:

case 1, 2, 3:
    assert x == 1 or x == 2 or x == 3

and can write this when we want to match against a sequence or iterator:

case *LIST_OF_KEYWORDS:
    ...


and on the rare occasion we want to match against substrings, we can 
build a wrapper class:

class Wrapper:
    def __init__(self, value):
        self.value = value
    def __eq__(self, other):
        return other in self.value

case Wrapper("Hello world!"):
    # matches if x is a substring of "Hello world!"



But what's the advantage here? Since Python is not a static-typed 
language, it's unlikely that there are any compile-time optimizations 
that can be performed here. If there are any run-time optimizations that 
a JIT optimizing compiler like Python can perform, it probably can 
perform them just as well on a series of if...elif. So I'm not sure I see 
what having special syntax for a switch-case statement gives us.



-- 
Steven



More information about the Python-list mailing list