bitfission

will leinweber

Haskell.tmbundle

Posted by Will Leinweber Wed, 21 May 2008 06:29:00 GMT

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.

no comments |

Test driving a file parser

Posted by Will Leinweber Sun, 13 Apr 2008 01:29:00 GMT

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
end

Stick 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.

1 comment |

When is it okay to reopen NilClass?

Posted by Will Leinweber Tue, 04 Mar 2008 08:00:00 GMT

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 times

The 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
end
Now we get:
WARNING: you tried to add expectations to nil!
and even a line number to where the typo is.

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

1 comment |

Merb and Datamapper

Posted by Will Leinweber Wed, 16 Jan 2008 16:51:00 GMT

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: normal distribution

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.

1 comment |

More on setting up Leopard

Posted by Will Leinweber Tue, 15 Jan 2008 06:06:00 GMT

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:

Blurminal

no comments |

RubyGems and Leopard

Posted by Will Leinweber Sat, 12 Jan 2008 21:12:00 GMT

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

1 comment |

rspec 1.1 and my open source debut

Posted by Will Leinweber Mon, 17 Dec 2007 21:36:00 GMT

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.

1 comment |

script/console sandbox mode

Posted by Will Leinweber Thu, 06 Dec 2007 16:45:00 GMT
I was exploring my redmine install on my server by going into script/console. Whenever I tried to do anything, like finding a user, I’d get
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.

1 comment |