Year: 2011

  • The fallacy of the general purpose tool

    I carry a Leatherman on my belt every day wherever I go. It has become a bit of an extension of my body, which I only really notice when I have to fly somewhere and I’m forced to take it off for the flight. Then I get to my destination and I can’t open the cable ties on my luggage. At the same time, I have a whole pinboard of tools up in my garage, which overlap somewhat with my Leatherman: a dedicated set of pliers, some dedicated screwdrivers and scissors and so on. This is because the is not as good as any of these dedicated tools.

    I think the same goes for programming languages, and therefore I have learned quite a few, just like I have stocked my pinboard with tools that do one thing very well. Many people find learning new languages onerous and will try to find the one language that does everything they want to do well. Their arguments against learning a new language often involves something like “but I can do that just fine in my language, and then I don’t have to learn a new language”. Here’s an example from real life that illustrates the advantages of special purpose languages.
    My father approaches me with this problem. He uses an accounting package which can import OFX files (they’re an SGML/XML format for financial records), but there is a slight problem. The ZAR needs to be changed to USD and the dates (which are tags of the form 20111201 – yes, no closing tag as it’s SGML) have to be changed from YYYYMMDD to YYYYDDMM. Now, turns out that Python has a nice OFX module. So does Java. But the fastest way to make the changes to his files is probably sed:
    sed -r -i -e 's/ZAR/USD/' -e 's/<DT(.*)>
    ([0-9]{4})([0-9]{2})([0-9]{2})/<DT1>243/' filename.ocx

    This does the replacement in-place, is really fast and is quick enough to throw together. This is the kind of thing that sed shines at. In fact, it is exactly what it was designed to do, so it is unsurprising that it does it so well.

    To do the same thing in Python (even without using the OFX module) requires a bit more effort:

    import os
    import re
    from tempfile import mkstemp

    filename = "test.txt"
    patternStrings = ["ZAR", r"<TD([^>]+)>([0-9]{4})([0-9]{2})([0-9]{2})"]
    replacements = ["USD", r"<TD1>243"]

    # Compile patterns
    patterns = [re.compile(p) for p in patternStrings]

    # Create temporary file to hold outputs
    _, tempfile = mkstemp()

    # Process file
    outfile = open(tempfile, 'w')
    for line in open(filename):
    for pattern, replacement in zip(patterns, replacements):
    line = pattern.sub(replacement, line)
    outfile.write(line)

    outfile.close()

    os.rename(tempfile, filename)

    Needless to say, the difference is even more pronounced in Java due to the large amount of boilerplate needed.
    import java.io.File;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.Scanner;
    import java.util.regex.Pattern;

    public class Fixer {
    static File infile = new File("test.txt");
    static String[] patternStrings = {"ZAR", "<TD([^>]*)>([0-9]{4})([0-9]{2})([0-9]{2})"};
    static String[] replacementStrings = {"USD", "<TD$1>$2$4$3"};

    public static void main(String[] args) throws IOException {
    Pattern[] patterns = new Pattern[patternStrings.length];
    Scanner in = new Scanner(new FileReader(infile));

    // Compile patterns
    for (int i=0; i<patternStrings.length; i++) {
    patterns[i] = Pattern.compile(patternStrings[i]);
    }

    // Create temporary file to hold outputs
    File tempfile = File.createTempFile("tmp", "tmp");

    // Process file
    FileWriter outfile = new FileWriter(tempfile);
    while (in.hasNextLine()) {
    String line = in.nextLine();
    for (int i=0; i < patterns.length; i++)
    line = patterns[i].matcher(line).replaceAll(replacementStrings[i]);

    outfile.write(line + System.getProperty("line.separator"));
    }
    outfile.close();

    // move temp file back to filename
    tempfile.renameTo(infile);
    }
    }
    Now, at this point someone is bound to say “but wait, people don’t write desktop apps in sed!”. But that’s quite the point – Java was designed with programming in the large in mind, but it is really tedious for short programs. In many cases, learning a small domain specific language and using it to solve your small problem is faster than learning how to do the same thing in your “one language”.
    I wish I had more time to put examples together, but this situation just presented itself and got me thinking.
  • Moral ergonomics

    It is quite hard to design a comfortable chair. The task is made more difficult by the variety of the human anatomy. While ergonomics has done some great things for our workplace comfort, it will never be able to come up with a truly one-size-fits-all chair.

    Perhaps it is because the physical differences are so easy to perceive that the above statement seems so obvious. However, rephrase the whole paragraph substituting systems of ethics for chair, and perhaps include something about moral feelings being at least as variable as our limb measurements and you’ve got a big philosophical argument on your hands. It appears that there is renewed interest in a formal study of morality, from many camps. People like Sam Harris are trying to say that science can say something about our moral urges. He is being fought by people that feel that a deity or a book should be the final authority. Whichever way we turn, however, I am sure that everyone has felt the feeling of conflict that arises when your stated ethics lead to an uncomfortable conclusion.
    As a moral noncognitivist I hold that moral statements like “X is wrong” can most appropriately be interpreted in a similar way to “I do not like X”, perhaps with an additional “and I think you shouldn’t like X either” thrown in for good measure. To borrow from a recent Facebook argument on a similar topic, it means that at the bottom of each moral statement lies a feeling. If you hold that killing people is wrong, it may be because that thing in itself feels wrong or because you have some connection to doing things against people’s will. Keep asking yourself “and why is X wrong” for every answer like “X is wrong because Y is wrong, and X is like Y”, and you’ll end up saying “because Y feels wrong” at some point.
    Of course, there are people who have tried to derive a consistent ethic. Is it so strange that none of them has really gained universal acceptance? Is it strange that no single chair design has been mass produced and rolled out all over the world? That our cars have adjustable seat backs? It’s a question of ergonomics, not of logic.
    I believe that we have to admit two things to go forward in the scientific exploration of morality:
    1. There is no universally acceptable set of moral rules. No, not even consequentialism or human rights or the golden rule or anything like that. People feel differently just like they have different sized feet.
    2. It may be more prudent to work on systems that don’t terribly offend a critical number of people rather than to try to argue that they should just come around. I don’t mean that we should coddle the extremists, but I do think it could be more productive to understand which feelings are causing the problem rather than to try to employ logic.
    Unfortunately, many rational people fall into the trap of believing that anyone who reaches a different conclusion from them is irrational, neglecting the possibility that they may simply be shaped differently.
  • Scientific python setup for Mac OS X 10.6

    For posterity, and to save some people some trouble with their install, here is what I have done to get up to a working matplotlib on my Mac running Mac OS X Snow Leopard 10.6.8:

    • Download and install the python.org python 2.7 from the .dmg installer
    • Download this egg. To run it, you may have to rename it to have a .egg extention rather than a .egg.sh one.
    • Open a terminal
    • Execute the file you renamed before by typing “sudo bash path/to/filename” – to get the path to filename, you can open a Finder window showing the file, then drag the icon onto the terminal – that will insert the full path.
    • Install pip by typing “sudo easy_install pip”
    • Install GNU readline by typing “sudo pip install readline”
    • Install nose (used for testing) by typing “sudo pip install nose”
    • Install iPython by typing “sudo pip install ipython”
    • Download and install the NumPy binary distribution
    • Download and install the SciPy binary distribution
    • Download and install the Activestate tcl/tk – this is the one recommended on python.org. If you click through the python website to the Activestate one note that you don’t have to fill in your info to download the files.
    You should now have a working scientific environment that allows you to do most of the things you would be able to in a stock install of Matlab with a couple of packages thrown in, except for plotting. The next step is a bit more arduous, because the default binary install of Matplotlib does not work (at least not for me). This is what I had to do to get it working:
    • Download and install XCode
    • Install git
    • Open up a terminal
    • Type “git clone git://github.com/matplotlib/matplotlib.git”
    • Type “cd matplotlib”
    • Type “sudo su” and provide your password when prompted
    • Create a temporary directory (XXX in the following command) then do ‘ARCHFLAGS=”-arch x86_64″ LDFLAGS=”-arch x86_64″ CFLAGS=”-arch x86_64″ FFLAGS=”-m64″ PREFIX=XXX make -f make.osx fetch deps mpl_build mpl_install’
    • Type “cp -r XXX/lib/site-packages/* /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/”
    To test if all this worked, do the following:
    • Test ipython: “iptest’
    • Start ipython and do
    • Test numpy: “import numpy; numpy.test()”
    • Test scipy: “import scipy; scipy.test()”
    • Test matplotlib: “import matplotlib; matplotlib.test()”
    Don’t be too upset if some errors occur: it seems the test suites aren’t entirely up to date. As long as you don’t see a segfault or ipython crash, it should be ok.
  • My brain can’t do that!

    When I was teaching computer programming to chemical engineering students I categorically denied that “I’m just not good at programming” was a valid excuse for flunking my subject. Lately I have become less sure of my position. Let’s be clear: I am quite convinced that people have varying levels of aptitiude, it’s just that I had thought that certain skills were so similar that one automatically led to the other. Chemical engineering students in their second year have already passed many mathematics courses and have shown themselves to be intelligent and able to follow the steps required to do algebra and calculus in a relatively mechanical way. Programming has always seemed entirely analogous to math for me, so I made the mistake of generalising from my experience to theirs. As any good lecturer will tell you, this is a fatal mistake.

    I am constantly fascinated by how inaccessible our brains are to ourselves. The puzzle of exactly how my brain makes the connections between formulae and computer language syntax is probably better understood by some neuroscientist somewhere than by myself. This is, of course, entirely counter-intuitive. Many people would even deny it. But the thing that concreted it for me was listening to this episode of Radiolab (which if you haven’t listened to it yet, is an entirely awesome podcast covering a wonderful array of different subjects in a wonderfully cock-eyed way). Spoiler alert: the skill displayed here is a guy who is able to run multiple symphonies simultaneously in his head. Try it. Start playing a song you know well in your head. A couple of seconds later, try starting another one by a different band. Now tell me where you are in the two different songs. If you are remotely normal you will be unable to even conceive of how to do this. The feeling I get when I try to do this makes me wonder: if we have such a clear example of a person who can do something that seems totally unrelated to skill or practice, but which normal people cannot do, who am I to say that those people in my class just couldn’t “get” programming, ever?
    The problem is that it leads to an uncomfortable end point. I cannot assume that any student who struggles simply cannot do the stuff he’s trying with – that would invalidate the entire purpose of teaching! Well, unless you ascribe to the notion that teachers are only allowing their students to reach their potential, but that’s a whole different post. Like the conundrums of free will, it appears the argument ends in a place where assuming something we know to be wrong in general (that “any student can do this”) is both easier and less risky than correctly determining who has the ability in the first place and then only focusing our attention on them.
    One good thing has come from these musings though: I find myself being much more sympathetic to the struggles my students have. And I suppose a little empathy never hurt anyone.
  • Public transport and a sense of society

    I feel more connected to people around me when I am in the street.

    This seems pretty obvious, but the effect on your psyche is so subtle that you may not notice the long term changes. When I started road running, I obviously noticed more runners on the road (due to confirmation bias), but I also started to feel less afraid on the road. I had experienced a certain sense of trepidation leaving my “safe” home to go into the “unsafe” street, which diminished as I realised that the people on the street were also real people with real lives, by and large going about their business with no ulterior motives. Now that I walk more I am noticing a similar thing – I am feeling more connected to the community.

    In the excellent book Traffic, Tom Vanderbilt posits the theory that being in a car makes us treat other people differently, while they perceive us differently. In effect, we treat the car as a whole new animal, only nominally controlled by its driver. It’s easy to think of the people who inhabit the street as totally different from us when there is a nice glass wall between us. When you walk in South Africa, you also realise just how poor our pedestrian infrastructure is. It’s amazing how often you get the “what are you doing in the road” look when you have no other option. Perhaps on a deeper level there is a question about why I am not in my car. I reckon that people would be more likely to contribute to their local communities if they walk or run.