Saturday, October 31, 2009

Self-hacks: Undistorting Your Availability Heuristic

Wikipedia will tell you the availability heuristic is a mental shortcut we use to predict the frequency of an event based on how easily an example can be brought to mind.

Modern media distorts our ability to use this built-in heuristic effectively by discussing and presenting rare events far too frequently. In fact, that's what media does almost by definition. Unfortunately, we aren't well-adapted for this scenario: you can't just turn the heuristic off in your decision-making and thought processes.

For example, if you've been paying attention to popular media lately, you will probably think about H1N1 if you think about death. (Of course, your actual risk from H1N1 is small compared to more traditional factors.) Along the same lines, particuarly earlier this decade you might have thought terrorism caused a significant loss of life globally compared to other causes. Probably more people are afraid of planes than cars even though it's clearly irrational.

We could come up with tons of other examples, but let's skip to the useful part: how can you fight back against media abuse of your own cognitive limitations? Unfortunately, merely reading this post and becoming more aware of the bias will not tend to increase the accuracy of your decisions, even though you probably think it will. But one easy way is to stop paying attention to the popular media so you can calibrate more accurately. Another way is to find accurate data (to the extent that such exists) on issues you care about and consult it frequently, such that the facts are always fresh in your memory for the heuristic to pull up.

I haven't really managed to develop a SuperMemo habit I can stick with, but the incremental reading tool is useful for self-programming. I imagine you could come up with a more efficient application if you had the goal of "undistorting the availability heuristic" instead of "maximizing retention of fact-based information". One could get a disproportionate amount of benefit from just 5 minutes of review per day.

Sadly, it's easier to just turn on the TV.

Saturday, October 24, 2009

Death knell for closed devices

There's a story over on Slashdot about a iPhone developer who's seen 80% of the high scores from his new game submitted from pirated copies. Just another piece of evidence at the end of a long trail showing that "closed" devices are not effective as a piracy prevention tool. The iPhone is about as closed, locked-down, and ridiculous of a platform as it's possible to create and market, and yet there's still a piracy rate of 80% for a $2 application.

Game companies aren't stupid, and when they see results like this they react by moving as much of their IP as they possibly can behind a firewall. The future belongs to open devices accessing closed services. Good, bad, indifferent, it's just the reality.

Structured Procrastination

“...If all the procrastinator had left to do was to sharpen some pencils, no force on earth could get him do it. However, the procrastinator can be motivated to do difficult, timely and important tasks, as long as these tasks are a way of not doing something even more important.”

-- John Perry

Brilliant. For me, even writing in this blog is always some form of creative avoidance.

Tuesday, October 20, 2009

Default Deny Is Good

To me, the biggest failure of the major desktop operating systems is their lack of an easy, it-just-works sandbox environment for running untrusted computations. This omission has allowed browsers to do an end-run around the OS companies to the point where we now have Google attempting to make the OS itself the afterthought.

They have a point. The average user is not capable of judging whether they can trust a piece of downloaded code or not. Hell, generally the sophisticated power user with full access to an application's source code does not have time to make a sound judgement just to try out some new toy. So, people take shortcuts and mistakes happen.

The right answer is to make the initial judgement irrelevant, which is exactly what's happening as web browsers evolve into a general computing platform. As more and more software moves into the browser, the implicit change to a default-deny security model on the client side will help stem the tides of malware while letting us encourage users to try software they (or some big corporation) haven't personally vetted as safe. And in a massively multicore environment where the worst a process can do is launch an (intentional or unintentional) denial of service attack against a few of your cores, why not?

In a world with default deny, at least it becomes clear exactly who you are trusting with your data.

Sunday, October 18, 2009

Python: How long does it take to remove a key from a dict?

I try to do micro-benchmarks in python as little as possible, but it never hurts to be aware of the cost of your primitive operations. That's regardless of the language you're coding in.

So, today's experiment... Say you want to remove a key from a dict whether it exists or not. How long does it take? Depends on your method of choice...

pop: 0.24 usec/pass
try/except: 2.27 usec/pass
if in: 0.11 usec/pass
if has_key: 0.20 usec/pass

if x in d: del d[x] wins for execution time, but there are definitely times when the (almost 20x!) overhead of exception can be worth it.

import timeit
num = 10000

a = {}

setup = """
a = {}
"""
stmt = """
a.pop("hi", None)
"""
t = timeit.Timer(stmt=stmt, setup=setup)
print "pop: %.2f usec/pass" % (1000000 * t.timeit(number=num)/num)

stmt = """
try:
  del a['hi']
except KeyError:
  pass
"""
t = timeit.Timer(stmt=stmt, setup=setup)
print "try/except: %.2f usec/pass" % (1000000 * t.timeit(number=num)/num)

stmt = """
if 'hi' in {}:
  del a['hi']
"""
t = timeit.Timer(stmt=stmt, setup=setup)
print "if in: %.2f usec/pass" % (1000000 * t.timeit(number=num)/num)

stmt = """
if {}.has_key('hi'):
  del a['hi']
"""
t = timeit.Timer(stmt=stmt, setup=setup)
print "if has_key: %.2f usec/pass" % (1000000 * t.timeit(number=num)/num)

Sunday, October 11, 2009

Photoshop-ify the Web

With all the new shadow and glow effects in CSS3, the web's starting to feel more and more like Photoshop. The only thing I really miss are the sliders. Firebug lets you see style changes quickly, but changing a property value by keying it in will never be as good as visualizing the whole range by dragging it from low to high. You'll always zero in on the sweet spot much faster that way.

I don't like GUI tools being used where text-based ones will suffice, but this seems like one area where it's hard to avoid them.

Friday, October 9, 2009

Typography: LaTeX, MS Office, and The Web

Here's a great read on the differences in font support between MS Office 2007 and LaTeX, and a recent presentation on typography for the web.

Typography has been around in some form or another for millenia and we've learned a thing or two in all those years. People who don't understand it or don't care about it are doomed to mess it up. Unfortunately that means HTML and MS Word have seriously botched it, and are only finally starting to get it right after nearly 20 years each.

As for this blog, don't even ask. The type layout is a disaster.

Saturday, October 3, 2009

I Wish Python Could Support Anonymous Functions

One of the things about Python that makes me the saddest is its lack of support for multi-line lambda functions. Guido talks about the reasons for not including them here. He's right, of course: they should not be included because it would make a mess. Python's beauty lies in its simplicity, and I fully appreciate the value in not implementing special cases.

But the fact that multi-line lambdas shouldn't be added to the language doesn't imply they aren't missed, or that Python isn't worse as a language because it can't add support for them without adding special cases and making a mess.

The canonical workaround for a situation where you'd prefer to use a multi-line lambda is to use a named function nested into the same scope where you would put the lambda. Yes, it works. It's functionally equivalent. But in practice I find this additional required step limits the number of little throwaway functions I'm willing to create. The extra work of trying to create an intelligent name for the function and then having to re-locate it on all subsequent code modifications, following that extra little indirection, really slows my thinking process. It changes the kind of code I tend to write, and not in a good way.

One of the reasons I dislike Java so much is the need to come up with some Identifier for every damn thing, cluttering up the source code with completely unnecessary verbosity. I'm not a Ruby person and probably never will be, but I think its better support for anonymous functions is probably a big win for the language. I know it's a big win for JavaScript/ECMAScript.

(Incidentally, I first learned this might be a problem from Steve Yegge a few years ago when I was just getting started with Python. I'll be sad if Python dies in relative obscurity to Javascript like he seems to think it might, but that may well be the way the industry is headed.)

And yes, Python is awesome, but let's be honest about the warts.