Wednesday, March 18, 2009

Using Extension Methods to Verify Assumptions

I was working on something with Tim yesterday, and between us we came up with what I think is a pretty cool trick. We were defining some extension methods on XElement and friends that make it easier to work work XHTML. Something like this:

doc.Html().Div(“foo”).Div(“bar”).Value

Which would pull out the text content of a div with a class of “bar” that was a descendant of a div with a class of “foo”. All well and good, but one of the problems we were trying to address is that we didn’t want to proceed if there was no div of class “foo”. A NullReferenceException would be thrown, but we wanted something more specific. So we came up with this:

public static T OrThrow<T>(this T obj, Exception e) {
    if (obj == null) {
        throw e; 
    } 
    return obj;
}

Which in turn allowed us to write this:

doc.Html().Div(“foo”).OrThrow(new MyException(“no foo”)).Div(“bar”).Value

The clever bit is that the OrThrow extension method is generic on the type it’s invoked on, and it returns that type, so you can insert it into a chained expression and you don’t lose any intellisense. And because of type inference, you don’t actually have to specify the type (you don’t have to type OrThrow<IEnumerable<XElement>>), which cleans up the expression a bit.

This approach is more general than just XHTML, of course. Really, it allows you to insert arbitrary assertions/checks into a series of chained calls using a fairly natural syntax (for some value of “natural”). Nothing you can’t do other ways, but we liked the way this came out enough to want to share it.

Friday, February 13, 2009

Hard Links in Windows Do Not Update Immediately

I was pretty excited when I saw mklink appear. Filesystem links can solve a lot of annoying problems, which is why you see them used all over the place in Unixy systems. Although, like salt, the key is to use them sparingly.

Which is why I’m so annoyed that the Windows version is pretty much completely useless. Soft links are only recognized in some contexts, but hard links are the real offender. Try this from an elevated command prompt:

> cd C:\temp
> echo foo > a.txt
> mklink /h C:\temp\hard-a.txt C:\temp\a.txt
> more hard-a.txt
foo

So far, so good. Now try this:

> echo more >> a.txt
> more hard-a.txt
foo
> more a.txt
foo
more
> more hard-a.txt
foo
more

WTF? My hard link doesn’t update immediately? That sucks!

From experimentation, it seems that it only updates after you’ve actually accessed the link once. Since one of the things I’d like to do is hardlink files into my Dropbox synchronization directory, this is pretty much a non-starter – they’ll never appear to be updated, and therefore will never sync. Unless I visit every file, which is pointless, because if I was going to do that, I could just copy them. Which is what I’m trying to avoid.

I’m more than willing to believe I’m missing something here, but if so I don’t know what it is. My best guess is that this is a bug in the filesystem caching code (I’m on Windows 2008).

Days like this make me want to switch full-time to my Ubuntu machine. Also not perfect, but at least the novelty makes me less sensitive to its shortcomings.

Monday, January 5, 2009

What Is All the Fuss About How You Can Write DSLs in Lisp?

I saw Chris’s recent post, and felt compelled to respond, despite the fact that I’m pretty sure I’m going to regret it. :)

Here’s what he says, abridged:

(when (and (< time 20:00)
                   (timing-is-right))
      (trade (make-shares 100 x)))

IMO, that's not a DSL -- that's just a set of function calls in an existing language.

The short version of my response to this is: “Yes! Exactly! That’s a feature, not a bug!” On to the longer version.

This argument, as a question of semantics, is fundamentally doomed to remain unresolved, unless someone can magically provide an exact definition of DSL that a) has no imprecision, and b) everyone agrees with. I’ll just pass on waiting for that to happen, and make my own observation:

A set of function calls in an existing language is generally preferable to a completely separate language. Particularly if it’s the language that you’re using to write the rest of your system. Sure, there are cases where using a specialized language is the thing to do, but over the last few years I’ve come to have a lot more - what’s the word? respect? fear? caution? – anyway hesitance around introducing additional languages into the development process. It’s not rare to see C#, SQL, XSLT, XPath, NAnt XML, regular expressions, and four or five other grammars floating around in the development lifecycle of a single process, and it’s got a real price. If nothing else, it means that not everyone can work on every part of the system. Throw in the fact that some of those are hard to debug, or have conflicting metaphors, or different performance characteristics, and it adds up.

So yes, one of the reasons that I’m excited about Clojure is that it’s a Lisp, and as a Lisp it is flexible enough to adapt to the point where I often don’t need a DSL. Or, if you like, where my DSL is also a Lisp. That doesn’t mean “I never want to use a DSL” or “I always want to use Lisp” – all things in moderation. It certainly doesn’t mean “You shouldn’t use M” – how the hell would I know what you need? But for me, I think it’s nice to have a tool that gives me the choice.

Wednesday, December 31, 2008

2008 – The Year in Review

It’s the end of the year, and although I skipped 2007, it is my habit to take a look back here on matters personal and professional. To whit:

I blogged a lot less this year. There are a number of reasons for that. The main one is that I’m just not as interested in blogging as once I was. I think that comes with the increasing “inward focus” my career has taken. I just find that more and more, what matters to me is what matters to me, not what matters to everyone else. That’s not a judgement or a boast, just an observation. It’s quite liberating: for example, I can go look at weird languages (see below) and not worry about it too much. :)

If you really can’t get enough Craig, you can always try me in appetizer size over on my Twitter stream. I seem better able to post a few dozen characters than a few paragraphs these days.

Career-wise, 2008 continued the shift I started in 2007 away from lots of small projects towards one big one. If I remember right, by the end of 2006 I’d worked on about seven different open source and proprietary projects, at a max of something like five simultaneously. That was too much, and I was feeling burned out. These days, pretty much all my professional time goes to a contract at Microsoft, where I’m working on the next version of Visual Studio. That has been very interesting for a variety of reasons, not the least of which is that it’s related to the work I’ve done on the MSDN REST Web Service.

Of course, the most significant event of 2008 had nothing to do with web services: it was the birth of our second child, daughter Susan. She was a cranky newborn, but has since turned into a charming and active baby. Needless to say, having two kids has really changed my life. I’m still coming to terms with giving up my free time – a painful process for me.

Not that I have no free time, of course. If I had none, I wouldn’t have been able to train for and run a marathon. But maybe I shouldn’t have talked so much smack in that post – Engberg whupped me good, and now I have to run another one. I think maybe this time I’ll make qualifying for Boston my stretch goal. Along the way, I’d also like to run a sub-20:00 5K. That’s much more my type of thing – I’m a fast runner, not an endurance runner.

This year saw my fascination with Lisp continue and even deepen, as is obvious from a variety of posts here. My latest interest on the parentheses front is Clojure. I made one (sort-of) provocative post about it, promised to say more, and never did. Well, given how not into blogging I am lately, I’m not sure whether I ever will live up to that promise. So go check it out for yourself: it really is an awesome language. Stu’s book is a good way to get started.

Here at the cusp of the new year, I don’t really know what 2009 will hold for me. I have a pretty good idea that the Microsoft work will continue for a while, but of course as an independent there’s always an increased level of uncertainty. But I like to think that it’s a rare problem that doesn’t yield an opportunity, so I’m optimistic.

On the family front, obviously we’re looking forward to watching both kids continue to grow and flourish. 2009 will be Ellen’s last full year of preschool, and of course Susan will likely start walking, talking, and doing all sorts of things. We hope to take family trips to Taiwan, Hong Kong, and Alaska, too.

On the professional front, I really want to spend more time working with Clojure. I’ve got some ideas for some real apps I can write, since that is, after all, the only true way to learn a language or platform. Plus it gives me a chance to run Ubuntu regularly, which I’ve been enjoying as a departure from the ordinary. (Clojure runs on Windows just fine, BTW.)

In the personal realm there are the running goals I mentioned earlier. I also hope to continue to fly Falcon, and maybe even DCS: Black Shark, which looks really sweet. If I somehow magically find extra time, and the basement finally gets finished, maybe I’ll even start playing bass and/or drums again.

Wishing you all the best in the new year.

Wednesday, November 19, 2008

A C# REPL (in Clojure)

It’s no secret that I’ve been interested in Lisp for quite a while. Lately, that has meant Clojure. Clojure is a new Lisp dialect that runs on top of the JVM. That means it has the power of Lisp (macros, dynamic typing, etc.) combined with the power of the JVM. The synergy reminds me of an old bumper sticker I saw years ago: “C: combining the speed of assembly with the power of assembly.” We’ve moved on a bit since then, but still. :)

Anyway, you should check out Clojure. It is easily the most exciting technology I’ve seen in years…probably since I first saw .NET in June of 2000. Even beyond just being a Lisp that actually has vast libraries (one of the main complaints against Lisps of the past) is the fact that there are some truly brilliant features of the language above and beyond what other Lisps sport.

One of the cool things I’d heard was that Clojure will run on top of IKVM.NET, which is a .NET implementation of the JVM. I figured that if there were a reasonable story for .NET interop, I’d be able to use Clojure to drive .NET code in a REPL. A REPL is a Read-Eval-Print Loop, which is a fancy way of saying “an interactive programming command line”. It’s like the immediate window in the Visual Studio debugger on steroids, and its absence is one of the increasing number of things that makes C# painful to use as I gain proficiency in more advanced languages.

Yes, I said it: C# is not an advanced language. If you think it is, then in my opinion you don’t know enough programming languages yet. :)

Intentionally provocative statements aside, here’s how you do it:

  1. Download and unzip ikvm.net. No installer required.
  2. Download Clojure. I recommend grabbing the head of the Subversion tree rather than the release that’s on the website.
  3. Build Clojure by running “ant jar” in the clojure directory. You’ll have to install Ant to do this if you haven’t already.
  4. Run “ikvmstub mscorlib.dll” to create mscorlib.jar, which will create the Java wrapper classes for the stuff in mscorlib.
  5. Launch a Clojure REPL via “ikvm –cp \path\to\clojure.jar;\path\to\mscorlib.jar clojure.lang.Repl”.

Now you have a working REPL, in which all the types in mscorlib are available to be driven by Clojure, which is most definitely an advanced language. Here’s a very simple example (the results of running the commands are indicated by =>):

(import '(cli.System DateTime))
=> nil

(new DateTime)
=> #<DateTime 1/1/0001 12:00:00 AM>

(.get_Now DateTime)
=> #<DateTime 11/19/2008 2:31:02 PM>

(.ToString (new DateTime) "R")
=> "Mon, 01 Jan 0001 00:00:00 GMT"

You get the idea.

Of course this is probably only useful as an exploratory tool: if I were writing Clojure for real, I’d write it against the JVM, not against IKVM.NET. But I use the excellent SnippetCompiler all the time now, but it’s still not the quite same thing as a real REPL, so I’m excited to have a real REPL available.

And really, the reason I’m posting this is that I’m hoping it will be a sort of gateway drug for you, and that what this will really do is kick off your interest in Clojure itself. The website is a pretty good source of information, but you can also check out Stu Halloway’s Programming Clojure book. It’s available in Beta form here. I’ve been tech reviewing it, and even the early beta looks pretty good.

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)))