[Python-Dev] Simple Switch statement

Guido van Rossum guido at python.org
Mon Jun 26 01:08:19 CEST 2006


On 6/25/06, Ka-Ping Yee <python-dev at zesty.ca> wrote:
> On Sun, 25 Jun 2006, Guido van Rossum wrote:
> > In your eagerness to
> > rule out surprises, you're creating the biggest surprise of all: the
> > restriction to literals is certainly a surprise!
>
> I disagree.  Perhaps what we mean by "surprise" is different.

Apparently. I would find it very surprising if a language as dynamic
as Python didn't allow expressions for cases. User learning a language
generalize from examples. They see that expressions can be used
whenever constants can be used. When they find that one particular
context doesn't allow an expression, they will surely be surprised.

I'm utterly unconvinced by Raymond's arguments for his proposal.
Disallowing names goes against half a century of programming wisdom.

Here's an argument for allowing names (this argument has been used
successfully for using names instead of string literals in many APIs):
if there is a spelling error in the string literal, the case will
silently be ignored, and who knows when the bug is detected. If there
is a spelling error in a NAME, however, the error will be caught as
soon as it is evaluated.

> In Raymond's design, there is a simple rule for what's allowed in a case.
> The whole statement can be described in very few words:
>
>     Each case is a literal integer, string, or tuple of integers
>     or strings.  Execution jumps to the first case that matches the
>     value of the switch expression (or to 'default' if no match).
>
> That's it.  The simpler the rule, the less surprising it is.  It would
> take a lot more words to explain the behaviour of something like Nick's
> 'once'-based proposal.  Here's an attempt:
>
>     Each case consists of an arbitrary expression, but the expression
>     may not refer to any local variables or arguments of the immediately
>     surrounding function definition.  The value of each case is computed
>     when the surrounding function definition is compiled.  If any two
>     cases have the same value, an exception is thrown at compile time.
>     At runtime, execution jumps to the case whose previously fixed value
>     matches the value of the switch expression (or to 'default' if no
>     match).
>
> Not only is that longer to describe, it's also more difficult for a
> beginning programmer to understand, since it requires knowing when
> different parts of a program are compiled (and what happens if the
> same part is compiled more than once).

But beginning programmers don't read descriptions like that. They
generalize from examples. It's the experts who need to have the
complete unambiguous rules so they can know where the boundaries of
safe code are. Beginners tend not to get near the boundaries at all.
The experts can handle the unvarhished truth. (Hey, they can handle
metaclasses. :-)

Here's how I envision beginners learning about the switch statement
(after they're utterly familiar with if/elif). We show them a few
examples, some involving literals, some involving manifest constants
(either defined locally at the module level, or imported). We give
them *one* simple rule: "the cases must be run-time constants" (an
intentionally vague term). Then let them loose. I expect that the
results will be total satisfaction. I expect that the same approach
should work for users who are beginning Python programmers but who are
experienced in other languages (say, Java).

The most likely problem a newbie will run into if they forget about
the "cases must be constants" rule is trying to use a locally computed
value as a case expression. This will most likely involve a local
variable, and the proposed switch semantics specifically disallow
these. So it'll be a compile time error -- better than most rookie
mistakes!

Yes, it's possible that someone has a global variable that really
varies between function invocations, and they might use it in a
switch. This will fail (give the wrong answer) silently (without an
immediate error). But I think it's pretty unlikely that someone will
try this -- they must not have been paying attention in two different
classes: first when it was explained that variable globals are usually
a bad idea; second when it was explained that switch cases must be
(run-time) constants.

Note that the entire class of well-known problems (which surprise
almost every ne Python programmer at least once) that are due to
one-time evaluation of mutable initializers (both parameter defaults
and class variables) is ruled out here, by the requirement that switch
cases be hashable, which in practice means immutable.

Now, I'm not convinced that we need a switch statement. There are lots
of considerations, and I sympathize with those folks who argue that
Python doesn't need it. But I'd rather have no switch statement than
Raymond's castrated proposal.

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)


More information about the Python-Dev mailing list