About matt

My name is Matt Wilson and I live in Cleveland Heights, Ohio. I love random emails from strangers, so get in touch! [email protected].

Help improve my PyOhio talk

I ran through my PyOhio presentation at tonight’s Clepy meeting.

I think I’ll spend more time talking about the material in the slides, rather than pausing just long enough to scan them with my eyes and move to the next. I’m anxious about boring people, so I think I go at a frenzied pace.

Also I need to learn how to tweak s5 (or at least rst2s5.py) so that I can have more control over how my content appears. A fair number of code samples had the last few lines truncated.

Anyway, I welcome comments on my presentation.

Don’t spend your termite poison money on insurance against Martian invasions.

This post wanders all over the place and I’m not sure I’m articulating my thoughts very well. Comments and criticism are welcome.

Fannie Mae and Freddie Mac (I don’t know why these companies have such ridiculous names either) are bound by regulations to hold enough capital (cash dollars) in order to remain solvent across some theoretical worst-case scenarios. The regulators dreamed up some really extreme situations that could likely bankrupt these companies, and insisted that the companies held enough cash to survive.

When I worked at Fannie Mae in the department that wrestled with the C++ model that calculated our reserve requirements for these 10-year stress tests, we used to joke around about how unlikely these stress tests really were. We would say that we might as well buy insurance against Martian invasions, or against all the animals teaming up together to attack humanity.

While Fannie Mae was legally complying with these unrealistic scenarios, the sub-prime crisis was a scenario that they were not prepared for, and it slaughtered them. The CEO had to step down. The price fell from around $80 a share when I left in 2001 to $18 today.

The sub-prime crisis at its core is very mundane. Lenders got sloppy and investors let their greed entice them to take risks they shouldn’t have. That’s all there is to it. Local banks lent money to high-risk borrowers, then the banks sold the loan to Fannie Mae, who sold the loans to Wall Street. Investors preferred the high-return investments over the low-return boring crap.

No perfect storm was necessary to trigger this. It was just a whole lot of people getting sloppy and eventually enough straws accumulated to break the camel’s back. The same pattern played out in the seventeenth century and probably a hundred times since then.

Now I’m a workaday programmer, and I see the same dynamic in code. People write elaborate systems to protect against ridiculously unlikely scenarios but then skimp on the boring stuff. Maybe they get the hard parts done but never make sure their app’s internals are well documented, easy to maintain, and intuitively designed.

In my experience, it’s the mundane bugs, not the diabolically clever hackers, that cause me the most grief.

If I write some algorithm that costs O(n2), I will almost immediately start trying to tame it down. The voices in my brain scream about worst-case costs. Macho programmers write badass algorithms. However, I find that the really smart thing to do is to spend a few minutes thinking about the likely use cases. If I know that for the forseeable future, I’m never going to run this algorithm with n > 5, then I think the grown-up thing to do is to write a big fat docstring that reminds me later about this risk, and then move on to getting other stuff done.

The market rewards a good-enough and finished solution more than an potentially amazing but currently unfinished solution.

If Fannie Mae had focused on just making sure that they were vetting the loans better, things wouldn’t have been so bad. The theoretical worst case scenarios are not going to happen before the more likely stuff goes wrong. I worked at Fannie Mae preparing against Martian invaders. We ignored the termites in the walls, so to speak.

Doing my part to promote PyOhio.

It’s going to be a brain-melting conference with amazing swag. We got people you wouldn’t believe lined up to present. Google recruiters will be there with suitcases full of cash looking for new hires. Terminator robots will travel backwards in time to try to prevent all the amazing breakthroughs that will happen on this day. We’re gonna shake the foundations of science.

I already mentioned my topic but here it is again because I’m shameless.

My netflix problem

We’ve had the same three movies in our house for a REALLY LONG TIME.

netflix.png

I’m sure all three of these films are great. But they also seem really heavy and serious. I have enough stress in my own life that I don’t want to absorb fictional stress also. So every time my wife and I have two or three hours to relax, we end up watching something else, like Andrew Zimmern chowing through a plate of horse penises.

Wacky idea for python coroutines

Christian Dowski posts some uses for python’s enhanced generators. I tried to type a comment on that post, but I couldn’t figure out how to submit it successfully. Either comments are not allowed or I failed the CAPTCHA.

Anyhow, ever since I read about how common lisp handles exceptions, I’ve been daydreaming about how to do the same trick in python. In lisp, an exception jumps to some other place to get handled, just like in python. However, what is different is that the exception handler can repair the problem and then hand control back into the original block. For example, in the lisp toplevel, if you forget to define a variable before you try to copy its value to somebody else, the exception will propagate to the debugger. And in the debugger, you can then assign a value to that variable, and then resume your original program.

So that’s the background for my idea for generators. The generator that is trying the exception-raising code could yield the traceback to another generator when it hits an uncaught exception. Then the other generator, the exception-handling generator, could repair/log/do whatever, and then yield a value back to the original code.

For example, if the original code is iterating through a list of two-tuples, and for each two-tuple, it divides the first element by the second element, when it raises a ZeroDivisionError, it could catch that and yield it over to the exception handler. Then the exception handler could do whatever, like maybe prompt the programmer to choose a new denominator. After the programmer chose a new denominator, the exception handler could yield that back to the original generator and then the original generator could resume.

Lua calls generators that can receive values “coroutines” or “non-preemtible threads”. I think those are better labels because they hint that generators are way more than just iterators in drag.

How to connect to a wireless network from the Ubuntu command line

Why use a friendly GUI when there’s cryptic shell commands out there?

Phoenix Coffee offers free wireless access without an access key and they broadcast their ESSID. Here’s how I connect:

$ sudo iwlist eth1 scan # eth1 is my wireless card.
eth1 Scan completed :
Cell 01 - Address: 0A:1D:19:15:C2:C1
ESSID:"bestcoffee"
Mode:Master
Channel:5
Frequency:2.432 GHz (Channel 5)
Quality=88/100 Signal level=-44 dBm Noise level=-81 dBm
Encryption key:off
Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 6 Mb/s
9 Mb/s; 12 Mb/s; 18 Mb/s; 24 Mb/s; 36 Mb/s
48 Mb/s; 54 Mb/s
Extra:tsf=0000003befa89182

That scan lists every available access point. The important piece of information to extract here is the ESSID. Now I set my wireless card up to connect to that ESSID:

$ sudo iwconfig eth1 essid "bestcoffee"

And finally, I tell my card to request an IP address from the router:

$ sudo dhclient eth1 # gimme an IP address plz!
There is already a pid file /var/run/dhclient.pid with pid 6911
killed old client process, removed PID file
Internet Systems Consortium DHCP Client V3.0.6
Copyright 2004-2007 Internet Systems Consortium.
All rights reserved.
For info, please visit http://www.isc.org/sw/dhcp/

wmaster0: unknown hardware address type 801
wmaster0: unknown hardware address type 801
Listening on LPF/eth1/00:1c:bf:96:7e:21
Sending on LPF/eth1/00:1c:bf:96:7e:21
Sending on Socket/fallback
DHCPREQUEST of 192.168.1.112 on eth1 to 255.255.255.255 port 67
DHCPACK of 192.168.1.112 from 192.168.1.1
bound to 192.168.1.112 -- renewal in 251284 seconds.

I can type these three commands way faster than waiting for the GUI to fire up. Here they are again, without all the output:

$ sudo iwlist eth1 scan
$ sudo iwconfig eth1 essid "bestcoffee"
$ sudo dhclient eth1

Sometimes, I need to connect to a network with a hidden ESSID. That’s just as easy. I just configure the ethernet card to connect to anything:

$ sudo iwconfig eth1 essid any # any is a keyword, not the name of an ESSID.

Finally, some networks require an access key. Sometimes, people can give you the human-friendly version, and you can type that in like this:

$ sudo iwconfig eth1 key s:password # translates to the hex for me.

Note the s: in front. That translates what I type into the hex jibberish.

Other times, people insist on giving you the goofy string of hex digits, so you can set it like this:

$ sudo iwconfig eth1 key ACDB-1234-1234-EFG2

defaultdict.fromkeys does not play nice.

I use defaultdicts a lot when I’m grouping elements into a dictionary of lists. Here’s a simple example:

>>> a = defaultdict(list)

>>> a['x']
[]

>>> a['y'].append('yellow')

>>> a
defaultdict(, {'y': ['yellow'], 'x': []})

Now here’s where I got silly. I used defaultdict.fromkeys to prepopulate the ‘x’ and ‘y’ key right away, because I know I needed those:

>>> b = defaultdict.fromkeys(['x', 'y'], list)

>>> b
defaultdict(None, {'y': , 'x': })

>>> b['x']

>>> b['z']
------------------------------------------------------------
Traceback (most recent call last):
File "", line 1, in
KeyError: 'z'

Wowsa! b calls itself a defaultdict, but it is not a defaultdict.

I haven’t really thought this through, but this behavior is so unexpected that I would prefer that defaultdict.fromkeys raised a NotImplementedError.