[Python-ideas] Yet Another Switch-Case Syntax Proposal
Steven D'Aprano
steve at pearwood.info
Sat Apr 19 05:12:24 CEST 2014
On Sat, Apr 19, 2014 at 01:08:58AM +0200, Lucas Malor wrote:
> On 18 April 2014 17:03, Joao S. O. Bueno jsbueno-at-python.org.br |
> python-ideas-at-python.org| <0ucjz7dbjt at sneakemail.com> wrote:
>
> > It may be just me, but I fail - in a complete manner - to see how this
> > syntax can offer any
> > improvement on current if/elif chains. It seems to differ from that
> > only by reducing
> > the explicitness, and the flexibility of the test condition that can
> > be used in any
> > of the subconditions
> >
>
> It's more simple to use when you can use it, as switch statement in the
> other languages. And it somewhat adheres to the DRY principle: why repeat
> the subject? If I'm checking what type of tarot card I have, why should I
> repeat every time I'm trying to identify a tarot card?
I think that is a misunderstanding of the DRY principle. I'll explain
further below, but even if the idea is to avoid writing anything twice,
the case syntax fails. Consider your example:
switch tarot case 0:
card = "Fool"
elcase 1:
card = "Alan Moore"
elcase 2:
card = "High Priestess"
<etc....>
Here, you are repeating "elcase" and "card =" each time, so you are
still repeating yourself. We can avoid that by using the lookup table
approach:
table = {0: "Fool", 1: "Alan Moore", 2: "High Priestess", ...}
card = table[tarot]
Now that truly is a DRY solution!
I think that your interpretation of DRY does not match the intention of
the people who invented it. DRY is not (as I understand it) concerned
with trivial, mechanical duplication like chained if...elif:
if tarot == 0: ...
elif tarot == 1: ...
elif tarot == 2: ...
and objecting to chained if...elif as a DRY-violation is, I believe, a
misunderstanding of DRY.
I'm going to quote Dave Thomas, co-inventer of the DRY principle:
Most people take DRY to mean you shouldn't duplicate code.
*That's not its intention.* [emphasis added] The idea
behind DRY is far grander than that.
DRY says that every piece of system knowledge should have
one authoritative, unambiguous representation. Every piece
of knowledge in the development of something should have a
single representation. A system's knowledge is far broader
than just its code. It refers to database schemas, test
plans, the build system, even documentation.
http://www.artima.com/intv/dry.html
DRY is also known as "Single Source Of Truth", which is perhaps a better
name, since it emphasises the fact that there is a single canonical
source of each piece of knowlege in the system, rather than putting the
emphasis on mere mechanical duplication. In the case of your tarot
example, it is *not* a violation of DRY, because the various elif lines
are not *sources* of knowledge which may contradict each other. The
worst that will happen is that if you change the variable name "tarot"
to something else, your code will fail with a name error. DRY is not
about reducing the amount of mechanical edits you do when you rename a
variable.
# Single source of truth for the name of the variable is its binding:
tarotcard = draw_card() # was "tarot"
if tarot == 0: # now fails
...
Subsequent lines merely *use* the name, they don't act as potential
sources of knowledge which could contract each other. DRY doesn't really
have much to say about variable names, except perhaps "don't use the
same name (in the same namespace) for different things", so if your
motive in introducing a switch/case statement is to DRY, I think you
need a better motive.
One motive I'd like to see is, could a switch/case statement be used to
automate table lookups? Two problems -- albeit mild ones -- with the
table lookup idiom is that the table lives longer than needed, and it
puts the table in the wrong place. This motivated Nick to suggest a
"where" block:
card = table[tarot] where:
table = {0: "Fool", 1: "Alan Moore", 2: "High Priestess", ...}
solving both problems at once: the table is declared only when needed,
not before hand, and does not exist outside of the block. A third
problem, not solved by Nick's "where", is that the table requires every
case's value ahead of time, whether it will be needed or not. When the
values are constants, that's not a big deal, but they might be expensive
expressions.
Perhaps there is some way to optimize a case statement so as to avoid
these disadvantages of the table lookup idiom. To me, that is a
reasonable motive worth chasing. I wouldn't bother with a case statement
unless it was more efficient than a chain of if...elif.
> @Skip Montanaro: yes, switch statement is used in C also for code
> optimization. Frankly, I think this aspect is unimportant for CPython in
> the present time.
Then I think we're not going to agree on the use or need for switch.
--
Steven
More information about the Python-ideas
mailing list