Ahh, the throws of young love. Remember that first wild romance? The incredible highs, the tragic lows, the fact that the swung from one to the other in 30 second intervals?
I had an interesting afternoon yesterday fighting with my new lover, Ruby.
I’m building a data processing application and started playing around with FasterCSV. It’s a great library, with the possible exception that it may secretly be giving me evil penguin pseudo-duck classes.
From various examples:
FasterCSV.foreach('/path/to/file') do |row|
foo = row[0]
bar = row[1]
puts foo + bar
end
Pretty nice. FasterCSV returns an array of values. It’s a fast way to access CSV files, especially using it’s :header, :col_sep and other arguments which would allow nice programmatic handing of CSV files easily.
But I had a problem. I’m used to fast one-liners and don’t like to spend all day setting variables when I really want to be calculating dissolved oxygen percentage. Thus I went straight to:
FasterCSV.foreach('/cool/scientific/data') do |row|
temp, cond, ph, domgl, depth, sal, turb = row[2..8]
…
blah = temp * 375
…
end
Well, not really crash. We love that word, though, don’t we. “My Excel crashed!” I’ll restate for clarity:
Exception!
Apparently, multiplying nil by an integer is an exception.
“What? Do I have blank line? How is temp nil?”
Well, you real Rubologists may know, but I didn’t. I thought that I could shortcut those variables, but it didn’t work! It took a long time, and I read more about Ruby slicing than I wanted to.
Turns out that you can, of course, shortcut those variables… provided that method exists. I guess it doesn’t in the duck-typed class returned by FasterCSV. Hunting around, I found that our friend row had a ‘to_a’ method. Thus, this works.
<pre>FasterCSV.foreach('/cool/scientific/data') do |row|
temp, cond, ph, domgl, depth, sal, turb = row.to_a![2..8]
…
blah = temp * 375</pre>
…
end
So, the lesson here: Just because examples tell you it’s an array, and because you can pull a value like an array, don’t assume that it is an array.
Apparently, this thing didn’t act quite enough like a duck.