Haskell.tmbundle
I’ve been learning Haskell lately, taking advantage of the downtime after graduation. I’ve been meaning to learn a functional language for some time now. It was a toss up between this and erlang. I picked Haskell because someone is running a weekly lesson thread on a forum I read, and it’s always more fun to learn a language with other people.
The TextMate bundle for Haskell is a nice start, but there are a lot of improvements that can be made. I made a repo for it over at github, which can be cloned at git://github.com/will/haskell-tmbundle.git
I’ll be adding improvements to the bundle as I make them, and hopefully other people join in.
Test driving a file parser
My current project involves pulling gene names and group data from a tab separated file, then coloring those genes on a pathway diagram. Just like any other part of an application, the parser should be well tested. But how exactly should you go about testing all the different edge cases that the parser will see?
One method I’ve worked with was to have several sample files in the fixtures directory and load them. I don’t really like this, for much the same reason I don’t like fixtures. It’s too easy for fixtures to deteriorate into a large, unmaintainable mess. But more importantly, I can’t see the whole test on one screen. Parts are hidden across several files, all of which you have to read before you can understand the test.
I’ve come up with a simple way to solve this problem. The test files should be created in the test. Now this is for tab separated files, but it could easily be changed to create csv files, or both.
it "should skip empty lines and extra columns" do
file = [
[ "gene 1", "group 1", "only the first two columns count" ],
[ ],
[ "gene 2", "group 1" ]
].to_test_file
parser = Parser.new file
parser.import
parser.lines.should == [ [ "gene 1", "group 1" ],
[ "gene 2", "group 1" ] ]
end(I actually have the empty lines test separate from the extra columns test, I just wanted to put them together for this post.)
#to_test_file is a method on Array, and it will create a file in the tmp decretory, then return the file name. Right now it can optionally take a specific file name. I’ve never had reason to use that, so I’ll probably remove that bit of complexity.
class Array
def to_test_file(filename = "test_file")
File.open("tmp/#{filename}", "w") do |f|
self.each do |line|
f << line.join("\t")+"\n"
end
end
"tmp/#{filename}"
end
endStick that in spec_helper or test_helper.
Originally I had it on String, and put in all of the \t and \n myself. That was an unreadable mess. With Array you get the column and line separation implicitly.
This doesn’t help at all for very large or complicated files. But for small, simple files, this is one of the easiest ways for testing the parser and keeping everything all in one place.
When is it okay to reopen NilClass?
I just read a post advocating changing NilClass#method_missing to always return nil. Their argument is that you no longer have to check if you actually have something before calling methods on it like:
@sun && @sun.still_burning? Instead, you could just call @sun.still_burning?, which is nice. I usually just check isthesunstillburning.com 20 times a day to make sure, but you get the point.

Now, it’s a very attractive, very short solution to an every day annoyance—that alone is enough to make me worry. Overriding #method_missing on NilClass just seems wrong. The better solution is to define Null Objects for all of your classes, and have those returned instead of nothing. Yeah, it’s more work than the method_missing solution, but it’s a lot safer and doesn’t leave such a bad taste in my mouth.
I do actually reopen NilClass though.
Often, actually. Working with rspec and making typos can be very frustrating otherwise. If do @sum.should_recieve(:set) instead of @sun, then you’ll get
Mock 'some mock' received unexpected message :tyop?
# or
Mock 'NilClass' expected :list_pathways with ("hsa") once, but received it 0 timesThe second one is easy to realize you have a typo, sure. But I know I’ve wasted time wondering why the expectation failed, and I’m sure you have too. By adding a few methods to NilClass, this is no longer an issue:
class NilClass
def should_receive(*args)
raise "WARNING: you tried to add expectations to nil!"
end
alias :stub! :should_receive
endWARNING: you tried to add expectations to nil!When else have you found it okay to mess around with NilClass?
I’m sure there are a few other occasions where it makes sense.
Sun picture from rodger smith, flickr
Merb and Datamapper
With the recent release of Merb 0.5, I’ve decided to use it along with datamapper for one of my new projects. It isn’t different enough to be completely foreign, but enough to be a refreshing change. I haven’t done a whole lot with either yet, but I have had a patch accepted, ran into a huge, annoying problem with autotest, and found out how to watch the SQL datamaper is generating.
stats patch
While I was in #merb earlier today, hassox posted some current benchmarks. Being somewhat a stickler for statistics, I had to point out that means alone were meaningless. Not to get into all of the boring details, two distributions can have the same mean, but be completely different. Here is an image I made in Mathematica and sktich to show why:

They all have the same mean, but a random pick from the distribution with the smaller variance of 0.5 is more likely to be actually be near the mean than with either of the ones with higher variances. If you apply this to load times, two severs could serve pages just as quickly on average. However, the one with the higher variance is going to seem a lot slower, since there are more slow points in the set.
I submitted a patch to add the standard deviations to each of the tests and clean up the output a bit.
More on setting up Leopard
After posting about setting up a new mac, I started to put all the other things I found myself missing on a new install. Aside from the standard adium, quicksilver, colloquy, and others there are a few things that are good enough to share.
Blurminal
I’m a long time user of iTerm but I’ve decided to give leopard’s new tabbed terminal a chance. The one big frustrating thing is it lacks iTerm’s ability to switch between tabs with command+arrow keys. However, a big plus is CiarĂ in Walsh’s Blurminal. Instead of just having a percentage of transparency, it slightly blurs whatever is behind the terminal. Here’s an example:
RubyGems and Leopard
I just got my replacement iMac (the speakers were shot on the first one) and was going about getting my development environment back together. While trying to instal datamapper, it choked on the json gem.
ruby extconf.rb install json
can't find header files for ruby.
As it turns out, the solution is very simple. I didn’t have Xcode tools from the install disc on there yet. Since it’s something you just put on once then forget about, it took me a while to realize what was going on. Hopefully this post helps others figure it out quicker than I did if they stumble across it.
Also remember to update RubyGems. Leopard comes with 0.9.4 and we’re up to 1.0.1 right now.
sudo gem update --system
rspec 1.1 and my open source debut
Everyone’s favorite BDD framework, rspec, has recently come out with a lot of nice improvements and fixes. One big thing that’s in there now is the ability to write stories. The best thing, however, is that I’m now on the community page!
Over the summer, while I was working at Collaborative Drug Discovery, Dav Yaginuma from Pivotal Labs and I wrote a patch to allow the specparser to parse describe blocks that had :behaviourtype set on them. This let us run focused tests on those sections. After figuring out what was wrong, it was just a matter of fixing some regexes and adding another clause.
Then when I was at the rails edge conference in Chicago in August, I had a chance to meet David Chelimsky. He suggested that I submit that as a patch. I first checked with CDD to see if doing so was breaking any sort of agreement I signed or anything, then wrote some specs for the changes and submitted. Even though it wasn’t all that much and it was pair-programmed, it was my first open source contribution and seeing it “official” now is awesome.
script/console sandbox mode
NameError: undefined local variable or method `acts_as_watchable' for Issue:Class followed by a stack trace. I spent a while trying to figure out why this wasn’t working, then gave up. A few weeks later I tried again, and quickly realized the problem was that I only have a production environment set up, and I wasn’t telling script/console to use the production environment.
In the process of figuring out how to do that ( –help ), I ran into this awesome feature I simply never knew about.
-s, --sandbox Rollback database modifications on exit. This is really cool. Especially if you’re going to be mucking around with your production data. I’m planning on hacking script/console to have -s enable by default if you go into the production environment. Or at the very least an alias.

