Saturday, February 10, 2007

Wordpress

I decided to migrate to wordpress.com for my blog.

I initially copied all my blogger entries through the API. After a lot of fighting with the formatting, I concentrated on my entries (3) since January 1st, 2007.

So, this is where it happens now.

Friday, February 02, 2007

Ruby Streams

I've been thinking about my business days problem some more. And this time I turned to Ruby, a language which I am becoming quite familiar with.

This is my naive implementation of streams in Ruby. Streams are thus functions. The actual class name is 'Proc', a lambda returns a 'Proc'. Each call returns a new value.

def stream_from(value)
lambda {value = value.succ}
end

class Proc
def filter
f = lambda do
value = self.call
return (yield(value) ? value : f.call)
end
end

def take(n)
result = []
n.times {result << self.call}
return result
end
end
As for "filter", it takes a predicate passed as block. The filter becomes a "decorator" for the stream.

This is a nice example of closures. The 'value' parameters becomes the state for the stream. Also of note, the use of the variable 'f' to fake recursion of an anonymous function.

Prints the 20 next business days:

s = stream_from(Date.today).filter {|date| date.cwday < 6}

puts s.take(20)

Note that my "contract" with stream_from is that what I pass it implements succ. Here's an example with integer:

s = stream_from(4)

puts s.take(20)

And, of course, filters can be chained. The next Monday that falls on a 17th:

s = stream_from(Date.today).filter {|date| date.day == 17}.filter {|date| date.cwday == 1}

puts s.call.to_s

Here's the same code as before, but with a function cast as a block:

def monday?(date)
date.cwday == 1
end

s = stream_from(Date.today).filter {|date| date.day == 17}.filter(&method(:monday?))

I decided consciously to avoid optimizations here. It did keep my code short and clean. Besides, you should only optimize based on need.

There's much more to streams... combining streams together, maps, more complicated generation of the next value, etc.

So, here's your next interview questions:

"What's the first 3 prime numbers after 5,000,000,000 which has a 3 as last digit?"

s = stream_from(5_000_000_000).filter{|x| x.prime?}.filter{|x| x.mod(10) == 3}

puts s.take(3)

I leave the code for "prime?" to your imagination.

The concept of command-line pipes springs to mind. One of the reason the command line is so powerful, is that you can combine filters together to perform truly complicated tasks. Another reason is that each filter does only one thing and does it well.

It's all about thinking in pipes.

Wednesday, January 31, 2007

The Story of business_days(...)

I've been really busy with work recently. However, while going over my requirements for the nth time, something caught my eye: business days. In particular, finding the date 7 business days from a another date.

Far from being a hard task, it fell more into the annoying category. Or maybe it would make for a good interview question. In the end, how complicated or simple can someone make such a function?

A little background first. I had to use JavaScript, a language I'm only superficially familiar with. Also, after discussion with the customer, the definition of business days was Monday to Friday. No holidays are included... In fact, which holidays? And from what region/country?

Having flirted with Haskell recently and being "influenced" by the SICP lectures, a few ideas came to mind.

"business days" is a subset of "days", and both are infinitely lists. If I have a list of all the days and I filter it through the is_business_day(date) function, and I access the element at position 7, I get the answer. I was getting pretty angry with my inability to accomplish my task in such a straightforward way. I started to understand what people mean when they talk about the expressiveness of a programming language.

I then turned to Ruby for ideas. The succ function came to mind, I made that my starting point.
function include(value, list) {
for (var i=0; i < list.length; i++) {
if(list[i] == value) return true;
};
return false;
}

function succ(date) {
return new Date(date.getTime() + 1000 * 60 * 60 * 24);
}

function is_business_day(date) {
return include(date.getDay(), [1,2,3,4,5]); // mon-fri
}

function business_succ(date) {
var result = succ(date);
return is_business_day(result) ? result : business_succ(result);
}

function repeat(f, x, n) {
if(n == 1)
return f(x);

return f(repeat(f, x, n-1));
}

function days(date, n) {
return repeat(succ, date, n);
}

function business_days(date, n) {
return repeat(business_succ, date, n);
}
Personally, the moment of enlightenment came when I realized that iterating for days or business days was the same code and that it could be made even more generic by the repeat function.

A few comments:
  • the include function would usually be borrowed from prototype.js

  • recursion has become part of my day-to-day programming techniques

  • all functional

  • definitely not the shortest code I've written, but all pieces are both trivial and reusable

  • a definite LISP-like flavor

  • proof that SICP and friends have been damaging my brain :)

Thursday, January 04, 2007

I didn't "get" bookmarklets

I have only recently been fully aware of the joys of bookmarklets. Of course I had the del.icio.us bookmarklets for quite a while now, but, the idea had not fully sank in until recently. I didn't "get" bookmarklets.

Yesterday I re-discovered Google Reader and with it came its own, very useful, bookmarklet: Subscribe....

Today I decided to wrote my own: booktrack...

Booktrack is a web application to keep track of the books I read. It keeps track of what I want to read, what I'm reading now and what I'm done reading. This was inspired by librarything.com.

When it came to data entry, I had integrated with the amazon search API and it was working great. However, when people talk about books they usually link directly to the entry at amazon. Being on the page and having to log into my application to look for the exact same book seemed like a task that could be automated.

This was a spur-of-the-moment idea. A what-if that needed answering. 5 minutes later, I had it and it was working. It is relatively crude, but I'll take the iterative approach on this one.

Now I'm wondering what else I could do with that? What else needs a bookmarklet? What have I missed? This is all part of me trying to keep an eye out for stupid and repetitive tasks.

Monday, November 27, 2006

Useful: latest

I reinstalled my computer from the ground up recently. This has given me a lot of opportunity to question, rethink and automate my day-to-day activities.

As part of my ongoing effort to redeploy my rails applications to my production environment in the most intelligent hands-off way, I've been looking for a way to "detect" the latest deployment.

Here's the script that resulted:

#!/usr/bin/env ruby
$VERBOSE = true

pattern = ARGV[0]
pattern ||= '*'

latest = Dir.glob(pattern).sort_by {|f| File.mtime(f)}.last

puts latest unless latest.nil?

It takes, optionally, a bash-style glob. ( latest 'booktrack*' )

I'm finding it surprisingly useful. Let me know if it helps you out.

Sunday, November 19, 2006

Automation - continued

It has been roughly a month since I started voluntarily pushing the limits of automation in my life. This has been mixed blessing.

PROS:
  • medium to long -term quality of life is improved
  • helps me assimilate Ruby libraries
    (spending a lot of time on gotapi.com)

CONS:
  • spending a fair amount of time automating
  • still facing the initial resistance to automation

A Story: Mac OS X Screenshots

3 words: CMD-SHIFT-4

One of the joys of working with Mac OS X is the screenshot mechanism part of the OS. Nothing to install, it is expected that you would want to take screenshots easily. You type CMD-SHIFT-4, you get a crosshair, you select a region, then a file is created on your desktop. Painless.

CMD-SHIFT-4 takes care of the file creation, a mental block in process of saving a screenshot. In the spirit of Don't Make Me Think, I can testify that one question I don't want to answer when taking a screenshot is "what filename should I save this as...?" Imagine taking a picture with a camera and being asked to give it a filename... I just want to save the screenshot, I will come back to it later. In fact, I just want a long list of screenshots I take to be dumped somewhere, as a chronological series of things I found interesting.

Mac OS X already takes care of incrementing the filename automatically. Image 1.png, Image 2.png, etc... That's great. However, I was not so hot about the default "dumping" location. So, naively, I created a folder called "dump" to which I would push the pictures when cleaning up. What I had not fully absorbed was that I would have a filename conflict on my hands every time I did that. If I had dumped a few screenshots to "dump", took a few more, and tried to push my files to "dump" again, chances would be very good I would have, for example, 2 files named "Image 1.png", the second one wanting to overwrite the first.

Before I had become such a stickler for automation, I had decided to zip the pictures, name the file based on the date and push it to "dump". This involved the manual steps of, selecting only the pictures on the desktop, selecting the "archive" option from the menu, finding out what was today's date, renaming the file in ISO style date format and moving the file to "dump".

Today, while contemplating the mess that my desktop was becoming, I realized how badly in need of automation this process was. So, 15 minutes of hacking later, I had a script that would select the pictures on the desktop (only the ones matching the screenshot naming convention), find out how many pictures I had moved so far (stored in a magic file in the destination directory), move the files while changing their names incrementally. A little more work was involved in figuring out how to have automator run this script as a plugin.

Now, I have what I wanted: screenshots stream.

Tuesday, October 31, 2006

Revisited: Thinking versus doing

I've talked about this before. But Knowing, doing and learning puts it better.

I liked this:
...we really don’t know something until we use it. Understanding that we can’t really separate knowing from doing explains why people who love to code are so much better at it than those who don’t: they try stuff out.

And this:
The cycle of learning is to learn a little, then use what you’ve learned, then learn some more.

Reinforces what I said, while being more articulate.

Friday, October 20, 2006

Rails for fun

After months doing other projects at work, I've been "drafted" for some Java this week. Specifically, I'm making a middleware servlet. Since I knew I was going to do the Java-thing again, I bought Head First Servlets and JSP. Like the others books in this series, it's really really good. Yes, I have mentioned this series twice before, but rest assured that I am not getting any money from this. People who know me know that I have trouble not mentioning the things I love.

Java is still not great, but it's not as bad as I remembered it to be. And maybe it's the machines we have at work, but it feels insanely fast. INSANELY fast. But I digress.

I've been programming in Rails for about a year now. I have 4 fully-functional personal webapps to my count. I also have forkmapit.com that I coded part of. However, much of the credit goes to my friend Daniel.

I eat my own dog food. All the applications I developed, I use on a daily basis. I coded my applications to solve actual problems that I was having. Application development, however, is an iterative process. You release something and your users tell you how close (or far) you are from what they thought they would get. I am my own customer, and I am pretty demanding. When you're forced to use your own application, you soon discover the annoyances and the many ways you could make it better. Tonight, I hit the mental threshold where I decide to fix bugs, streamline and improve.

After a week of Java, going back to Rails is a much needed break. I code in Rails for fun. Like myself, a lot of people using Rails have normal 9-to-5 jobs where they code in whatever technology will ensure a regular paycheck. In many ways, Rails is double-edges sword. It's a pleasure to work with ... but a curse to those who have to "go back" to, say, Java for work. I mentioned to coworkers that going back to Java after having used Ruby felt like having your hands tied behind your back and trying to program by typing with your nose...

The application I was working on, I call "tvguide". With "tvguide", I keep track of the episodes for the TV shows I watch. It was a plain application with a little bit of AJAX to update the numbers in a table.

It was a glorified spreadsheet.

No more... I implemented photo upload to the application, thumbnails for my listings, I completely changed (and improved!) the presentation, I took out pre-RJS DIY AJAX. Best of all, I have a much better application now, with more features and LESS code.

I want the tools I use to empower me. Rails and Ruby are such tools. As for "fun", I would say it's a side effect of using good tools.

Thursday, October 19, 2006

Ruthless Automation

How many people truly use computers to automate repetitive daily tasks? Even if they do, to what extent are they automating these tasks?

I've always been a fan of automating boring and/or repetitive stuff out of my way, but I never conciously made an effort to automate all I could automate. That was until I read Saving Time and Pragmatic Project Automation.

I can think of 4 reasons for automating your tasks:
  1. It forces you to really "understand" a task. What am I exactly doing here? Is there a better way? Is this robust?

  2. It documents a task. Not just a series of steps in your head anymore. The script is the intent, the all encompassing series of steps you need to do combined with the things you need to "touch" to accomplish your tasks.

  3. It saves times. This one is obvious and is the most often presented reason. I would dare say that taking 10 minutes to automate something that would have taken 5 minutes is still worth it. Read on.

  4. It hones your skills. Makes you practice your soft-scripting skills

In light of #4, you can now see automation as an end rather than a means.

Daily automation will expose you to a lot of small problems. "How would I get the third column from that file?" "How would I insert a line after a match in a file?" "How many lines are in that file?" "How many times is the word 'tomato' in that file?" Note here that everything is a file in UNIX, so these examples are more general than they appear.

The more you automate, the better a programmer you become. The better a programmer you are, the easier it is to automate. You can also consider better understanding, better process documentation and time-saving as welcomed side-effects.

Thursday, September 14, 2006

Mocking Ruby

No... not like it has been recently.

The question came up of whether I had been using mock objects before and how I would do it in Ruby. Having read recently Pragmatic Unit Testing, I had a few ideas on how to proceed. However, the rules change when you are using Ruby instead of Java.

Here is the test code I answered my questions with:

puts "before: #{Time.now}"

class Time
def self.now
'mock answer'
end
end

puts "after: #{Time.now}"

Outputs:

before: Thu Sep 14 13:02:46 EDT 2006
after: mock answer

No wrapper class. No factories.

For the sake of full disclosure:
  • You might want to save a pointer to the old method.

  • The way you would do that is a little cumbersome for static methods . But it's very clean otherwise.