Friday, April 08, 2011

Python switch statement

Having a bit of fun at 3 in the morning.

The Python version of the C-style switch statement is either a bunch of if/else's or a dictionary. Going the dictionary route can be ugly looking (not to mention confusing, pulling a value out of a mapping and calling it). This just encapsulates the whole thing and adds some support for a pseudo-default case.

The structure is a bit weird, nowhere near as nice as regular syntax, but if you absolutely have to do this, it makes it easier to read.

"""A simple function (roughly) implementing C-style switch statements.
Usage::
switch(value, {
'it':
"You said the word!",
'fruit':
"Suppose he's got a pointed stick.",
'camelot':
"'Tis a silly place.",
Ellipsis:
("You've got two empty halves of coconut and you're " +
"bangin' 'em together.")
})
Also accepts *args and **kwargs, which will get passed on to the
specified case if it is callable.
The result of the callable is returned, as is the value of
non-callables.
Since `default` isn't a built-in name (and obviously not a statement),
the under-used built-in singleton Ellipsis is used in its place under
the assumption that it is unlikely to be used as a real case.
Fortunately, in the event that it *is* used as a real case, using
Ellipsis as the switch value will properly select the Ellipsis case.
Unfortunately, so will a non-match. It's probably best you don't use
Ellipse as a real case.
Finally: implicit break, no fall-through at all. Ever. First of all,
dict isn't ordered, so fall-through would be weird. Second, I'm not
going to specialize for OrderedDict (plus it would look weird on your
end), and third, I have no idea how to put breaking in if I did. If you
want this, do it yourself.
"""
def switch(value, cases, *args, **kwargs):
try:
case = cases[value]
except TypeError:
raise TypeError("Cases must be scriptable.")
except KeyError:
case = cases[Ellipsis] if Ellipsis in cases else None
finally:
try:
return case(*args, **kwargs)
except TypeError:
return case
def main():
import sys
try:
value = sys.argv[1]
except IndexError:
value = None
print switch(value, {
'it':
"You said the word!",
'fruit':
"Suppose he's got a pointed stick.",
'camelot':
"'Tis a silly place.",
Ellipsis:
("You've got two empty halves of coconut and you're " +
"bangin' 'em together.")
})
if __name__ == "__main__":
main()
view raw switch.py hosted with ❤ by GitHub

Wednesday, April 06, 2011

And now I can't remember what got me on this line of thought...

So here I am, hacking away in Python for oh, a few years now, and I just remembered what got me into Python in the first place.

See, I was using Python's implicit line wrapping with a tuple, and remembered back to when I read an article explaining that Python did that. Before that, all my longer lists weren't wrapped, or wrapped with '\'.

That made me recall the impetus that had me looking for such information in the first place: a Wiimote driver for Linux called CWiid.

Which, coincidently, was the first time I had seriously taken a look at Python.

I was using it to add motion control to Descent 3, which I had just purchased from GoG.com, which was... September 23rd, 2008.

I got something rudimentary going, noted that it would take a lot of hacking to make it better, and I needed to be better at the extension language it used to do it myself. So I waded into that language, which turned out to be Python.



Huh. I never did get back to motion control in Descent 3...