Friday, January 30, 2009

Being The Mark

I just finished with my dental appointment. Good news is, I was given a clean bill of health. No filling, crowns or dentures needed. Whew.

The bad news is that I'm still the biggest sucker around when I sit in that chair. Would I like floride fluoride (which I'm told at my age isn't needed)? Yes! Would I like the more expensive floride treatment? Double Yes! Does that come with undercoating and floor mats? Hope so.

I shouldn't mock these guys - I genuinely believe they have my best interest in mind.

--Ben

Update: The problem is, it's not just my hygienist that wants me to fall for this, it's also Colgate. And come on, can you really take on Colgate?

Thursday, January 29, 2009

Saving Your Configuration of Damn Small Linux

I continue to be impressed with Damn Small Linux. Consider, how I've turned an ancient laptop (without a hard drive) into a jukebox just by turning it on with this CD in it.

The only annoying part of using DSL is that your configuration is lost on a reboot. So, the commands needed to setup my network needed to be re-entered every time I restart the computer.

Of course, DSL provides a clever way for addressing this. But, I've always looked at the instructions and decided I didn't have the time to sort them out. Turns out, they aren't that bad. Here's what I did to make my setup restore on a reboot:

  • Found a spare USB thumb drive lying around. Nearly any size will do.
  • Booted up DSL
  • I plugged the thumb drive into the computer and mounted it with the command:
      mount /dev/sda1 
    
    In my case, I was fortunate enough to have this work. If you have problems, you might want to check out this article
  • I updated /opt/bootlocal.sh to contain the commands I wanted run at bootup time. My script looked like:
    #!/bin/bash
    # put other system startup commands here
    
    # Change XXX to the name of your access point
    # and YYY to the passphrase used to access it
    echo "Setting up WiFi to XXX..."
    iwconfig eth0 essid XXX
    iwconfig eth0 enc s:YYY
    
    echo "Requesting IP address..."
    pump&
    
    I could get fancier, I suppose, for now, these are the main commands I need run at bootup time.
  • Under the "DSL" toolbar (where the start button is on Windows), I went to: System >> Backup/Restore
  • For device, I entered in sda1
  • A few moments later, the box disappeared. I confirmed I had a backup in place by running:
      ls /mnt/sda1/
    
    and confirmed that backup.tar.gz was found there.

I now had a thumbdrive with my configuration settings on it. Now, every time I boot up the computer, I enter:

  dsl restore=sda1

And after a few moments (faster than my Windows laptop boots), I have a running Linux system with a correctly configured network.

I'm telling you, if you have any hardware lying around, you've got to give DSL a try. It's just remarkable what kind of system you can put together that's less than 50 Megs.

Google Apps E-mail Gets Gmail Labs

I just realized that my Google Apps e-mail now has access to GMail Labs.

For example, I can now add a send and archive button or enable forgotten attachment detection. These even more esoteric features like mouse gestures available.

If for some reason you still don't have personalized e-mail (for either work or business), run, don't walk, to Google Apps and get yourself setup for free today.

Say goodbye to yourcompany@hotmail.com and hello to you@yourcompany.com.

Me, I'm just happy to have all these cool new toys to play with.

Insights On The Octuplets

I really enjoyed my Sister-in-Law's take on the Octuplet story. But that not too surprising, if there's anyone who's well versed on this whole baby-making-process, it's her.

Thanks for sharing Sis!

Wednesday, January 28, 2009

recovery.gov - Will it be enough?

The president and congress is busy hashing out the stimulus package. And while they do this, you can actually follow along. Weighing in at 258 pages, and being written in govyspeak, this isn't exactly easy to do. But, browsing through the bill, I noticed what a high profile the recovery.gov website receives. On page 20 it explains:

REQUIREMENT TO ESTABLISH WEBSITE.
The Board shall establish and maintain a website on the Internet to be named Recovery.gov, to foster greater account ability and transparency in the use of funds made available in this Act.

Excellent. The report even outlines what needs to be published there. For example, on page 12 the bill explains:

(A) Each such agency shall notify the public of funds obligated to particular infrastructure investments by posting the notification on the website Recovery.gov.
(B) The notification required by subparagraph (A) shall include the following:
(i) A description of the infrastructure investment funded.
(ii) The purpose of the infrastructure investment.
(iii) The total cost of the infrastructure investment.
(iv) The rationale of the agency for funding the infrastructure investment with funds made available under this Act.
(v) The name of the person to contact at the agency if there are concerns with the infrastructure investment and, with respect to Federal agencies, an email address for the Federal official in the agency whom the public can contact.

Again, this is more good news. As a citizen, we can understand why our money is being spent the way it is.

This is a huge step forward. But, is it forward enough? Why not write into the bill provisions for more functionality, like say...

  • What about a facility for the public to ask questions, and have the answer provided by the contact? Of course, the responses would be archived.
  • What about a digg style voting of the projects, where you can view the most and least popular among those funded? This would tell our government (a) where they are doing a good job (and have our support) and (b) where either the public has found a project unworthy of support, or more likely, where a project needs more information to justify its existence.
  • What about requiring RSS feeds and an API? That is, make the site not only one visitors can benefit from, but also one programmers can leverage. Can you imagine a Google Maps + Funded Projects mashup? That's a no brainer. This is also nice because the government won't have to add all the features to recovery.gov, concerned citizens will be able to chip in and help too.
  • What about taking the Facebook Fan concept and using it for projects. Imagine that as a fan of a project, you'd get regular updates about the status and perhaps even be involved in helping.
  • What about a feedback area, where citizens can report how the project has positively or negatively impacted them personally.
  • What about requiring the project owner to publish photos or videos of how the project is proceeding?

Clearly, recovery.gov is a step in the right direction and one that hopefully everyone can get behind. I just hope they understand that simply having a website isn't good enough. Like the rest of us on the web, they've got to innovate.

Tuesday, January 27, 2009

Using WordPress Galleries to Store Post Image Meta Data

One of the neat features in WordPress is that an end user can so easily attach meta data to a post.

For example, I might want to make some posts only viewable if a user is subscribed to the blog. I can fairly easily tweak the theme to show users a message if they aren't logged in. I can then instruct the owner of the blog to use a custom field (the layman's term for meta data) named visibility with either the value free or subscription. The result: I've managed to add sophisticated functionality, and the dashboard of WordPress more or less automatically supports it.

One area where I've seen this meta data approach break down is in the world of graphics. The classic example being a thumbnail image that goes with your post and is shown on the home page. I've seen this handled using the meta data feature above, where the user is instructed to set the name of custom field to thumbnail and the value to an uploaded file name, such as music.jpg.

The problem with this approach is two fold: (1) end users need to know how to use FTP well enough to put the image in place on the server. And (2) depending on a file name is quite fragile - what if the user isn't consistent about case or doesn't include a space. It works, but unlike the meta data solution above, it's just not smooth.

A Better Image Meta Data Solution

I recently learned about an existing WordPress feature which helps out with the above problem. That is, galleries. Every post gets it's own gallery (which, I think isn't a great name, but it'll do), which represents images associated with the post. What's interesting is that images in the gallery don't have to appear in the article. In fact, when you upload an image in WordPress, there's a specific Insert into post button you need to hit. If you don't hit this button, the image is in the gallery, but not actually shown to the user. I'm sure this is a bit confusing, but again, it seems reasonable.

It turns out that you can trivially use these images in the gallery as meta data. I'm sure there's a variety of ways to do this, though I found the most straightforward way was to make the image name the meta data key. To implement the thumbnail meta data I discussed above, you instruct users:

  1. On the post editor's toolbar, next to Update/Insert click on the Add Button image.
  2. Upload the file as you normally would
  3. For the Title attribute, enter thumbnail
  4. Do NOT click Insert Into Post. Just hit Save All, and close the dialog box.

The user is now done. The image is in the post's gallery and ready to be picked up by the theme.

The theme can then leverage a function like get_post_thumbnail below. You'll see that it queries for child posts associated with a particular post's ID. This is where the gallery is stored. It then iterates through every child and looks for the one named thumbnail. When it finds it, it returns back the URL to the image.

function get_post_thumbnail($post_id) {
  $found = get_children(array('post_type' => 'attachment',
                              'post_mime_type' => 'image',
                              'post_parent' => $post_id));
  if(!$found) {
    return false;
  }
  foreach($found as $p) {
    if(strtolower($p->post_title) == 'thumbnail') {
      return wp_get_attachment_url($p->ID);
    }
  }
  return false;
}

The above function can be used anywhere in your theme you have a post ID.

There's no reason to link the above technique to images alone. Any media, perhaps a voice over or video, could be used as meta data just as easily. I love it when WordPress offers these flexible, yet easy to use features that make both the programmer and end user's life easier.

Emacs tip: a slightly better find-grep command

I finally got around to tweaking the the find-grep command in emacs to remove one of it's biggest annoyances (to me). Mainly, that it searches .svn directories for content. I'd say at least 99.999999% of the time this isn't what I want.

Here's what I added to my .emacs to fix this:

(setq grep-find-command 
  "find . -type f '!' -wholename '*/.svn/*' -print0 | xargs -0 -e grep -nH -e ")

Ahhh, much better.

Monday, January 26, 2009

Washington DC Sites-To-See List

I just had a terrifically fun visit with the parents and Grandpa, and had the same realization I always have when folks visit: there's so much in DC to see, yet, when they arrive, I never seem to have any fresh ideas to offer them.

So, now, I'm going to start planning ahead. I'm going to use this blog post to catalog sites in and around DC that I'd like to eventually see. When folks come to visit, we can check out this list for ideas. When I hear about new things, I can add it to the list. (Like how I say the past few sentences like I'm actually going to live up to this? Hope so.)

This page will be like my a gift wishlist, only for places to see.

Oh, and won't you help me out by putting up your own suggestions? The more obscure and wacky, the better! Remember, you could be the next visitor to the Simon household, and you wouldn't want to be stuck just driving around and looking at the same old monuments.

Always Enjoyable Stuff To Do

Stuff Yet To Be Done

OK, this list is woefully incomplete. Please, what can you suggest as a must do in DC that I should add to it?

junction.exe - Making my temporary laptop setup livable

I've written about junction.exe before - a super small tool that allows you to setup the equivalent of symbol links on Windows. What makes junction so cool is that the linked directories look and behave just like the source, whereas a Windows Shortcut is actually a file with link information in it.

This morning, Fedex came by to pickup my laptop, send it off to the repair depot. This left me with a temporary laptop and my current laptop's hard drive plugged in using a USB cable. Technically, the setup works just fine - but having all my files under F:\ has made it painful to access them. My fingers are just too used to typing the usual paths.

Not only that, but I've got content and programs on my new hard drive that the temporary laptop is missing. I was faced with having to resetup the MySQL databases that I had sitting already configured on my laptop hard drive. This was not a fun prospect (OK, it wasn't that bad - all the data was there, but I had better things to do than shuffle around files).

Enter junction.exe! I was able to create a few strategic links, like:

  junction.exe c:\tools f:\tools
  junction.exe c:\Documents and Settings\Ben\files f:\Users\ben\files

And bam!, the files appeared to be on C:\, yet were on the F:\ drive. This includes things like the database files I mentioned above. The result: I was able to run a MySQL instance right off the old drive, and use the existing files that were in place.

Not only didn't I need to take the time to worry about setting up a new environment, but, now I don't have to worry about the two environments getting out of sync.

Now, I realize this is nothing special for the Linux and Mac OS world. But, for us Windows people, being able to fake a directory layout like this and have Windows, Cygwin and any other tool be oblivious to it, is just too cool.

Why junctions aren't more popular on Windows is beyond me. Seems like they are a power user's dream.

Sunday, January 25, 2009

Making The Canadians Work For It

From the fine print on an Old Navy contest:

""For all prizes: If a winner is a Canadian resident, he/she must
correctly answer a time-limited skill testing question before submission
to claim prize.""

Anyone want to explain this?

I think this explains why Americans are so lazy - we just pickup our
prize. Our Canadian neigbors, they have to work for it.

--Ben

A Listening Trip Down Memory Lane

Grandpa Irv and I had a blast listening to a variety of classic radio shows.

Not much has changed since Amos and Andy discussed being republicans and democrats. Grandpa remembered the race between Hoover and Al Smith. Ben has no idea who Al Smith was - ahh, the forgotten loser. Grandpa also tells me that Al Smith didn't win because he was a Catholic, and that was controversial.

We listened to Flash Gordon and Benny Goodman. It's good stuff.

Grandpa also recommended with find some Sid Ceasar, which we did and was quite hilarious. Here's a sample below. It's completely politically incorrect, but quite funny:

And here's another hilarious one:

Fun stuff.

Saturday, January 24, 2009

The Story Behind The Logo

This article on food logos was a surprisingly fun read. Ever wonder what the other 56 varieties of Heinz are? Or why it's raining on Morton Salt Girl? Well, as the article explains:

The Morton Umbrella Girl got her start in 1914. The logo was produced as part of a series of ads in Good Housekeeping. The concept was that Morton Salt - unlike regular salt of the day - poured without clumps, even in damp weather. The company added magnesium carbonate as an absorbing agent to ensure that its table salt poured freely (it had since been changed to calcium silicate).

At first, the advertising agency suggested "Even in rainy weather, it flows freely" as the company's motto. Morton felt that it was too long, and the motto was changed to the catchier "When it Rains it Pours."

Like I said, fun stuff.

Thanks to @perrybelcher for the link.

Like Christmas For Dell

Dude, Dell's making out from me, big time! Check it out: I'm shipping them a laptop, hard drive, memory and even a CD image of Vista. Generous, no?

I've hit the end of my diagnostic rope with Dell, and am sending the laptop, plus all the crap they sent me to fix my laptop, back to them.

How much you want to bet their repair center sends it back to me with a big: Can't reproduce the problem sticker on it.

C'mon Dell, don't let me down on this one!

The only good news is that I don't need to send them the hard drive back, so at least I won't have to go through a rebuilding session again. Whew.

Friday, January 23, 2009

Quote Of The Day

What, are they opening a shoe store here?

Said by my Grandpa as he walked into our house for the first visit in years. Apparently, our legendary number of shoes kept in the front hall wasn't a good thing to him.

I love grandpa, he can get away with saying anything.

Update: My bro said:

Warm up the grill and get out the scotch, Grampa's in the house, and we're going to make the most of it.

Amen! I couldn't have said it better myself.

Thursday, January 22, 2009

Gotcha Of The Day: Shira's Dell Laptop Having Network Woes

For some time, Shira's noticed that networking on her relatively new Dell Laptop is flaky. She'll visit a site, say weather.com and the browser will hang. She'll hit reload, and it will load more or less immediately.

She tried out different browsers, including IE, Firefox and Chrome and had the results in all of them. What the heck was going on?

Last night and today and tackled the problem. First, I tried one of the most fundamental networking tests - a ping. Ping times the round trip life of a packet and confirms it didn't get lost along the way. In this case, I pinged my wireless router like so:

C:\Users\ben>ping -n 100 192.168.0.1

Pinging 192.168.0.1 with 32 bytes of data:
Reply from 192.168.0.1: bytes=32 time=3ms TTL=127
Reply from 192.168.0.1: bytes=32 time=5ms TTL=127
Reply from 192.168.0.1: bytes=32 time=4ms TTL=127
Reply from 192.168.0.1: bytes=32 time=3ms TTL=127
...

I chose to ping my wireless router, as all packets need to go through there before hitting the Internet at large. While most of the packets hit the local router quickly (like they did in my test above), some actually timed out. This is surprising, as the packet doesn't have all that far to travel - just to my basement - and didn't have any other hosts to travel through.

If a connection as basic as this is having problems, my thought was that the cause had to be pretty fundamental.

Using my Dell knowledge, I visited support.dell.com and entered in Shira's laptop's service tag (found relatively inconveniently on the bottom of the unit, but, I digress).

I then scrolled down till I found the section that mentioned her wireless card. I attempted to download the latest driver, but that didn't work as I ended up at some odd Dell FTP site. I then retried with Internet Explorer, instead of Firefox, and it downloaded like a champ. I ran the executable and rebooted.

I then repeated the test above, and there were no dropped packets. Surfing around the Internet, things seemed fast.

It's probably too early to declare this issue totally solved. But, at least I confirmed that there's no longer packet loss doing something as simple as pinging my router. I also saved myself a phone call to dell by using their support site. So, all in all, I'm pretty happy.

This problem could have been solved a whole lot faster if I remembered Windows Hardware Rule #1: When in doubt - upgrade the driver.

Wednesday, January 21, 2009

What's a crappy photo worth?

Liz, a friend on Facebook, linked to this article, which includes a perfect photo of Obama at the Youth Ball last night. What's perfect about it is that every single member of the audience appears to be taking a camera phone snapshot of Obama at the same time.

The author of the article laments that people were spending too much time capturing the moment instead of actually enjoying it. And besides, the crappy photo you get won't be nearly as nice as the ones available just a few hours later, so why bother?

It's an interesting point. In fact, part of it I can totally agree with.

Yesterday at the inauguration, I made a special effort to twitter the event. I thought it might be useful to have a blow-by-blow history of what happened, say 20 years from now. But, the reality is that I'm not a court reporter and trying to capture the event thoroughly is just frustratingly impossible. Like the author eluded to, you can end up worrying more about what you are capturing than actually remembering to enjoy yourself.

I also tend to run into this when I travel. I want to record everything I see and do, because it's all interesting. But, again, I'm not a travel writer and don't plan to become one. So, when on vacation I remind myself that the purpose of blogging is to capture some of the interesting stuff, not to capture the full record.

So, I agree with the article, you can take it too far.

But, I disagree that your own personal photo is either unnecessary, or can somehow be replaced by professionally done one.

Consider this crude recording I did at the U2 concert I was at years ago. When you listen to it, you'll hear a terribly fuzzy recording. When I listen to it, I can close my eyes and be transformed back to that evening in the Verizon Center, swaying with my wife as Bono played for thousands of us.

In other words, this crude audio recording is a hook into a memory. When I listen to U2 on the radio, it doesn't evoke those kind of memories. It can't.

I'm guessing the same will be true of the crappy recording I did at the inauguration as well as the photos. Imagine showing my grand kids these photos and recording? Sure, the professionally done photos will be nicer, but the cruddy photos are all mine. I suppose it's the difference between a public history and a personal history.

This whole notion of keeping a person history is nothing new. It didn't start with camera phones or blogging. Those are just tools - really this is just the act of keeping a journal.

With that in mind, when I look at the photo of the audience snapping a camera phone shot of the President, I don't see people trying to replace CNN, I see people capturing memories; ones that they'll look back on with friends and families and cherish.

Watching Obama Become President

Here's a video I shot yesterday, as I stood with millions on the mall and watched Obama become president:

This was one happy crowd.

Tuesday, January 20, 2009

2009 Inauguration - A Chilly Adventure

What a day! It started at 5:30am as David and I headed down to the DC mall area to watch the inauguration and to meet up with Greg.

We stood on the mall from about 7:00am till 11:30am, when the festivities began.

The crowd was in a good mood, and was generally fun to hang out with. We were all a bit chilly, but were layered enough that none of us suffered too bad in the 20 degree weather.

We could see the Capitol off in the distance, but watched the ceremony itself on the jumbotron. So, while the view wasn't that impressive, the crowds and energy more than made up for it.

The only hostility came out was when Bush took the stage. There were definite boos, and even a chant of Naahh, Naahhh, Nahhh, Hey, Hey, Hey, Goodbye. Even Jimmy Carter got a loud applause. Of course, Clinton got a rousing greeting from the crowd.

Trying to get out of the city was a little trickier than arriving. There seemed to be a lack of crowd control as the masses tried to cross the street, ending up with a thick mess of people pushing in different directions. But even that passed, and we made it out of the city pretty uneventfully.

All in all, it was a wonderful experience. One I plan to never repeat, but still wonderful. Here are some photos:

A Ben's Eye View Of The Inauguration

In just over 4 hours I'll be waking up to head to the inauguration. It's just me and about 2 million other people. I'm planning to Twitter what I see, so you can keep up with me by following along with @LiveOnLocation.

You can also read the messages below.

Between the walking, cold, lack of food, inability to bring a backpack full of goodies, security and general lack of planning I've done - this will probably not be pretty. But, at the very least, it's going to be an adventure!

Wish me luck!

Gotcha Of The Day: Vista Doesn't Recognize My Canon SD630

Ever since I've had a digital camera, my preferred way to get photos off it is to plug the memory card into a cheap memory card reader. These handy little devices mean you don't need to fuss with cables and camera drivers.

Though, lately, I realized that it might be easier to just plug my Canon SD630 right into the computer via the USB cord I have handily available.

I did this a few weeks ago, and nothing happened. I didn't get the usual chirps and beeps that the computer recognized a device. I got nothing. I futzed with it for a few more seconds and then gave up.

Today I tried again, and still, no luck. What the heck? I Googled around and Microsoft claims the camera is compatible with Vista. It pointed me to Canon's to download the driver, yet the site said none were needed.

Again, what the heck?

Then, in a moment of brilliance, I both plugged the camera in and TURNED IT ON. All of a sudden, the computer started chirping and beeping and instantly found my photos.

D'oh. When in doubt, hit the on switch. Don't I feel like a genius.

The I2X Company Chef

Sure, Google may offer all sorts of fancy benefits like one site car wash, dry cleaning, massage therapy, gym, hair stylist, fitness classes and bike repair. And of course, free lunch and dinner. But, they've got nothing on us in the chef department.

We may not be big, but we've got our own company chef - Chef David:

While the job pays no salary or benefits, it does provide free access to whatever's in the fridge and the rights to crash on the couch whenever you want.

After the CFO, you're the most valuable member of the team.

I just have to remember to update my elevator pitch to something like:

Ideas2Executables is a tiny company that specializes in taking your software idea and making it real. We're located in Arlington, VA and the company consists of myself (I do the coding), my wife (she does the business side of things) and my brother (he's the chef).

If that doesn't land us more business, I don't know what will?

Sunday, January 18, 2009

Inaugural Concert - Close, But Not Quite

Shira was a trooper today, and head down to the National Mall to try to catch the Inaugural Concert. Unfortunately, it wasn't meant to be.

We made it downtown without any problem, and then stood in a massive line for over an hour:

As we inched closer to the security entrance, the line we were in disintegrated. Apparently, the Fire Marshall had closed down the entrance, as the line had become more or less out of control, with people being pushed up against the entrance. We asked around, and two other entrances had been closed, leaving one option left. With the thousands and thousands of people, it became clear that we weren't getting in.

It's amazing, a campaign that could run a 50 state effort couldn't manage to keep lines from falling apart. Someone needed to take a lesson from Disney Land, and setup some barriers or even tape.

We headed back home at that point, and had few crowds to contend with. Though, I think this video captures the situation well:

There are two things to note:

  • Notice how the street is filled with a mass of people? Only a 15 seconds earlier, there was no one in the street - order was being kept by one traffic guard telling people to stay on the sidewalk. As you can see, the massive crowd filled in the street in no time.
  • This video was shot at 2:00'ish. The concert was either beginning or about to begin. All these folks you see have absolutely no chance of getting in to see anything. These are effectively the late attendees - imagine how many people were already there?

It was certainly a spectacle to see. We then watched the concert from the comfort of our own home. Warm and toasty and without a nasty commute home. I guess all worked out in the end.

Saturday, January 17, 2009

Best Wine Description Ever

So, yesterday, I'm shopping for a bottle of wine to bring as a gift. I'm clueless, so I'm standing in the store Googling various bottles that have attractive labels (brilliant method, eh.).

This is by far the best description I've found:

Purchase FRANCIS COPPOL ASYRAH /SHIRAZ DIAMOND SERIES GREEN LABEL
750ML
...
Aroma: Plum and clove intertwine on the nose Palate: Like its French cousin, thissyrah offers hints of rich bacon fat, ripe blackberry, jammy boysenberry, black currant, violet and vanilla flavors. Supple and balanced, notes of cinnamon and chocolate peek through on the finish.

Yes, ladies and gentlemen, wine with a hint of "rich bacon fat." Yum.

Who thinks up this stuff?

Anyone have any wines they can recommend for a gift?

--Ben

Thursday, January 15, 2009

The Picture That's Louder Than The News Broadcasts

Yikes, a plane just crashed into the Hudson river. And while the new stations are running their usual chatter, I think this one photo says it all.

And, yes, the photo came from a guy on Twitter.

Amazing stuff, actually. I just hope everyone makes it out OK.

Update: Oh, and in case you were wondering, the US Airways page has already been updated with the incident. Amazing. Also, a USAirways user has just popped up, though they don't have a lot to say. Note to businesses: get your company's Twitter account setup and ready for incidents (even if they aren't life threatening), today - before you have a PR disaster on your hands.

Verizon's Network Strikes Again

They've done it before, and they're doing it again - Verizon has sent out their Network to follow a guy around.

There's just something entertaining about these videos. I just can't help but smile throughout them - see what I mean:

Thanks to Anna for the site recommendation!

With Programming Languages, All Publicity Is Good Publicity

As the PLT-Scheme mailing list pointed out, Scheme was recently featured in an interview with developer who worked on a large real world system. The only catch, he was developing nasty AdWare. He explained:

S: You wrote adware. You bastard.

M: [sheepishly] Yes, I did. I got to write half of it in Scheme, which probably means that I deployed more Scheme runtime than anybody else on the planet.
...
There was also of course Scheme. Eventually, we got sick of writing a new C program every time we wanted to go kick somebody off of a machine. Everybody said, “What we need is something configurable.” I said, “Let’s install a Turing-complete language,” and for that I used tinyScheme, which is a BSD licensed, very small, very fast implementation of Scheme that can be compiled down into about a 20K executable if you know what you’re doing.

Eventually, instead of writing individual executables every time a worm came out, I would just write some Scheme code, put that up on the server, and then immediately all sorts of things would go dark. It amounted to a distributed code war on a 4-10 million-node network.

If you ignore the fact that he's probably responsible for making your computer slow to a crawl, it's a good read, and a good endorsement.

I've actually had on my list for some time the idea of integrating TinyScheme and PHP. Imagine, the speed and libraries of PHP, and the code clarity of Scheme. It's a winner, right? I bet it's not all that hard to do, either.

I think this is proof that Evil Genius's not only prefer Linux, they also prefer Scheme.

Wednesday, January 14, 2009

A Truly Simple Stock API

I would have thought that stock quote API's would be everywhere. It seems like getting a stock quote is among the most obvious 3rd party services out there. Yet, when I needed to find one, I was at a loss.

There's the Google Finance API - but that seems overkill. It will get information about a stock portfolio. But, what if I don't want a portfolio? What if I just want to know what the current price of a stock is?

Yahoo also has a finance developer section. But, theirs is focused on giving you RSS feeds for company information. Interesting, but again, if all I want to know is the current price of a stock - this doesn't help.

After much poking around, I found that Yahoo does offer a solution. It's even a refreshingly simple one. You can get stock data in CSV format by hitting the following URL:

  http://finance.yahoo.com/d/quotes.csv?s=RHT+MSFT&f=sb2b3jk

Which in this case, returns:

"RHT",15.50,14.74,7.50,24.84
"MSFT",19.62,19.58,17.50,35.00

More generally, the URL has the parameter s which takes in stock symbols (which would be space URL encoded - or + separated), and f is set to a format string. If you visit this page you can see all the format string options.

I'm a little bit confused by Yahoo doesn't advertise this capability more. But, it seems there and just what I need, so I may end up using.

Seeing It In Action

Here's some trivial code to grab back stock quotes using Scheme

(require (planet neil/csv:1:2/csv)
         net/url)

(define-struct sq (symbol price last-closed opened) #:prefab)
  
(define (stock-quote stock-symbol)
  (let ([url (format "http://download.finance.yahoo.com/d/quotes.csv?s=~a&f=sl1po" stock-symbol)])
    (apply make-sq (first (csv->list (port->string (get-pure-port (string->url url))))))))

With the stock-quote function defined, you can say:

 (define q1 (stock-quote "MSFT"))
 (printf "Current price: ~a\n" (sq-price q1))

Definitely not rocket science. But, pulling down a CSV feed from a URL and cramming it into a data structure shouldn't be. It should be easy, and as the above code shows, it is.

Tuesday, January 13, 2009

What The Internet Knows

On the lighter side - two things the internet knows:

There, I feel better.

Flow Where Flow Shouldn't Exist

I'm making my way through Finding Flow, a book by the psychologist who came up with the term Flow. Flow is that amazing mental state where you are totally in the zone. Time passes and you don't notice. You don't get hungry. You're just 100% focused on a task. Life is good.

The book, to put it kindly, hasn't been all that easy of a read. I think Csíkszentmihályi is being especially thorough, which can come off as being long winded.

But, having said that, there's an insight I read from him just the other day that knocked my socks off.

First, let's assume that ideally at work and at play you're in a state of flow. If that's the case, then an 8 hour work day, will just whiz right by. That's considerably better than 8 long hours. Of course, not every moment can be spent in Flow, as there are specific conditions that need to be met. For example, you need to have specific goals at a balanced level of difficulty (if the task is too easy, you'll find it boring, if it's too hard, you'll get frustrated - just right, and you're a candidate for Flow).

Now suppose you have a job where you never get into Flow. In other words, you're job sucks. What can you do. Of course, Csíkszentmihályi acknowledges you can quit. And if your job always sucked, then you probably should. But, what if you just have a few parts of your job that suck. You could delegate/outsource what you don't want to do. Again, this is a fine approach, but what if you can't.

What knocked my socks off is how Csíkszentmihályi demonstrated that you can in fact tweak the tasks you don't like, and turn them into ones you can find Flow in. This is probably best explained with an example:

George Klein, a tumor biologist who heads a renowned research department at Karolinksa Institute in Stockholm, illustrates how such people approach their work.
...
Klein likes what he does enormously, yet there are two aspects of his job he hates. One is waiting at airport terminals, which he has to do often because of his very busy schedule of international meetings. The other aspect he detests is writing the inevitable grant proposals to government agencies that provide the funding for his research team. These two boring tasks were depleting his psychic energy, and building up dissatisfaction with his work. Yet, they could not be avoided. Then Klein had a flash of inspiration: What if he combined these two tasks? If he could write grant applications while waiting for planes, he would save half the time previously devoted to boring tasks. To implement this strategy he bought the best pocket tape recorder he could find, and stated to dictate grant proposals while waiting or inching forward at airport custom lines. These aspects of his job are still objectively what they were before, but because he took control Klein transformed them almost into a game. It is now a challenge to dictate as much as possible while waiting, and instead of feeling that he is wasting time at a boring task, he feels energized.

I just love this approach. Instead of assuming that tasks are fundamentally boring or exciting, Csíkszentmihályi shows that it's the approach you take that controls this. It's certainly not a new concept - in fact, "boring" was a word not ever to be used growing up - but it's one that can't be said enough.

I've been on the lookout for tasks that I'm not finding Flow in, and taking Klein and Csíkszentmihályi's lessons to heart.

Just recently I had to copy and paste around a whole bunch of SQL - a task that was definitely not going to be fun, and probably quite error prone. Instead, I learned about a new code generation technique, that made the task an exciting and Flow induced one. As a programmer, I guess I'm especially lucky, as I can frequently exchange one task (copying and pasting code) for a variation of the that task (generating the code instead). However, as Csíkszentmihályi shows, this concept isn't limited to one field.

When it comes down to it, you're in control, By tweaking the approach you take to the work you do, you can vastly control your level of enjoyment with it. Remember that next time you're having a crappy day.

Update: So it occurs to me, nearly all of the above words can be boiled down to:

Happiness is controlled by both what you do and how you do it. Not happy and can't change the what? Then change the how. Either way, you can find happiness (aka Flow).

Monday, January 12, 2009

This Just Might Be Reality Based Government

I especially liked the report and video released on Obama economic stimulus plan. Essentially, the output of studying the proposal a scientific context, rather than a purely political one.

The report attempts to show clearly and concisely what they are trying to accomplish and who is affected. The very existence of the report shows that while they are trying to get the stimulus package in place quickly, they are putting thought into it. In short, they are demonstrating common sense. Something our government doesn't always do.

I thought Obama's comments on stimulus package this weekend further emphasized this reality based politics approach. My favorite quote being:

We don't have pride of authorship [in the package]. There are a couple of basic principles that I laid out. ... But -- just to finish the point, if people have better ideas on certain provisions, if they say, you know, this is going to work better than that, then we welcome that.

In other words, he has principles he wants to stick to, but is at the same time open to new ideas. This is good. This is sane.

Watch the video and see what I mean. This is going to be really interesting to see if the ideas that have been laid out can manage to survive the actual law making process...should be fun to watch.

Saturday, January 10, 2009

Why don't they just stop with the rockets?

The Israel-Palestine conflict has a long and complicated back story. But, it seems to me, this latest crisis is pretty straightforward: Israel is fed up with Hamas launching rockets into their country, and Hamas - for reasons I don't yet understand - feels that they need to do this.

And from what I can tell, that's not really the problem. The problem is all the civilians that are caught in the middle. And with good reason, the photos alone are horrific.

The world is demanding Israel to stop the attack.

But, what about Hamas' role? After all, they aren't just some fringe group. They are the elected government. This is both their people and their rockets. Haven't they made the decision that to hurl 30 rockets into Israel is more important than welfare of their own population?

Could it be that Gold Meir was right when she said: "Peace will come when the Arabs will love their children more than they hate us."

Hamas may not think it's fair how severe the attacks from Israel are, but they continue, on a daily basis to provoke them. Why? What kind of government could be that cruel to their own people?

Friday, January 09, 2009

Burger King - King of the Viral?

Burger King has arguably done it again - create a viral marketing campaign that's wildly popular. This time, it's Whopper Sacrifice. The idea behind this campaign: dump 10 of your friends on Facebook, get a free Whopper.

But this isn't the first time they've done this. Nope, I remember back in April of 2004, Burger King announced the Subservient Chicken Website. To show that you could have chicken Your Way, they provided a site where you could type in commands ("jump up and down") and a guy in a chicken suit would respond.

Sounds silly, but it was pretty impressive in terms of creativity and hilarity.

If you look at these two campaigns, they share some common elements:

  • They are both quite unique. Sure, you could use Facebook to send your buddy a burger or something - but the whole idea of deleting friends, that's whacky. And a guy in a chicken suit, online, to advertise chicken? Seriously, who thinks of this stuff. Once Burger King came out with their campaigns, others followed suit - but it was too late, Burger King had been first.
  • They are both demonstrate technical difficulty. Nowadays we think nothing of video on the web, but the idea of streaming video in '04 was still novel. In general, both campaigns have a How'd they do that?! feel to them.
  • Both campaigns are risky. There's something fundamentally naughty about ordering around a guy in a chicken suit. And ditching your friends, that's hardly nice. But, this risk has certainly paid off. Burger King is dealing with this riskiness now with their latest TV campaign - and maybe it backfires.

So there you have it: unique, a technical tricky and risky. I'm not sure if that's the recipe for a winning viral campaign, but it seems like a good start.

PowerPoint Time Saver - Setting default text box properties

I don't like bullets in PowerPoint (though, I do like their cousin, Smart Art). So, I find myself frequently dropping text boxes around the page (hopefully mixed in with images and other visually stimulating things).

Today, while working on a development plan for a project, I finally got fed up with having to create a new text box and then set the font size to 12pt, instead of the default 18pt (I was making a printable document, not a presentation - hence the small font size).

Turns out, setting the default font size couldn't be easier. Just drop some text in place, then right mouse click on the text box:

Be careful - if you select the text and right mouse click, you'll get a different (and wrong) menu than you just click once on the text box to get a frame around it.

This will save the font color, size and other attributes. A definite time saver.

Thursday, January 08, 2009

Getting Fancy With Twitter

Today I discovered TweeteLater.com. It's a service that sits on top of Twitter and ads some nice feature. You can schedule posts (well, technically, "tweets") in the future, as well as auto follow people who follow you. It even allows you to send an automatic direct message to new followers.

These are neat features, but for most people, they probably aren't all that interesting. Twitter typically has a discussion / real time feel to it, why would you want to schedule posts in the future?

For me, on the other hand, I use Twitter as my "Corporate Blog" for my business. It allows me to publish news and tips like I would on a blog, but at 140 characters it's not nearly as much of a time commitment.

Using Twitter in this way also has a couple of added benefits. First, Twitter makes it easy to spread your update feed around using the industry standard RSS format. This means I can put company news on my website, Facebook and other pages with a minimum of fuss. Twitter also brings in the notion of subscriptions, allowing my company updates to be delivered to interested individuals, rather than just sitting on a web page somewhere.

For folks like me, TweetLater.com is powerful stuff. I can write a couple of blog posts and let them drip out over time.

I may use the auto follow functionality, as it's generally courteous to follow those who follow you. And finally, the auto Direct Message is actually my chance to send a sort of: "Hi, thanks for following me? Have an idea for software, we should talk!" message to everyone who follows me. It's yet another chance to pitch my business. I'm not sure how excited I am about this, but I'm considering it.

If you're like me, you've seen people use the above features - well, turns out there's nothing to it. Just a quick sign-up process and you're off and tweeting.

See you on Twitter as @i2x.

Getting Things Done Hilarity

I really enjoyed reading Diary of a Self-Help Dropout in the latest issue of Wired magazine. In this article, Chris Hardwick takes readers through attempts to implement various self help philosophies, including: Getting Things Done, Never Check Your E-mail In The Morning and The Four Hour Work Week.

The results are not only educational (yes, I should read and maybe even adopt some of the mentioned material) but also quite hilarious.

One of these days I'm going to devise my own Getting Things Done Strategy, and I'll write a book about it. While I haven't gotten it figured out completely, it will definitely emphasize Flow and include plenty of Slack. It will include a mandatory waiting period before dealing with some tasks (or until acceptance is reached on them). It will also have a required sabbath (read: day when you don't do any work), though it won't have to be Saturday. In terms of tools, it will leverage both paper and online. It'll have a clever name, and a very, very, very small following.

I know, one more thing to add to my todo list...

Wednesday, January 07, 2009

Jon Stewart , Gaza, And the search I wish I hadn't done

I really wish I hadn't done this. I was goofing around with Google's Blog Search and tried:

[inposttitle:gaza jon stewart]

This brought up post after post of Jon Stewart being praised for his latest comments on the war in Gaza. This is the same clip that I got nauseated from watching.

Take a watch:

To summarize, Stewart chose to string clips together that showed the US as ignoring Palestinians, and blindly supporting Israel.

Let me say, I have no problem with Jon being hard on Israel, and US / Israel relations. No country deserves a blank check. And yes, there's definitely some absurdity to the clips of US politicians they put together. But what about absurdity on the other side? Like, say how Hamas uses a Masque to store their ammunition, forcing Israel to choose between not protecting itself, and destroying a sacred place? Or how about how Hamas is storing explosives in their own people's residences? And what about the absurdity of Isreal dropping leaflets and calling homes it's going to bomb - I mean really, is that any way to run a war?

And maybe, just maybe, the reason so many US politicians can back Israel is because in this case it's not really that far a stretch? Heck the EU President called the "act defensive, not offensive." Look, Hamas lobbed 10,000+ rockets at Israel over the years, there was a cease fire, Hamas broke it, and Israel defended itself. Is that such a far political stretch?

I think Ari Shavit said it well:

The Israeli offensive in Gaza is justified. It was launched following incessant and intolerable provocations by Hamas. Nevertheless, the fighting in Gaza is causing humanitarian disasters. However unintentionally, it is nevertheless also hurting innocents. Therefore, the Israeli government has an obligation to complement the aerial operation and the ground operation with a humanitarian one.

Now, am I going to boycott The Daily Show? Of course not. Jon is a comedian and he makes a living out of creating a context from one that didn't previously exist. Usually it's very funny. And I suppose when you don't agree with the context, it isn't. Either way, it's powerful stuff. And he's still a powerfully funny man.

Man, I wish I had never done that blog search.

My Digital Dance Instructor

No question about it, I have Annabelle The Sheep to thank for all my dance moves. As music visualizations go, can you really go better than Annabelle?

Say what you want about The Real Player, at least they have a good sense of humor about their software.

See Annabelle rock out...

A Scheme Application Configuration Strategy

I've developing a Scheme app for a client, and of course, the people he's selling it to want customizations. Some of the customizations were pretty basic and I simply stored them in a prefab structure on disk.

Lately he's picked up a client that wants all sorts of random'ish customizations - from changes in labels on the screen to application functionality. Storing this information in a structure just wasn't going to work. I needed a more dynamic and scalable approach. Here's the rough idea I came up with.

First, every client can have their own customizer function. The implementation of each client's customizer is in their own scheme module. A customizer has the signature:

(define (foo-customer-customizer key default)
 ...)

We'll come back to how these arguments are used in just a moment. To make the customizer available to the rest of the code, I make use of a paramter, which is a kind of cleaner approach to global variables. At the beginning of my application, I effectively say:

(define the-customizer
  (make-parameter (match customer-name
                    ["foo" foo-customer-customizer]
                    ...)))

Finally, let's define a helper function so we don't need to see the-customizer throughout our code:

(define (cv key default)
 ((the-customizer) key default)))

OK, now we can get to the interesting stuff. Let's look at how this can be used. Let's say I want to customize a button on the Welcome screen, I can say:

(new button% [label (cv '(welcome-screen enter-button) "Welcome")] ...)

And suppose I'd like to change what happens when the hits the exit button:

(new button% [callback (lambda (b e)
                         (let ([f (cv '(application exit-button action) quit)])
                           (f)))] ...)

Or perhaps the customer likes to see people's name in all upper case:

 (define choices (map (cv '(format names) identity)
                          (get-user-names)))

You might need to customize the value based on some context, such as whether a row is odd or even:

(for-each (lambda (row-number row-value)
            ((cv `(ui table format ,row-number ,row-value) list) 
             row-number row-value))
          (get-row-numbers)
          (get-row-values))

Here's how this customer's customizer could be implemented:

(require scheme/match)
(define (foo-customer-customizer key default)
  (match key
    [`(welcome-screen enter-button) "Ahoy-hoy"]
    [`(application exit-button action) 
      (lambda () (ask-user "Are you sure?" ...) ...)]
    [`(format-names) string-upcase]
    [`(ui table format ,row-number ,row-value)
      (if (odd? row-number) (handle-odd-row row-value) (handle-even-row row-value))]
    ;; No match for our key, choose to return the default  
    [_ default]))

I realize that this isn't exactly rocket science, but there were a few aspects of this solution I was especially happy with:

  • Adding in new configuration points using (cv ...) was easy to do
  • The list notation for a key (ui table format ...) turned out to be both natural and extensible
  • Having functions be first class values here absolutely makes all the difference. Instead of being limited to customizing strings, I can customize pretty much anything I want.
  • The customer's customizer functions turned out relatively clean, with no need to try to account for every customized value in the system.
  • The use of (match ...) was absolutely key, as it allowed me to skip writing a special parser for configuration values. The fact that it handles including values along with constant data, such as `(format ui table ,row-number) makes it especially flexible.

When it comes down to it, this solution could have been written in any language, yet it turned out to be quite naturally done in Scheme.

Tuesday, January 06, 2009

Handy Design Site: Common Mac and Windows Web Fonts

I was exchanging e-mail with a designer yesterday, and the topic of standard web fonts came up. I know the list of reliable web fonts is pretty short, but I realized I didn't have a website that spelled out exactly what they were.

I do now. This article lays it all out for you. Here's a sample:

It even organizes the fonts into CSS font-families. So, us non-Mac people will know to enter:

 h1 {
   font-family: Impact, Charcoal, sans-serif;
 }

To end up with:

Text That Impacts

The site is simple, clear and just what I needed.

Monday, January 05, 2009

5 Windows Vista New Year's Resolutions

So, my New Year's present to myself was a fresh install of Vista. I've decided I'm going to roll with this and try to make the best of it. Here are 5 things I'm going to try differently this time around:

  • I will learn to love Windows Gadgets. I think the magic here is the Windows + Spacebar key combination which brings all the gadgets into view. This means that I can have a 1 click dashboard to the world, or something like that.
  • I will resist temptation and not disable User Account Controls. Yes, it means more annoying Are you sure? questions from Vista, but it's time I took their security seriously instead of just turning it all off and winging it.
  • I will start using the user directory structure proposed by Vista. Microsoft finally dropped the "My" from "My Documents," and related folders, which was both silly (who's documents were they, if not mine?) and added a unnecessary space to the file name. If they are going to grow up a little, I should play along.
  • I will use the Windows Backup and Restore Center to create nightly backups. I always claim I'm going to get my backup-strategy-act together, and I never do. Now, Vista has made it drop dead simple - I will follow their lead and embrace them.
  • I will read more Vista help documentation, to do things like learn new key combinations and ways to tweak the UI so it works better for me. You can teach an old Unix geek new tricks. Any suggestions for sites I should be reading for tips?

What else should I be embracing about Vista?

Oh, and just in case you think I've totally lost my mind, I still do 90% of my work in a cygwin rxvt and an emacs buffer.

Coping With An Unexpected Laptop Outage

To make a very long story short, my conversations with Dell have left me with my same old laptop, but a new hard drive. The result, I started off this first real work day of the year with a laptop with no software on it.

This wasn't good. Here's what made it less painful...

  • Having documents, calendar and my e-mail all in Google Apps means that the crash didn't effect any of these. I simply pointed the web browser to the right URL, and I was instantly back in business. Sure, the Spreadsheet and Docs tools are somewhat crude, but they really pay dividends in situations like this.
  • The above is also true for my TODO list and customer notes, which I store on a secure wiki. Again, having this information online means it's accessible from any device, including a freshly installed version of Windows.
  • Having a list of software tools I use made it a little easier to grab the key ones I needed. It also contains some specific URLs to somewhat hard to find utilities like sitecopy and GNU screen.
  • The issue I ran in to, we believe, was a hard drive that has some issues. Luckily, the drive is still usable enough so I can mount it. I purchased a BlacX hot swapping SATA docking station. This is a fancy way of saying I bought a device I can literally (gently) drop my hard drive into and see it from my built compute r. It's awesome. It's well worth the $60.00, to be able to easily see and copy files from my old computer as I need them.
  • Finally, Low Fat Moose Tracks and Reddi Wip definitely played a critical role in keeping me sane during this process. When in doubt, have another bowl of ice cream.

So far, the new system is coming together relatively well. I may even get some real work done today. Wouldn't that be nice?

Gotcha Of The Day: Moving MySQL's data directory between machines

I'm suffering from some laptop woes, and a as a result, I'm working this morning on a different laptop than my usual one.

To save time getting up to speed on the temporary laptop, I thought I would copy the database files from the old machine to the new one. That way, I wouldn't have to recreate the databases for the apps I was working on.

This turned out to be slightly easier said than done. But, after putting up with some arcane error messages, I was off an running.

Here's what I went through...

  • I shut down the MySQL service on the temporary laptop
  • I moved my current data directory out of the way to something like C:/Program Files/MySQL/MySQL Server 5.0/data.orig
  • Using cygwin, I copied the files in place from the currently broken laptop. You'll notice I had the broken laptop's hard drive mounted on F:/
     cd /cygdrive/f/Program\ Files/MySQL/MySQL\ Server\ 5.0/
     tar cf - data | (cd /cygdrive/c/Program\ Files/MySQL/MySQL\ Server\ 5.0/ ; tar xvf - )
    
  • I then attempted to start up the MySQL service and it failed.

This is when things started getting annoying. For some reason, MySQL wasn't writing a .err file to the data directory, so I couldn't even get a lot message explaining what was broken. After much poking around, I realized that I had a permission problem - apparently, the above tar command worked too well, writing files as user Ben instead of Administrator. I then ran the following commands:

 cd /cygdrive/c/Program\ Files/MySQL/MySQL\ Server\ 5.0/
 chmod -R a+rwX data
 chown -R administrator data

This, of course, explains why a .err file wasn't being written to the data directory. The process lacked the permissions to do so. Duh.

Now when I attempted to start up MySQL, it failed, but gave me the following error message:

InnoDB: Error: log file .\ib_logfile0 is of different size 0 25165824 bytes
InnoDB: than specified in the .cnf file 0 26214400 bytes!
090105  9:01:30 [ERROR] Default storage engine (InnoDB) is not available
090105  9:01:30 [ERROR] Aborting

Huh?

I looked through my.ini (my guess as to the .cnf file it was talking about) and the only value that jumped out at me was:

 innodb_log_file_size=25M

I updated this value to be:

  innodb_log_file_size=25165824

And Holy Smokes! the server started up. I'm able to get into the database and all looks Kosher.

Bottom line: you can copy around the data directory in MySQL (at least between Windows boxes and the same server version), you just need to be willing to chase around a handful of issues before it can be expected to all work.

Sunday, January 04, 2009

Currying For The Working Programmer - Why Bother?

Grant asked a good question - why should the working programmer care about Currying?

Here's my answer...


For me, the practical side of currying has to do with providing some arguments to a function, while leaving others unset*. The result is a new function that takes in just the unset arguments. This may not sound very useful, but as the example below attempts to show, it can actually be quite handy.

My suggestion is to read up on SRFI 26 and make it one of the standard tools you use.

#lang scheme

;; Scheme doesn't offer automatic currying, but SRFI-26 provides
;; the (cut ...) operator which gets us close enough.
(require srfi/26)

;; A function to send e-mail. This is a bogus implementation,
;; could easily be a "real" implementation
(define (send-mail smtp-host smtp-port from to subject message)
  (printf "Would have sent a message: \n")
  (printf "  SMTP server: ~a:~a\n" smtp-host smtp-port)
  (printf "  From: ~a\n" from)
  (printf "  To: ~a\n" to)
  (printf "  Subject: ~a\n" subject)
  (printf "  Message: ~a\n" message))

;; A place holder function to return a list of e-mail addresses. Used
;; for testing below.
(define (list-of-emails)
  '("foo@nowhere.com" "bar@nowhere.com" "baz@nowhere.com"))

;; Let's start currying...

;; EXAMPLE 1
;; Here we provide two arguments to our send-mail function, and leave
;; 3 unset (<> serves as a place holder). The result of this is a those
;; function that takes in just  3 remaining arguments.
;;
;; Now we can use `mailer' throughout our application and not have to worry about providing
;; the SMTP host and port.
(define mailer (cut send-mail "mail.myhost.com" 25 "noreply@myhost.com" <> <> <>))

;; Use our mailer
(mailer "example@nowhere.com" "Hello World" "This is just a test...")

;; EXAMPLE 2
;; Let's say we want to send the same message over and over again. We can use (cut ...) to
;; provide every argument but the to address.  Notice how we can operate on our already curried
;; function.
(define broadcaster (cut mailer <> "A Special offer, Just For You" "Here's a special offer, sent only to you. We promise..."))

;; Use our broadcaster
(for-each broadcaster
          (list-of-emails))

;; EXAMPLE 3
;; We can provide all the arguments except for a message, and turn our mail 
;; function into a logger.
(define logger (cut mailer "logging@nowhere.com" "Log Message" <>))

;; Pretend this is some complicated function
(define (something-complicated logger)
  (logger "Starting to do something complicated...")
  (void)
  (logger "Whew, and we're done."))
(something-complicated logger)

*Note: true currying involves converting a N argument function into a series of 1 argument functions. So, the example I provieded isn't currying in the formal sense. But, hey, I happen to think it's close enough.

Update: Thanks to Jens Axel for reminding me that I left various < and > improperly escaped in the post, thereby making it impossible to cut and paste. D'oh.