Sunday, October 26, 2008

MCM 2008 (Or, “Take That, Engberg”)

I just got done running the 2008 Marine Corps Marathon. My entry in this event was so full of drama, it belongs in a figure skating vignette.

The whole thing started a little over a year ago. I’d taken a fairly long break from running, and had hit the magic weight I’d set for myself that meant I had to start again. I’m a moderately serious runner, having done it since high school. At around the same time I was starting up, my neighbor Steve was talking about starting an exercise program. I convinced him to come out with me, despite the fact that he had never really run regularly before, and certainly not seriously. It was selfish, really: a running partner a few doors down is a precious resource.

Over the next few months, we slowly built up the mileage, doing first six miles, then seven, then longer and longer runs. With each one, Steve would exclaim at how he couldn’t believe he’d just run ten or twelve or whatever miles, and at how the slightly shorter one we’d done last week now seemed like an easy distance. Major credit to Steve: he stayed with it, even when we were running through the January sleet at 6AM.

Cut to six years earlier. I’d just finished running Grandma’s Marathon in a fairly reasonable time of 3:33. My oldest friend, Rob Engberg, had run the race as well, in a very respectable 3:48. I did the marathon “just to do one”, and was feeling beat up enough at the end of it to comment to Rob that I’d run one again if he beat my time. Rob is faster than me all other things being equal, but he is a self-admitted slacker, and I figured he’d never get motivated enough to train to the point where he could take down my time.

As these things do, this one sort of took on a life of its own. The years slid by and Rob ran a few more marathons but never repeated even his old time, let alone mine. And as also so often happens, the years erased the memory of pain and I started to contemplate doing another one. Plus, I figured it wasn’t fair for Rob at 40 to be chasing a time that I ran when I was about 30. So I told him we’d reset the clock every five years. And to make it interesting, we made it more of a bet: the loser has to post a picture of himself on his blog wearing a t-shirt of the winner’s design. In a public place. (Design suggestions welcome, BTW.)

So now that we’re both between 35 and 40, we’re into the second round. Rob ran a 4:07:03 this year, and that became my time to beat. So I convinced neighbor Steve to run the Marine Corps Marathon with me (and more importantly, to train for it with me). We signed up, and started an 18-week training program that culminated with the race today. That’s where the drama comes in.

Steve and I were running well. We had a good program and we followed it faithfully. After working out a few kinks (hint: over about 13 miles, you need to eat during a run), we were even blasting through our long runs in excellent form. Then came the 18-miler.

Running the 18 miles itself was fine. We ran on Sunday morning, and I didn’t even need to take a nap like I did after some of the previous long runs. When I saw Steve across the courtyard the next day, we traded a round of, “How you feeling? Great!” Then that evening I sat down next to my daughter to read her a story, and when I got up five minutes later, I felt like someone had shoved a stack of coins under the ball of my left foot. It happened that suddenly. I immediately went online and ordered new shoes, which I’d been meaning to do anyway, and went to bed. The next day, it was just as bad if not worse, and there was some bruising on my foot. I took Tuesday off of running, but came back at it Wednesday.

And the same damn thing happened – I was fine after the run, and the next day, it suddenly started hurting again. Only this time it didn’t get better.

To make a long story slightly shorter, I wound up having to take about eight weeks off of running. Several (rather expensive) visits to the doctor later, we had a tentative diagnosis of metatarsal capsulitis, which is Latin for “you hurt your foot”. I hit the stationary bike faithfully five times a week for an hour or two at a time, trying to keep up with my running. But as the weeks rolled by and I still couldn’t walk in regular shoes without limping, my hopes for competing dwindled. Meanwhile, Steve was plowing through the training by himself, including three runs of 20 miles or longer.

Finally, finally, my foot started to feel better. Just in time, too: I was able to resume my training with about a month to go before the race. If it had taken any longer, I probably would have given up, as running 26.2 miles takes a certain amount of preparation. I was doubly glad of the timing, because I got better just in time to compete in the Army Ten-Miler, which Steve and I had signed up for as a sort of warm-up race/workout. In fact, it was going to be our first longish run together.

More drama. As I walked out to meet up with Steve at 6AM on race morning, he told me that he couldn’t compete. The reason? “Dude, it feels like someone shoved a stack of coins under the ball of my foot.” Injury! Maybe even the same one!

So now, as it were, the shoe was on the other foot. I was left training by myself, and Steve was left wondering if he was going to recover in time for the marathon. It sucks, by the way, to not know. Both of us experienced the thought that if someone could just tell us we couldn’t run, that would have been better than just not knowing one way or the other.

Fortunately, race day saw us both ready to run. Unfortunately, a major miscommunication before the start meant that we never linked up during the race. So after all that, we both wound up running separately! But even that may have been for the best, as Steve ran with another neighbor of ours, and I was able to run a bit faster than I might have if I’d run with him, important because the only reason I was running the race was to screw over by buddy Rob.

The race itself sort of sucked. The weather was perfect, and it’s cool that the marathon winds through the various monuments in Washington DC, but I have to say that the course was completely inadequate to the number of people running on it. I’m not sure who thought it was a good idea to route 30,000 runners down two-lane roads, but I spent the first ten miles dodging around and between other runners, or getting pissed at being boxed in for the fiftieth time. Fortunately, it opened up after about ten and I was able to run a bit faster, but for the first hour and a half, I was sure I wasn’t even going to beat Rob’s 4:07, let alone run the sub-4:00 marathon I wanted to. The Marine Corps Marathon gets a C-minus – definitely not recommended.

So after all that, what was my time? Three hours, fifty minutes, eight seconds (a pace of 8:47 per mile). Rob, who lives in New Zealand, is running his marathon in about two weeks. It sounds like he’s actually be training for this one, but that time is only two minutes short of his best ever, which he ran when we were barely 30, not nearly 40. So it should be interesting. Me? I’m hoping he runs a 3:50:09. Because it would add to the drama. :)

Tuesday, October 7, 2008

typing-speed-mode Emacs Minor Mode

I’ve been really into Lisp lately, especially Clojure, which looks really interesting. More on that some other time, though. Anyway, I’m always looking for an excuse to write code in Lisp – any Lisp.

As I was writing some prose in emacs this morning, I got into a real flow. I started to wonder how fast I was typing…and there was my excuse! About an hour later, I had written the code below. It’s an emacs minor mode that displays your typing speed (defined as the number of times self-insert-command has been run in the last five seconds, times twelve) in the mode-line. So you can watch your typing speed go up and down in real time. Note that you can customize a few things about it, like changing the default five-second window.

My emacs-fu (and my Lisp-fu) is not all that it could be, so the code is likely suboptimal in several ways, but it seems to work, and I always hate it when people say, “I’ll post the code once I get a chance to clean it up.” To hell with that: enjoy my code for the garbage it is :). 

;;; typing-speed.el --- Minor mode which displays your typing speed

;; Copyright (C) 2008 Wangdera Corporation

;; Permission is hereby granted, free of charge, to any person
;; obtaining a copy of this software and associated documentation
;; files (the "Software"), to deal in the Software without
;; restriction, including without limitation the rights to use,
;; copy, modify, merge, publish, distribute, sublicense, and/or sell
;; copies of the Software, and to permit persons to whom the
;; Software is furnished to do so, subject to the following
;; conditions:

;; The above copyright notice and this permission notice shall be
;; included in all copies or substantial portions of the Software.

;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
;; OTHER DEALINGS IN THE SOFTWARE.

;; Author: Craig Andera <candera@wangdera.com>

;; Commentary: Invoke this minor mode to have your typing speed
;; continuously displayed in the mode line, in the format [75 WPM]
;; To use, just load this file and invoke (typing-speed-mode) or
;; (turn-on-typing-speed-mode)

(define-minor-mode typing-speed-mode
    "Displays your typing speed in the status bar."
  :lighter typing-speed-mode-text
  :group typing-speed
  (if typing-speed-mode
      (progn
    (add-hook 'post-command-hook 'typing-speed-post-command-hook)
    (setq typing-speed-event-queue '())
    (setq typing-speed-update-timer (run-with-timer 0 typing-speed-update-interval 'typing-speed-update)))
      (progn
    (remove-hook 'post-command-hook 'typing-speed-post-command-hook)
    (cancel-timer typing-speed-update-timer))))

(defcustom typing-speed-window 5
  "The window (in seconds) over which typing speed should be evaluated."
  :group 'typing-speed)

(defcustom typing-speed-mode-text-format " [%s WPM]"
  "A format string that controls how the typing speed is displayed in the mode line.
Must contain exactly one %s delimeter where the typing speed will be inserted."
  :group 'typing-speed)

(defcustom typing-speed-update-interval 1
  "How often the typing speed will update in the mode line, in seconds.
It will always also update after every command."
  :group 'typing-speed)

(defvar typing-speed-mode-text (format typing-speed-mode-text-format 0))
(defvar typing-speed-event-queue '())
(defvar typing-speed-update-timer nil)

(defun typing-speed-post-command-hook ()
  "When typing-speed-mode is enabled, fires after every command. If the
command is self-insert-command, log it as a keystroke and update the
typing speed."
  (if (eq this-command 'self-insert-command)
    (let ((current-time (float-time)))
      (push current-time typing-speed-event-queue)
      (typing-speed-update))))

(defun typing-speed-update ()
  "Calculate and display the typing speed."
  (let ((current-time (float-time)))
    (setq typing-speed-event-queue
      (typing-speed-remove-old-events
       (- current-time typing-speed-window)
       typing-speed-event-queue))
    (typing-speed-message-update)))

(defun typing-speed-message-update ()
  "Updates the status bar with the current typing speed"
  (let* ((chars-per-second (/ (length typing-speed-event-queue) (float typing-speed-window)))
     (chars-per-min (* chars-per-second 60))
     (words-per-min (/ chars-per-min 5)))
    (setq typing-speed-mode-text (format " [%s WPM]" (floor words-per-min)))
    (force-mode-line-update)))

(defun typing-speed-remove-old-events (threshold queue)
  "Removes events older than than the threshold (in seconds) from the specified queue"
  (if (or (null queue)
      (> threshold (car queue)))
      nil
      (cons (car queue)
        (typing-speed-remove-old-events threshold (cdr queue)))))

(defun turn-on-typing-speed ()
  "Turns on typing-speed-mode"
  (if (not typing-speed-mode)
      (typing-speed-mode)))

(defun turn-off-typing-speed ()
  "Turns off typing-speed-mode"
  (if typing-speed-mode
      (typing-speed-mode)))

Wednesday, October 1, 2008

You Think You Like Halloween?

I don’t think you like Halloween like this guy likes Halloween…

I’m glad to have helped in even a very small way.

Tuesday, September 9, 2008

Announcing Sudo for Windows

If you’ve used a Unix much, I’m sure you’re familiar with sudo, a command-line utility that lets you run things as the superuser. Not only it is very handy, but it is the basis for one of the better XKCD strips.

Sudo is one of those things I find myself wishing for in Windows, especially given the new(ish) UAC features in Vista/Windows 2008. There are lots of times when I just want to run something as administrator, dammit. Typing “sudo notepad2 C:\somewhere\foo.txt” would fit the bill.

I tried Sudo for Windows, but it made me type my password. That seemed silly, given that I don’t need to type my password anywhere else to run things elevated. There are probably other implementations of this out there, but it literally took less time to write my own than it would to crawl through all of them looking for the one I like best. All it does is execute whatever arguments get passed to it, but the program itself has the “require administrator” bit in the manifest, so the target program winds up running elevated as well.

Anyway, it’s in my arsenal. Visit here to get it in yours, too.

Wednesday, August 20, 2008

Announcing InhibitSS

Short story: I wrote a little tray app that will prevent your screensaver from running. Download it here.

Long story: I’ve been training for a marathon over the last few months, but a couple of weeks ago I hurt my foot and have been unable to run consistently. While I’m recovering (and hoping I’ll be well soon enough for me to be able to race), I’ve got to do something to keep in shape. One of the things I do is to ride my bike on a stationary trainer in front of the computer. While that works well, it’s a pain to unlock the screen if the screensaver kicks in while I’m pedaling, as it sometimes does. So I wrote InhibitSS, which runs in the tray and will prevent the screensaver from running, and therefore the screen from locking. Here’s what it looks like when it starts up:

Then, if you double-click it, it looks like this:

The red X indicates that the screensaver is inhibited.

I’m sure there are a dozen apps just like this. But this one has the feature that I had fun writing it. :)

Wednesday, July 9, 2008

C# Mixins

Update: Corrected terminology – it’s “generic functions” not “generic methods”.

Aside from macros, another nice feature that Lisp supports is mixins. In fact, this is one of the (very, very) few things I miss about C++. Of course, Lisp does it in a much more powerful way using something called generic functions. See here and here for a great description of generic functions in Common Lisp – it’s one of the cooler parts of Lisp, in my opinion, especially for someone like me who has come from a C++/C#/Java OO background.

Although not a tool for every occasion, and somewhat against the spirit of Inherit to Be Reused, Not to Reuse, mixins are nonetheless handy at times. Since mixins are generally implemented via multiple inheritance, they haven’t really been an option in C#…until extension methods came along. Now you can do something like this:

using System;

public interface TellNameMixin
{
    string Name { get; }
}

public static class MixinImplementation
{
    public static void TellName(this TellNameMixin subject, string prefix)
    {
        Console.WriteLine("My name is: {0}{1}", prefix, subject.Name);
    }
}

What we’ve done is to define an interface type and a corresponding extension method that adds functionality to that interface. Since any number of interfaces can be implemented on a type, we can apply our mixin to classes that have no other type relationship, or that already have a base class. Like this:

public class Craig : MarshalByRefObject, TellNameMixin
{
  public string Name { get { return "Craig"; } }
}

public class Program
{
  public static void Main()
  {
     Craig craig = new Craig();
     craig.TellName("Mr. "); // Prints “Mr. Craig”
  }
}

The best part about this is – as with all reuse mechanisms – there’s only one place where I have to change how TellName works. Obviously, if the Craig class was the only class I was extending, I could skip the mixin class and just use extension methods directly. But if I have additional types that I want to add this functionality to, and if those classes have no other type relationship (a situation I found myself in just today) then this might be handy.

Anyway, it’s not something you’ll use every day, but it’s worth knowing about.

Tuesday, July 8, 2008

Lisp, Too, Is Mainstream

You’ve seen me talk here before about the fact that I have been lately fascinated with Lisp. Sadly, I haven’t been able to spend the time I’d like with it, but I continue to read and think about it. And I’d really, really like to put in some serious time writing a real app (better: several) in Lisp.

So it was with great interest that I read Lisp, too, is mainstream. I like pretty much everything that Eric has written, and his LispCast screencasts are good, too. This article starts with Greenspun’s Tenth Rule (“Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp”) and extends it to a rather different conclusion:

My point is that it may be too late to start with Lisp so you don't have to reimplement all of its features. Because all of those new languages have already implemented them. At least what most people consider the important ones.

Or put another way:

I guess my point, through all this meandering, is that other languages did borrow a lot from Lisp. About half of it. And now those features are out there, in the world. And in the meantime, while they were borrowing, they got some new features of their own. Features like giant user bases, gazilions of libraries, corporate support, standards bodies. So Lisp has half of the features of Python. Java and Python are far from my ideal language---but so is Common Lisp. The idea that I would have to implement so much of Lisp on my own is a little overblown these days. And speaking of reimplementation: How much of Python's standard library does a complex Lisp program reimplement? How much of Python would you have to reimplement before you regret choosing Common Lisp?

And speaking specifically to macros, which I currently see as the single biggest weakness of C# when compared to Lisp:

Macros let you subsume more code into less code. Macros let you write more functionality with fewer lines. Macros let you abstract away boilerplate into new syntax.

But the corporate manager will say: if everyone writes their own syntax, my programmers can't read each other's code. So instead of having to learn a language once, they will have to learn a new language each time they approach a program for the first time. And the value of macros is lessened.

It’s enough to take the wind out of an aspiring Lisper’s sails. :) However, I haven’t given up yet. I have two questions that I still need to answer for myself before I draw any conclusions of my own.

  1. Is the value proposition of macros (i.e. custom syntax/DSLs) different for small teams? And particularly for stuff I read and write only for myself? Because I’ve got a lot of code that falls into those categories.
  2. Is the library situation really so dire? I find that I don’t actually wind up using third-party libraries all that much in C#, so either the BCL is extremely complete or the types of problems I’m solving are just naturally self-sufficient. Or I’m doing something wrong. :) Besides, when I cruise the Lisp sites, I actually see lots of libraries I could use. But maybe there’s some critical functionality that I’d have to write myself that would take a long time.

Of course, the answers to these questions are inherently highly subjective. Like pretty much any question touching on programming tools. If I can find a way to go write a fair amount of Lisp, I’ll get my answers. They will, however, be my answers. I’ll share them with you if I ever get there, but don’t expect them to help you much. :)