<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Tom Moertel's Weblog: Tag programming</title>
    <link>http://blog.moertel.com/articles/tag/programming?tag=programming</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Quality rants on programming theory and stuff geeks like</description>
    <item>
      <title>That looks about right</title>
      <description>&lt;p&gt;Via &lt;a href="http://www.cwinters.com/news/display/3624"&gt;Chris&lt;/a&gt;:&lt;/p&gt;


&lt;pre&gt;$ history | awk '{print $2}' | sort | uniq -c | sort -rn | head
    196 git
    110 l
    102 cd
     70 make
     34 darcs
     30 pushd
     23 ssh
     23 m
     23 ls
     20 rm
&lt;/pre&gt;

	&lt;p&gt;The &lt;em&gt;l&lt;/em&gt; and &lt;em&gt;m&lt;/em&gt; commands are aliases:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;em&gt;l&lt;/em&gt; = &lt;em&gt;ls &amp;#8211;CF&lt;/em&gt;&lt;/li&gt;
		&lt;li&gt;&lt;em&gt;m&lt;/em&gt; = &lt;em&gt;less&lt;/em&gt;&lt;/li&gt;
	&lt;/ul&gt;</description>
      <pubDate>Fri, 11 Apr 2008 11:58:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:8c556b83-dcaa-4044-9f0f-7af434f6f3f7</guid>
      <author>Tom Moertel</author>
      <link>http://blog.moertel.com/articles/2008/04/11/that-looks-about-right</link>
      <category>interesting stuff</category>
      <category>programming</category>
      <category>life</category>
      <category>memes</category>
      <trackback:ping>http://blog.moertel.com/articles/trackback/715</trackback:ping>
    </item>
    <item>
      <title>Cost-reducing interfaces should be the focus</title>
      <description>&lt;p&gt;I have been following with interest the debate about &amp;#8220;humane&amp;#8221; 
vs. &amp;#8220;minimal&amp;#8221; interfaces, sparked recently by &lt;a href="http://www.cafeaulait.org/oldnews/news2005December6.html"&gt;Elliotte Rusty Harold&amp;#8217;s
response&lt;/a&gt; to
&lt;a href="http://martinfowler.com/bliki/HumaneInterface.html"&gt;Martin Fowler&amp;#8217;s HumaneInterface
post&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Harold writes:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;Martin Fowler&amp;#8217;s a really smart guy, and he&amp;#8217;s pretty reliably
right; but today he manages to get it 180° wrong. &lt;span class="caps"&gt;A 78&lt;/span&gt; method List
class is about three times as bad as a 25 method List class, not three
times as good. &lt;span class="caps"&gt;A 12&lt;/span&gt; method List class would be about twice as
good. Simplicity is a virtue for both users and implementers. There&amp;#8217;s
simply no reason for 78 methods in a basic List class.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;The problem with Harold&amp;#8217;s argument is that he is using the
wrong goodness metric.  His metric is interface complexity when
it ought to be overall cost.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Cost is what counts.&lt;/strong&gt;  If adding methods (or making any change, for that matter) reduces the overall cost of
getting legitimate work done, it&amp;#8217;s the right thing to do.  That&amp;#8217;s
all there is to it.&lt;/p&gt;


	&lt;p&gt;Yes, adding methods to a library increases complexity and thus
increases the cost of understanding and using the library.
Adding methods to a library means asking users to make a small
investment of their time and mental capacity in exchange for the
promise of a later return &amp;#8211; clarity and code savings.  The duty of a
library designer, then, is to make sure that this return is
worthwhile, that the additions are useful enough and used frequently
enough to pay for themselves.&lt;/p&gt;


	&lt;p&gt;In &lt;a href="http://www.cafeaulait.org/oldnews/news2005December8.html"&gt;a later post&lt;/a&gt;,
Harold implicitly acknowledges the does-it-pay-for-itself test when he lists some methods from &lt;a href="http://www.ruby-doc.org/core/classes/Array.html"&gt;Ruby&amp;#8217;s Array class&lt;/a&gt; that he thinks are unjustified.  He writes:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;Do you really need any of [these methods] getting in your way?
Possibly you need one or two of these methods; but how often, and how
many?&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;The thing is, I use many of the methods he lists.  Further, the ones I
don&amp;#8217;t use don&amp;#8217;t seem to get in my way.  In sum, those methods have
paid me back far more than I have invested in them.  Given this, why &lt;em&gt;shouldn&amp;#8217;t&lt;/em&gt; they be in the Array class?&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m not saying that &amp;#8220;humane&amp;#8221; interfaces are better.  Rather, I&amp;#8217;m
saying that &lt;strong&gt;focusing on &amp;#8220;humane&amp;#8221; vs. &amp;#8220;minimal&amp;#8221; is missing the forest for
the trees.&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;Cost is what matters, so why shouldn&amp;#8217;t it be the focus?  Who cares if
that focus leads us to a &amp;#8220;humane&amp;#8221; interface one time and a &amp;#8220;minimal&amp;#8221; 
interface another?  With cost as our guide, we&amp;#8217;ll always arrive at a
good interface.&lt;/p&gt;</description>
      <pubDate>Thu, 08 Dec 2005 17:35:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:487847a070f866c536cf21a3e6103796</guid>
      <author>Tom Moertel</author>
      <link>http://blog.moertel.com/articles/2005/12/08/cost-reducing-interfaces-should-be-the-focus</link>
      <category>programming</category>
      <category>cost</category>
      <category>interfaces</category>
      <category>programming</category>
      <category>minimal</category>
      <category>humane</category>
      <trackback:ping>http://blog.moertel.com/articles/trackback/21</trackback:ping>
    </item>
    <item>
      <title>Closures and the professional programmer</title>
      <description>&lt;p&gt;I came across &lt;a href="http://www.tbray.org/ongoing/When/200x/2005/08/27/Ruby"&gt;Tim Bray&amp;#8217;s thoughts on
Ruby&lt;/a&gt; via
the ever-delightful &lt;a href="http://lambda-the-ultimate.org/node/view/934"&gt;Lambda the Ultimate&lt;/a&gt; and found the following bit fascinating:&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;I&amp;#8217;ve had access to languages with closures and continuations and
suchlike constructs for years and years, and I&amp;#8217;ve never ever written
one. While I&amp;#8217;m impressed by how natural this stuff is in Ruby, &lt;em&gt;I&amp;#8217;m
still unconvinced that these are a necessary part of the professional
programmer&amp;#8217;s arsenal.&lt;/em&gt; [Emphasis mine.]&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;While Tim Bray may be unconvinced, I am a true believer.&lt;/p&gt;&lt;p&gt;I use closures so much that I feel cheated into doing busy work by
languages that do not support them.  I use continuations less often
but frequently enough to appreciate how much time they save me.
Neither is strictly required for professional work, but they are
potent tools, and a professional who knows how to use them has an
advantage over those who do not.&lt;/p&gt;


	&lt;p&gt;Closures, in particular, are something every professional ought to
master.  Besides their more celebrated uses, closures make refactoring practical on a small scale.  For
example, consider the following Ruby method, which we will assume is
one of several similar methods belonging to a class that implements some kind of Internet server:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;process&lt;/span&gt;
  &lt;span class="ident"&gt;sn&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;next_serial&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
  &lt;span class="ident"&gt;log&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;info&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;process/&lt;span class="expr"&gt;#{sn}&lt;/span&gt;: stage 1&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="comment"&gt;# ... do some work&lt;/span&gt;
  &lt;span class="ident"&gt;log&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;info&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;process/&lt;span class="expr"&gt;#{sn}&lt;/span&gt;: stage 2&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="comment"&gt;# ... do some more work&lt;/span&gt;
  &lt;span class="ident"&gt;log&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;info&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;process/&lt;span class="expr"&gt;#{sn}&lt;/span&gt;: finished&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The method first gets a unique serial number, which is used during the processing of requests and also to relate log entries generated by the same processing call.  Then the method does its work, logging each stage in passing.&lt;/p&gt;


	&lt;p&gt;The method makes three logging calls that each hardcode the logger, the logging level, and the format of the log entries.  Since these things are repetitive and could very well change, we probably ought to factor them out into an isolated method.  After all, we don&amp;#8217;t want to rewrite a bucket of logging calls if the log-entry format changes.&lt;/p&gt;


	&lt;p&gt;Let&amp;#8217;s introduce a helper method &lt;em&gt;mylog&lt;/em&gt; to hold the common pieces:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;process&lt;/span&gt;
  &lt;span class="ident"&gt;sn&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;next_serial&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
  &lt;span class="ident"&gt;mylog&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;process&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="ident"&gt;sn&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;stage 1&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
  &lt;span class="comment"&gt;# ... do some work&lt;/span&gt;
  &lt;span class="ident"&gt;mylog&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;process&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="ident"&gt;sn&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;stage 2&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
  &lt;span class="comment"&gt;# ... do some more work&lt;/span&gt;
  &lt;span class="ident"&gt;mylog&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;process&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="ident"&gt;sn&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;finished&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;mylog&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;activity&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;sn&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;msg&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;log&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;info&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="expr"&gt;#{activity}&lt;/span&gt;/&lt;span class="expr"&gt;#{sn}&lt;/span&gt; &lt;span class="expr"&gt;#{msg}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;While we managed to isolate the logger, the logging level, and the
format of our logging messages, just &lt;em&gt;calling&lt;/em&gt; our helper method &lt;em&gt;mylog&lt;/em&gt; still
requires much redundancy.  Worse, the redundancy is on such a low
level that we can&amp;#8217;t factor it out with another helper method &amp;#8211; calling
the new helper would be as expensive and redundant as calling &lt;em&gt;mylog&lt;/em&gt;
directly.&lt;/p&gt;


	&lt;p&gt;What we need are refactoring tools that scale down to this sub-method level, and
that&amp;#8217;s where closures come to the rescue.  Using them, we can corral
the remaining redundancy with a local logging helper &lt;em&gt;llog&lt;/em&gt; that &amp;#8220;closes
over&amp;#8221; the relevant state:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;process&lt;/span&gt;
  &lt;span class="ident"&gt;sn&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;next_serial&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
  &lt;span class="ident"&gt;llog&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;s&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;mylog&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;process&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="ident"&gt;sn&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;s&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
  &lt;span class="ident"&gt;llog&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;stage 1&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;]&lt;/span&gt;
  &lt;span class="comment"&gt;# ... do some work&lt;/span&gt;
  &lt;span class="ident"&gt;llog&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;stage 2&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;]&lt;/span&gt;
  &lt;span class="comment"&gt;# ... do some more work&lt;/span&gt;
  &lt;span class="ident"&gt;llog&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;finished&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;]&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Notice how much simpler and less redundant the logging code is?  Each stage can now be logged just by giving its name to &lt;em&gt;llog&lt;/em&gt;.  We don&amp;#8217;t need to pass in the activity name or serial number because &lt;em&gt;llog&lt;/em&gt; already knows them both.  It knows the activity name because we made it part of &lt;em&gt;llog&lt;/em&gt;&amp;#8217;s definition, but it knows the serial number because &lt;em&gt;sn&lt;/em&gt; is captured in &lt;em&gt;llog&lt;/em&gt;&amp;#8217;s closure &amp;#8211; for free.  (Note: If &lt;em&gt;f&lt;/em&gt; is a &lt;tt&gt;Proc&lt;/tt&gt; object, &lt;em&gt;f&lt;/em&gt;[&lt;em&gt;args&lt;/em&gt;] is syntactic sugar for &lt;em&gt;f&lt;/em&gt;&lt;tt&gt;.call&lt;/tt&gt;(&lt;em&gt;args&lt;/em&gt;).)&lt;/p&gt;


	&lt;p&gt;Of course, if we have several methods that require a unique serial
number and a corresponding logger, we could (thanks to closures)
factor things further:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;process&lt;/span&gt;
  &lt;span class="ident"&gt;sn&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;llog&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;next_serial_and_logger&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;process&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
  &lt;span class="ident"&gt;llog&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;stage 1&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;]&lt;/span&gt;
  &lt;span class="comment"&gt;# ... do some work&lt;/span&gt;
  &lt;span class="ident"&gt;llog&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;stage 2&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;]&lt;/span&gt;
  &lt;span class="comment"&gt;# ... do some more work&lt;/span&gt;
  &lt;span class="ident"&gt;llog&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;finished&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;]&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;next_serial_and_logger&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;activity&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="ident"&gt;sn&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;next_serial&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
  &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;sn&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;s&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;mylog&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;activity&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;sn&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;s&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;}]&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;You get the point: Closures reduce the cost of working with local
state because they capture it implicitly.  There is no need to pass
the state back and forth; it&amp;#8217;s simply there.&lt;/p&gt;


	&lt;p&gt;Because the craft of programming is dominated by writing the stuff
&lt;em&gt;inside&lt;/em&gt; of methods, where local state lives, the potential benefits
of closures are immense.  If more programmers knew how to use them,
the profession would be richer for it.&lt;/p&gt;


&lt;div class="update"&gt;
&lt;p&gt;&lt;strong&gt;Update 2006-01-11:&lt;/strong&gt; First, because this article is getting renewed interest, I have turned the comments back on. Second, I edited the article to improve clarity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2007-05-04:&lt;/strong&gt; Added syntax highlighting to code snippets.&lt;/p&gt;
&lt;/div&gt;</description>
      <pubDate>Tue, 30 Aug 2005 14:56:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:4433a298ab264c9e20e1d5853ee5b250</guid>
      <author>Tom Moertel</author>
      <link>http://blog.moertel.com/articles/2005/08/30/closures-and-the-professional-programmer</link>
      <category>programming</category>
      <category>functional programming</category>
      <category>programming languages</category>
      <category>ruby</category>
      <category>ruby</category>
      <category>programming</category>
      <category>closures</category>
      <trackback:ping>http://blog.moertel.com/articles/trackback/3</trackback:ping>
    </item>
  </channel>
</rss>
