<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[recurs.es]]></title>
  <link href="http://recurs.es/atom.xml" rel="self"/>
  <link href="http://recurs.es/"/>
  <updated>2012-04-02T14:49:40-04:00</updated>
  <id>http://recurs.es/</id>
  <author>
    <name><![CDATA[Joe Fredette]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Bonsai and Elasticsearch and Tire]]></title>
    <link href="http://recurs.es/blog/2012/04/02/bonsai-and-elasticsearch-and-tire/"/>
    <updated>2012-04-02T14:32:00-04:00</updated>
    <id>http://recurs.es/blog/2012/04/02/bonsai-and-elasticsearch-and-tire</id>
    <content type="html"><![CDATA[<p>Working on a client project where we use a statically generated ElasticSearch
index. We recently noticed that <a href="http://bonsai.io/">bonsai.io</a> was available on
<a href="http://heroku.com/">heroku</a> for free public beta usage. Previously we
self-hosted on amazon. Obviously it&#8217;s nice to have everything in one place, so
we decided to move.</p>

<p>On the old system, we used <a href="http://github.com/karmi/tire">Tire</a> as to generate
the indicies and mappings, as well as to generate the correct query strings, and
to wrap the results of such queries into nice structures. Needless to say Tire
was doing some heavy lifting for us. In particular, we used it to bulk-populate
the indices, which made regenerating the indicies on demand very quick, which is
desirable when you&#8217;re trying to keep your publish times down.</p>

<p>One last important thing, Tire has an opinion about how you index models in your
system &#8211; one index per model. This means that multiple types of index for a
single model is possible &#8211; eg, having <code>searchserver.com/items/english/&lt;query&gt;</code>
and <code>searchserver.com/items/farsi/&lt;query&gt;</code> &#8211; in the event you wanted to
separate these &#8216;logical&#8217; indicies from elasticsearch&#8217;s notion of a &#8216;literal&#8217;
index[1].</p>

<p>Bonsai has another opinion &#8211; one &#8220;literal&#8221; index per <em>app</em>. Naturally, there is
some impedance to overcome.</p>

<p>To do this, I had to pull in two different changes from two lovely guys on the
githubs. First was <a href="https://github.com/karmi/tire/pull/194">this</a> pull request,
by <a href="https://github.com/dylanahsmith">dylanahsmith</a>, this implemented the &#8220;PUT&#8221;
mapping API, which allows for mappings per logical index (&#8216;type&#8217; in proper ES
terms). That got me halfway there, but bulk upload was also broken due to the
difference of opinion.</p>

<p>So I pulled in changes from <a href="https://github.com/Evan-M">Evan-M</a> which I found
via <a href="https://github.com/karmi/tire/issues/240">this</a> issue. This changes how you
configure tire to be aware of how bonsai does it&#8217;s indexing.</p>

<p>Once I pulled both of these changes in, I ran the tests &#8211; got 4 failures.
Fortunately, they&#8217;re the same 4 that are on master. To that end, I feel pretty
confident about using it, especially since it is a reasonably non-interacting
part of the app.</p>

<p>So, if you want to use my combined changes, you can find them
<a href="https://github.com/jfredett/tire">here</a> on the master branch. Be warned that
these may not be totally operational in every way. Our usecase is pretty small
in scope, so it&#8217;s use-at-your-own-risk.</p>

<p>[1] the &#8220;logical&#8221; and &#8220;literal&#8221; terms are mine. ES calls them &#8220;Indexes&#8221; and
&#8220;Types&#8221; &#8211; but I don&#8217;t think &#8220;type&#8221; is the right word for the thing.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Three Wrongs make me Syck]]></title>
    <link href="http://recurs.es/blog/2012/03/14/three-wrongs-make-me-syck/"/>
    <updated>2012-03-14T10:53:00-04:00</updated>
    <id>http://recurs.es/blog/2012/03/14/three-wrongs-make-me-syck</id>
    <content type="html"><![CDATA[<h2>In which I track down a bug to three causes</h2>

<p>I recently had to put this comment in a codebase for a client, to explain why
I&#8217;d written a task that did this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>    <span class="n">task</span> <span class="ss">:hack_yaml_parser</span> <span class="k">do</span>
</span><span class='line'>      <span class="no">YAML</span><span class="o">::</span><span class="no">ENGINE</span><span class="o">.</span><span class="n">yamler</span> <span class="o">=</span> <span class="s1">&#39;syck&#39;</span>
</span><span class='line'>    <span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>The text of the comment follows:</p>

<hr />

<p>This dodges a bug with httparty and neo4j and psych/syck. The rundown is thus:</p>

<p>Neo4j uses a bareword response for certain querys, which is valid JSON
in the world of the ECMA people, but not in the world of the RFC.</p>

<p>HTTParty can&#8217;t use the superior MultiJson library, because it
interprets (with some force) the RFC version, and thus can&#8217;t handle the
response. Therefore, it depends on the older, crustier &#8220;crack&#8221; JSON
library.</p>

<p>Crack uses a &#8211; unique &#8211; approach to parsing JSON. It munges the text
to be valid yaml, then defers it&#8217;s parsing to the ruby stdlib&#8217;s yaml
parser.</p>

<p>Ruby upgraded it&#8217;s YAML engine to &#8220;Psych&#8221;, which is based on libyaml
and very snappy.</p>

<p>Unfortunately, some of the YAML that crack generates is less than
perfect, so sometimes YAML.load throws a Psych::SyntaxError. Due to
what I can only describe as an extremely unfortunate mistake,
Psych::SyntaxError derives from SyntaxError, which follows up the chain
to ScriptError, Exception, and Object.</p>

<p>Astute readers of Avdi Grimm&#8217;s book &#8220;Exceptional Ruby&#8221; will note that
this means it&#8217;s not a subclass of StandardError, which means you cannot
rescue from it (because it is in the same class hierarchy as an actual
ruby syntax error).</p>

<p>So. You are left with an unrescueable syntax error. You can&#8217;t use the
parser that would dodge this because it causes worse issues (eg, you
can&#8217;t get single properties from a node). You can&#8217;t use the provided
library because it can&#8217;t parse without error. What&#8217;s a hacker to do?</p>

<p>Well, you can revert to the older &#8220;Syck&#8221; yaml parsing library. Which
happily accepts the failing cases, and generates <em>rescueable</em> errors
when it hits a YAML syntax bug.</p>

<p>Thus, this unfortunately terrible line of code is present to fix a bug
that all boils down to someone deriving from the wrong class, someone
else following the wrong rules, and a third person (you) being in the
wrong place, at the wrong time.</p>

<hr />

<p>So let this be a lesson, follow RFC&#8217;s, not communities if you can. Don&#8217;t derive
from the wrong class hierarchy, and try not to be in the wrong place at the
wrong time.</p>

<p>I spent <em>way</em> to much time on this.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Fear]]></title>
    <link href="http://recurs.es/blog/2011/12/19/fear/"/>
    <updated>2011-12-19T11:47:00-05:00</updated>
    <id>http://recurs.es/blog/2011/12/19/fear</id>
    <content type="html"><![CDATA[<h2>Fear</h2>

<p>I&#8217;m sitting in an airport right now, about to embark on a living embodiment of
fear.</p>

<p>I hate flying. Perhaps it&#8217;s just irrationality, or perhaps it&#8217;s that burden of
knowledge that there is a thousand-ton vehicle about to go careening down a
finite runway towards a seemingly-infinite ocean, only to, a few hours later,
come careening down towards another finite strip of asphalt at exceptional
speed. It&#8217;s just the physics that gets me. None of it seems at all safe &#8211; and
while I know that there are far fewer plane accidents than train or car
accidents each year, it doesn&#8217;t alleviate my terror at the prospect of breaking
up at thirty-two thousand feet above our little marble.</p>

<p>I also hate spiders, and needles, and probably more things than I have a right
to hate.</p>

<p>Suffice it that I am often afraid, almost always without cause. So why do I get
on the plane? Why do I keep going? If I am terrified, why don&#8217;t I just not do
any of it?</p>

<h2>Family</h2>

<p>So, I&#8217;m sitting here at Gate A-two-one &#8211; that&#8217;s what they keep saying, as if we
wouldn&#8217;t figure it out if they just said &#8220;A twenty-one&#8221; &#8211; awaiting this coach
of (what I imagine to be) death. I&#8217;m going to Sunny California, going to see my
inlaws. As I await my inevitable demise, I quietly think to myself, &#8220;Fucking
inlaws, if it weren&#8217;t for them, I could be home. Enjoying the cold and playing
video games.&#8221; I&#8217;m burning off the rest of my vacation time for the year, so I&#8217;d
be taking vacation in any case, but so motivated was I by that
pretty-lady-who-feeds-me, that here I await the reaper.</p>

<p>So I&#8217;m motivated to fly, against (perhaps) my better judgement (and
certainly against my will), but I will perservere to make that scary-wife-lady
happy, because it&#8217;s Christmas, and while Santa Clause and Jesus Christ may be
bullshit, my wife&#8217;s happiness isn&#8217;t. So how can I get through my fear? How can I
deal with the fact that in less than three hours, I&#8217;ll be hurtling through the
upper atmosphere?</p>

<h2>Finding Confidence</h2>

<p>When I&#8217;m coding, there are &#8211; many times &#8211; changes which need to be made, but
appear to be hard. Changes that are sweeping, changes that involve large
deletions, or philosophical changes to how the project is approached. Sometimes
it&#8217;s about using a new tool to solve an old problem. Sometimes it&#8217;s about
realizing a certain cross-cutting concern has been slicing into the codebase in
a nonoptimal way. It&#8217;s a hard change because the team might be against it, or
maybe the team is for it, but they don&#8217;t understand how the tool is &#8220;really&#8221;
supposed to be used.</p>

<p>Similar to flying, we are often motivated by necessity to make these changes,
but are hesitant due to fear. We&#8217;re afraid that the thing won&#8217;t work, that our
whole infrastructure will come tumbling down, that everything will generally go
to shit and we&#8217;ll get fired. Or worse, we <em>won&#8217;t</em> get fired, and will have to
live with the shame as we pick up the tattered peices of a product.</p>

<p>The risk may be great, and that risk is directly proportional to the fear it
induces, but I&#8217;m reminded of a quote from one of my favorite books:</p>

<blockquote><p>I must not fear.</p>

<p>Fear is the <em>mind-killer</em>.</p>

<p>Fear is the little-death that brings total obliteration.</p>

<p>I will face my fear.</p>

<p>I will <em>permit</em> it to pass over me and through me.</p>

<p>When it has gone past I will turn the inner eye to see its path.</p>

<p>Where the fear has gone there will be nothing.</p>

<p>Only I will remain.</p>

<p>&#8211; Bene Gesserit Litany against Fear, Dune, Frank Hebert</p></blockquote>

<p>The problem of rejecting risk due to induced fear is that &#8211; oftentimes &#8211; that
induced fear is phantasmal. It&#8217;s <em>not</em> going to crash and burn, it&#8217;s <em>not</em> going
to drive the company into the ground. In fact, the opposite &#8211; it will build the
company up.</p>

<h2>Make Fear Fuel</h2>

<p>I peruse, often, <a href="http://c2.com/cgi/wiki">Ward&#8217;s Wiki</a>. Amongst the thousands of
amazing articles, there is one which I dearly love &#8211;
<a href="http://c2.com/cgi/wiki?MakeFearFuel">MakeFearFuel</a>. In it, the argument is made
to &#8211; rather than shirk from risk due to fear &#8211; to embrace it for the same
reason. If you&#8217;re afraid of something, it&#8217;s natural, it&#8217;s okay. Fear is designed to
protect you. However, Fear is <em>not</em> designed to <em>paralyze you</em>. Fear is a tool
to enable you to run faster and further, to be more aware of your actions and
surroundings &#8211; these latter two especially are of great use to a programmer.
The fear from risk comes from the unknown &#8211; the inability to see all paths.
However, that self-same fear can be <em>harnessed</em>, and made to work <em>for</em> you, to
make your product better, to see further, to build something better.</p>

<p>As the article suggests, Don&#8217;t think of it as fear &#8211; but rather &#8211; excitement!
You must <em>permit</em> fear &#8211; not &#8216;allow&#8217; or &#8216;be okay with&#8217;, you are in control of
fear &#8211; to pass through you. Fear is subservient, not superior, and when you
understand the use of fear as fuel, and moreover, when you begin to apply it to
your life (and not just programming, but everywhere), I think you will find
yourself more amenable to making good changes, better at mitigating undue risk,
and better at recovering from problems when shit really does hit the fan.</p>

<p>For my part, I&#8217;m being called to board this black coach, to sit amongst my
brothers and sisters before death. I will not fear, fear is the mind-killer, I
will face my fear, and give fear the finger.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Lessons Learned: A Sortah Postmortem]]></title>
    <link href="http://recurs.es/blog/2011/12/16/lessons-learned-a-sortah-postmortem/"/>
    <updated>2011-12-16T17:27:00-05:00</updated>
    <id>http://recurs.es/blog/2011/12/16/lessons-learned-a-sortah-postmortem</id>
    <content type="html"><![CDATA[<h2>Ruby is flexible</h2>

<p>Flexible like a Russian Gymnast. Seriously, it was never more than a few moments
of thought to bend ruby to my will. Still, there were some wiggly tricks I had
to use to get some things to work, and there still are several things which need
fixing. For instance</p>

<figure class='code'><figcaption><span>This doesn&#8217;t work</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>    <span class="n">sortah</span> <span class="k">do</span>
</span><span class='line'>     <span class="c1">#...</span>
</span><span class='line'>
</span><span class='line'>      <span class="n">router</span> <span class="ss">:lenses</span> <span class="o">=&gt;</span> <span class="o">[</span><span class="ss">:foo</span><span class="o">]</span> <span class="k">do</span>
</span><span class='line'>        <span class="c1">#... </span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>This doesn&#8217;t work, presently you have to write it with <code>router :root, :lenses =&gt; [...]</code>
because the &#8220;parser&#8221; (mine, and in a way, the ruby parser) doesn&#8217;t know how to
handle an implicit first argument &#8211; that is, I need positional arguments, and
have to simulate them with defaulted arguments. This isn&#8217;t a new problem in
ruby, in fact, 2.0 is supposed to provide named arguments, which will make life
a bit nicer. One way I could get around this is to <del>hack</del> *cough* enhance the
parser to check the class of the first argument. So it would go from:</p>

<figure class='code'><figcaption><span>Current `router` parser from lib/sortah/util/component.rb</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>    <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="nb">name</span><span class="p">,</span> <span class="n">opts</span> <span class="o">=</span> <span class="p">{},</span> <span class="o">*</span><span class="n">potential_block</span><span class="p">)</span>
</span><span class='line'>      <span class="vi">@name</span> <span class="o">=</span> <span class="nb">name</span>
</span><span class='line'>      <span class="vi">@opts</span> <span class="o">=</span> <span class="n">opts</span>
</span><span class='line'>      <span class="vi">@block</span> <span class="o">=</span> <span class="n">potential_block</span><span class="o">.</span><span class="n">first</span> <span class="k">unless</span> <span class="n">potential_block</span><span class="o">.</span><span class="n">empty?</span>
</span><span class='line'>    <span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>to something like:</p>

<figure class='code'><figcaption><span>Current `router` parser</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>    <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="nb">name</span><span class="p">,</span> <span class="n">opts</span> <span class="o">=</span> <span class="p">{},</span> <span class="o">*</span><span class="n">potential_block</span><span class="p">)</span>
</span><span class='line'>      <span class="k">if</span> <span class="nb">name</span><span class="o">.</span><span class="n">is_a?</span> <span class="no">Hash</span>
</span><span class='line'>        <span class="vi">@opts</span> <span class="o">=</span> <span class="nb">name</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'>        <span class="vi">@name</span> <span class="o">=</span> <span class="nb">name</span>
</span><span class='line'>        <span class="vi">@opts</span> <span class="o">=</span> <span class="n">opts</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>      <span class="vi">@block</span> <span class="o">=</span> <span class="n">potential_block</span><span class="o">.</span><span class="n">first</span> <span class="k">unless</span> <span class="n">potential_block</span><span class="o">.</span><span class="n">empty?</span>
</span><span class='line'>    <span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>which would allow (I think) for defaulting. It might have issues with how I
extract the optional block, but that would require actually applying this &#8211;
which I&#8217;m not really willing to do. Mostly because it&#8217;s ugly, but also because
I&#8217;m not sure it&#8217;s so bad to have to specify that your root router is in fact a
root router when you want to run lenses. I think it makes more sense to <em>not
have lenses applied to the root router</em>. Here&#8217;s my reasoning.</p>

<p>Almost every lens you run is useful in a fairly limited context, For instance, I
may not want to share my spam filters between my personal email and my work
email &#8211; since the types of email I get in my personal email are very different
than the types I get from my work email. This is not something that occurs to
you normally &#8211; what you think is, &#8220;I want to filter my email for spam&#8221; so
naturally you would tack the lens at the root. The problem is &#8211; this arguement
could pretty much be made for <em>every</em> lens, &#8220;Ooh, wordcount, gonna need that&#8221; or
&#8220;Hey now, definitely going to need the mailinglist name extractor&#8221; so you end up
with a pile of lenses on the root router, and suddenly your email sorting is
thrashing the CPU and taking 20 minutes besides.</p>

<p>The practicality of sortah is this &#8211; routers are much more likely to be cheap
than lenses. Remember that a router <em>should</em> boil down to a few conditionals and
<em>consumption of existing metadata</em>, it&#8217;s job is more or less to <em>delegate to
other controllers</em>. In a sense, routers are controllers, lenses are models. The
former should be thin, the latter should be fat. Thinness here means both the
supplied code to do the routing, and the number of lenses attached, should be
small. To understand why, we can look at the algorithm used for evaluation:</p>

<figure class='code'><figcaption><span>Sortah core execution methods, #sort and #send_to. From lib/sortah/cleanroom.rb</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>    <span class="k">def</span> <span class="nf">sort</span>
</span><span class='line'>      <span class="kp">catch</span><span class="p">(</span><span class="ss">:finished_execution</span><span class="p">)</span> <span class="p">{</span> <span class="n">run!</span><span class="p">(</span><span class="vi">@pointer</span><span class="p">)</span> <span class="p">}</span> <span class="k">until</span> <span class="vi">@pointer</span><span class="o">.</span><span class="n">is_a?</span><span class="p">(</span><span class="no">Destination</span><span class="p">)</span>
</span><span class='line'>      <span class="nb">self</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>    <span class="kp">private</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">def</span> <span class="nf">send_to</span><span class="p">(</span><span class="n">dest</span><span class="p">)</span>
</span><span class='line'>      <span class="vi">@pointer</span> <span class="o">=</span> <span class="k">if</span> <span class="n">dest</span><span class="o">.</span><span class="n">is_a?</span> <span class="no">Hash</span>
</span><span class='line'>        <span class="no">Destination</span><span class="o">.</span><span class="n">dynamic</span><span class="p">(</span><span class="n">dest</span><span class="o">[</span><span class="ss">:dynamic</span><span class="o">]</span><span class="p">)</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'>        <span class="vi">@__context__</span><span class="o">.</span><span class="n">routers</span><span class="o">[</span><span class="n">dest</span><span class="o">]</span> <span class="o">||</span> <span class="vi">@__context__</span><span class="o">.</span><span class="n">destinations</span><span class="o">[</span><span class="n">dest</span><span class="o">]</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>      <span class="kp">throw</span> <span class="ss">:finished_execution</span>
</span><span class='line'>    <span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>@pointer</code> is either a Router object or a Destination object. #sort is
called with @pointer set to the root router, it calls a local helper <code>#run!</code> on
the pointer. <code>#run!</code> first calls the <code>#run_dependencies!</code> function on the
pointer, which runs all of the lenses (a noop if there aren&#8217;t any), and then
does a <code>self.instance_eval</code> on the block contained in the router. This is what
ends up calling the <code>#send_to</code> method[1] which sets up the new pointer based on
the symbol it&#8217;s provided (checking to see if it&#8217;s a router first, destination
second, so a router will always override a destination[2]). <code>#send_to</code> then
makes use of the niftiest thing I hadn&#8217;t known previous to this project. It uses
<code>throw</code> to unwind the call stack, which has the pleasant effect of burning up to
the nearest catch block (assuming it is a block which specifies the given symbol &#8211;
which is in <code>#sort</code>! The punchline is that now, <code>#send_to</code> acts like the <code>return</code>
keyword. So we can do the nice:</p>

<figure class='code'><figcaption><span>Isn&#8217;t that pretty&#8230;</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">sortah</span> <span class="k">do</span>
</span><span class='line'>  <span class="n">router</span> <span class="k">do</span>
</span><span class='line'>    <span class="n">send_to</span> <span class="ss">:foo</span> <span class="k">if</span> <span class="n">bar?</span>
</span><span class='line'>    <span class="n">send_to</span> <span class="ss">:baz</span> <span class="k">unless</span> <span class="n">quux?</span> <span class="o">&amp;&amp;</span> <span class="mi">1</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">4</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>rather than having to spell out all of the details with a full if/else/end
block.</p>

<p>The point of all this is to show that delegating to a router with no lenses is
crazyfast, so the big price to pay is not routing delegation, but lens overhead.
This means that it will be better to minimize the number of lenses you need to
run, which means you should really try to minimize the number of lenses ran on
the root and &#8220;higher level&#8221; routers. Remember that routers form an arbitrary
graph &#8211; you can happily call a router from itself if you like. There is no
stack to worry about, so while I can&#8217;t think of a reason it would be useful to
recursively call a router, it is possible. What I see as more likely is a sort
of &#8220;two stage&#8221; approach to writing your routers, the first being &#8220;figure out
what lenses will need to be run on this thing&#8221;, the second being &#8220;pipe through
something which runs a bunch of lenses and does the real routing for this
&#8216;class&#8217; of mail&#8221;.</p>

<h2>Temporary regrets</h2>

<p>The big one is lack of <em>direct</em> support for maildir[3], at the moment you&#8217;ll have
to tack on <code>new</code> manually. I don&#8217;t see much point in preserving mbox, I don&#8217;t
like the format. I don&#8217;t even really like maildir &#8211; but I haven&#8217;t thought of
something better yet. Future non-sortah plans of mine include a mail reader (I&#8217;m
shopping for names at the moment, if anyone has a brilliant idea), so perhaps
that will become a labratory for new mailbox format experiments. I&#8217;m not
particularly opposed to maildir philosophically, it&#8217;s just a bit of a pain to
get it to work with, for instance, mutt. If I had a &#8220;Longterm regrets&#8221; column,
it would be &#8220;Thinking that it would be cool to use mutt&#8221; &#8211; seriously, I don&#8217;t
know how people deal with the miserly state of the thing, it&#8217;s got that &#8220;I&#8217;m a
unix tool for unix nerds and thus I must be configured only in this
incomprehensible language which tries to merge bash and vimscript and shit all
together.&#8221;</p>

<p>I <em>like</em> bash, I <em>like</em> unix, I <em>am</em> a unix nerd, but this shit is unacceptably
awful.</p>

<p>New rule, if you use single-character symbols as a &#8220;shortcut&#8221; for anything that
is actually a <em>variable</em> in your script because <em>you can&#8217;t be bothered to do
proper substitution of shit</em>. You are to be paraded through town, naked, with a
feather shoved&#8230;</p>

<p>Well, you get the idea, I don&#8217;t like muttrc.</p>

<p>Getmail is kindof crappy too, but I&#8217;m less hateful of it because it has the
fringe benefit of being easy to tweak from a cut-and-paste I stole from someone
else.</p>

<p>I&#8217;d really like to roll in getmail in some way to sortah. I know that the unix
philosophy says &#8220;one thing, one thing well&#8221;, but it always felt to me like
retrieval and processing were really the same thing &#8211; acquisition. In my head,
my mail is <em>already</em> in the sorted format, in theory, I should just be doing a
glorified <code>scp</code>. So naturally I dislike a tool which messes with that mental
model. Similarly reading and sending email always struck me as a &#8220;delivery&#8221;
problem, though the model there is perhaps less clear.</p>

<p>There are a few other minor things I wish were different in sortah, most of them
are listed in the &#8220;FUTURE_PLANS&#8221; doc in the repo, but largely I&#8217;m looking
forward to getting my own sortah system set up, getting it working (if
temporarily) with mutt, and getting off the GUI with my email as it is.</p>

<hr />

<p>[1] don&#8217;t mind that it&#8217;s private, it probably shouldn&#8217;t be since it&#8217;s getting
called externally, but <code>instance_eval</code> bypasses normal checks, and the
important thing is that you shouldn&#8217;t be able to call it from any context but a
<code>sortah</code> block.</p>

<p>[2] this is on the list of, &#8220;Things which are a bug no matter which side you
choose&#8221; &#8211; in this case, I chose router because it will cause your filter to
hang, rather than gleefully put your email in the wrong (or at least unintended)
spot. I figure it&#8217;s better to be loud and wrong than quiet and wrong&#8230;</p>

<p>[3] This, as of publish time (12-16-2011) is no longer an issue, sort of. Sortah
has really hacky support for maildir. It&#8217;s not been an issue for me in practice
yet, but I have more pressing issues in terms of email to deal with (eg, I hate
every textmode email client I&#8217;ve tried, so I&#8217;m writing my own).</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Easy things]]></title>
    <link href="http://recurs.es/blog/2011/12/16/easy-things/"/>
    <updated>2011-12-16T08:15:00-05:00</updated>
    <id>http://recurs.es/blog/2011/12/16/easy-things</id>
    <content type="html"><![CDATA[<h2>Start flapping&#8230;</h2>

<p>People have this notion &#8211; if you want to be good at something, you should study
how to do that thing. This, in-and-of-itself is not so much &#8216;wrong&#8217;, as it is
itself misunderstood or misinterpreted. When I told my parents I was going to
study Math, my Dad scoffed at the thought. &#8220;What are you going to do for <em>work</em>,
Joe? How are you going to support a family?&#8221; Implicitly, I think, he was saying,
&#8220;It&#8217;s nice you like your airy-fairy mathematics, but you should do something
practical, like computer science, so you can get a job.&#8221;</p>

<p>Bullshit.</p>

<p>Mathematics has made me ten-times the programmer I would have ever been if I&#8217;d
studied Computer Science directly. When I got to school, I looked at the course
requirements for a CS degree, all I saw was tedium. I didn&#8217;t see anything that
would <em>challenge</em> me, anything I couldn&#8217;t learn on my own. I was already pretty
good at CS &#8211; certainly not great, but I understood the basics. I&#8217;d read the GoF
and DDD, I&#8217;d tried writing a few compilers, I&#8217;d messed around in Scheme and
tried to write some Python[1]. The courseload didn&#8217;t match my skill, and I sure
as shit wasn&#8217;t going to pay them to teach me nothing for two years while they
caught up.</p>

<p>Compare Math. Out of the gate, I jumped into Multivariable Calculus, I did
Linear Algebra and The next semester, Differential Equations.</p>

<p>Holy shit.</p>

<p>My brain couldn&#8217;t keep up, I couldn&#8217;t absorb the knowledge I needed fast enough.
It was like someone grabbed me and threw me off a cliff and screamed, &#8220;Start
flapping, asshole, it&#8217;s a long way down.&#8221; Towards the middle of my sophmore
year, I hit a stride with mathematics, but it never stopped being hard, it never
stopped making my brain hurt.</p>

<h2>DIY</h2>

<p>So what the hell does that have to do with making me a better hacker? Well, in
short, it made me a hacker period. When you&#8217;re falling down the side of an
intellectual cliff, the first thing you need to do is figure out where the
instructions are for the DIY parachute. So too, in studying math, it was a
frantic scramble to ply any advantage I could find &#8211; same with my classmates.
Some of my peers used the fact that they were organized to take copius notes to
preserve the knowledge they couldn&#8217;t otherwise absorb. Some used their social
abilities to tap the resources of others. Some &#8211; like me &#8211; made use of
technology, especially the internet, to glean the information from the ether.</p>

<p>Using the internet to learn is like holding your to a firehose.</p>

<p>But &#8211; that&#8217;s what made me good at things. I learned, in fact, not how to do
math. Indeed, that ability came for free with learning how to learn from the
internet. My professors, I realized, weren&#8217;t the ones with the ripest knowledge
to give, but rather, they were the ones who could be help me learn how to
delineate the intellectual chaff from the wheat. I did not need someone to teach
me Group Theory, I needed someone to tell me that, &#8220;Gallian&#8217;s book for that is
great, but here, try Hungerford, he&#8217;s a bit higher level, but the proof is more
clear his way.&#8221; Something that could never occur to me, something that isn&#8217;t
really &#8220;learning math&#8221; but more &#8220;learning how to math.&#8221;</p>

<h2>Jim and Jane</h2>

<p>Learning mathematics made me good at learning things, sure. Everyone has heard
that cliché more times than they care to count. Consider, however, what the
consequence of that is. Does learning how to learn mean that you are stuck
learning only about the thing you went to study? Of course not, I know how to
learn, therefore, I can learn anything. So then why is it that, oftentimes,
people who study Computer Science (ostensibly, in the process, learning how to
learn), continue to only really learn computer science (if they continue to
learn anything)? I cannot describe the number of people I know who studied CS,
got a Bachelors, when to work at some corporate waterfall company, and remain
there, churning out ten-penny code when they could be writing practical poetry
in another context, working for people who <em>care about being craftspeople</em>.</p>

<p>Now, while my knowledge of many people who coordinate with my claim is by no
means proof, it is an interesting sort of anecdote. It is reasonable to consider
why &#8211; certainly, one hypothesis is that it&#8217;s my fault. After all, I am one
thing they all must have in common (or else I wouldn&#8217;t be considering them)!
However, I have another hypothesis which I think is more likely. That those
people chose to study something that was not challenging, and thus, they never
learned how to learn.</p>

<p>Take, for instance, Jim. Jim is not his name, but it is his moniker for our
purposes. Jim studied CS at UMass, a certainly not terrible school. He learned
his GoF, he studied how to drive design based on the domain, he learned a little
Lisp and a little C and a little Java and a little bit of everything. He was a
fairly reasonable Computer Scientist.</p>

<p>Then he started to work writing C# at a company that didn&#8217;t have a great set of
standards, they didn&#8217;t have a passion for code-poetry, they didn&#8217;t feel like
<em>craftspeople</em> &#8211; they felt like <em>code monkeys</em>.</p>

<p>So whats Jim to do? Jim stagnated. He became a code monkey, he churned out his
requsite KLoCs and never wrote tests and fixed bugs and generally proceeded to
be a just another drop in the waterfall. Jim got stuck, Jim stopped learning.</p>

<p>Compare now, Jane. Jane was a classmate of mine who studied CS. She&#8217;d
never touched a computer (at least, inasmuch to program it) before. She started
her program with an old windows machine which she, &#8220;Was gonna put Linux on, once
[she] figure[d] out what Linux is.&#8221; She didn&#8217;t know about OOP, she&#8217;d never
touched Scheme, she had, seriously, no clue what she was getting into.</p>

<p>But Jane sat down in her first programming class, and studied her ass off to do
well. She learned mountains of material. She wrote code all day.</p>

<p>She also failed.</p>

<p>This served mostly to infuriate her. So when she took the class again, she
redoubled her efforts, she was in every day for office hours. Hacking away,
building her knowledge and her toolset. She was a permanent fixture in the CS
lounge. She was a permanent open IM window on my desktop. She had more questions
than Columbo, but that was because I had some answers, and she needed them.</p>

<p>Jane took what she needed.</p>

<p>Jane works for a Financial firm now as a Quant. She ended up picking up a double
major in Math and CS (focused on stats), and graduated top of her class. She&#8217;s
not a code monkey. She&#8217;s an innovator, she loves her job. She programs all the
time, she (finally) got Linux on her laptop.</p>

<p>The fact that Jane has a &#8220;better&#8221; job is not the moral, the &#8220;betterness&#8221; here is
merely a metric &#8211; I think that, Jane likes her job more than Jim. Jane talks
about her job, the challenges she faces, the problems she wrestles with. In much
the same way as when she was in school, she still is the girl who failed her
first class because it was hard, and who aced the rest of them because she
wasn&#8217;t one to back down.</p>

<p>Jim doesn&#8217;t care anymore. He works for a paycheck, not pride. He doesn&#8217;t talk
about the new problem he has to solve, there aren&#8217;t any. He writes a little
glue, surfs the net, writes a little more. There is no concern for quality &#8211;
it&#8217;s not like the project is going to go through anyway. It&#8217;ll just be another
cancelled plan from upper management. He&#8217;ll get reassigned.</p>

<p>Whats the moral here? The moral is that Jim studied something he knew, and so he
never needed to learn, and so he never had to learn how to learn. Jane, on the
other hand, had no clue going in, she chose a path that would challenge her, and
make her get creative in solving her own difficulties with CS.</p>

<p>It&#8217;s the challenge &#8211; or moreso, the desire to overcome adversity that drives
Jane. It&#8217;s lizardbrain the whole way down.</p>

<h2>Creativity, Elegance, and Craftsmanship</h2>

<p>My larger point is simple, it is less important to study something you &#8216;need&#8217; to
know, and more important to study what is <em>hard to learn</em>. If you can read a
book, and understand it completely without having to really sit and think about
it, you should find a better book. This (for me) roughly boils down to
hacker-culture. Hacker-culture (or at least, my definition of it[2]) strives for
<em>creativity</em> in solutions, <em>elegance</em> in implementations, and <em>craftsmanship</em>
above all. Hacker&#8217;s aren&#8217;t made by taking the easy path, they aren&#8217;t found in
the Jim&#8217;s of the world &#8211; who study only what they <em>know</em>. Hacker&#8217;s are the
Jane&#8217;s, the people who challenge draw inspiration from fields which no one else
would think to combine. They&#8217;re the musicians-turned-mathematician, the
philosopher-hacker-kings, they&#8217;re the people who chart the edge of the world and
shout, &#8220;No dragons here. Keep sailing!&#8221;</p>

<p>Maybe you charge my view of these hacker-heroes is pure romance, if so, then I
am a romantic. I call them as I see them.</p>

<hr />

<p>[1] The former of which I love; the latter of which I emphatically do not.</p>

<p>[2] A definition which is principally derived from the definitions found in the
Jargon File and similar.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Sortah? I barely know 'er!]]></title>
    <link href="http://recurs.es/blog/2011/10/26/sortah-i-barely-know-er/"/>
    <updated>2011-10-26T08:04:00-04:00</updated>
    <id>http://recurs.es/blog/2011/10/26/sortah-i-barely-know-er</id>
    <content type="html"><![CDATA[<h2>What is Sortah?</h2>

<p>Sortah is a embedded DSL for Ruby, which provides a framework for writing email
processing routines in Plain Old Ruby Code (PORC[1]). It looks a bit like this:</p>

<figure class='code'><figcaption><span>sortah example </span><a href='http://recurs.es/2011/10/26/sortah-i-barely-know-er/'>original article</a></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">sortah</span> <span class="k">do</span>
</span><span class='line'>  <span class="n">maildir</span> <span class="s2">&quot;/home/jfredett/.mail/&quot;</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">destination</span> <span class="ss">:work</span><span class="p">,</span> <span class="s1">&#39;work/&#39;</span>
</span><span class='line'>  <span class="n">destination</span> <span class="ss">:gmail</span><span class="p">,</span> <span class="s1">&#39;gmail/&#39;</span>
</span><span class='line'>  <span class="n">destination</span> <span class="ss">:personal</span><span class="p">,</span> <span class="ss">:gmail</span>           <span class="c1"># aliases &#39;gmail&#39; destination</span>
</span><span class='line'>  <span class="n">destination</span> <span class="ss">:trash</span><span class="p">,</span> <span class="ss">:abs</span> <span class="o">=&gt;</span> <span class="s1">&#39;/dev/null&#39;</span> <span class="c1"># an absolute path to somewhere on</span>
</span><span class='line'>                                          <span class="c1"># the system</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>  <span class="n">lens</span> <span class="ss">:spam</span> <span class="k">do</span>
</span><span class='line'>    <span class="n">blacklist</span> <span class="o">=</span> <span class="no">CSV</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="s2">&quot;blacklist.csv&quot;</span><span class="p">)</span>
</span><span class='line'>    <span class="n">email</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">split</span><span class="o">.</span><span class="n">inject</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">a</span><span class="p">,</span> <span class="n">word</span><span class="o">|</span>
</span><span class='line'>      <span class="n">a</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">blacklist</span><span class="o">.</span><span class="n">include?</span> <span class="n">word</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>    <span class="kp">true</span> <span class="k">if</span> <span class="n">a</span> <span class="o">&gt;</span> <span class="mi">20</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">router</span> <span class="k">do</span>
</span><span class='line'>    <span class="n">send_to</span> <span class="ss">:work</span> <span class="k">if</span> <span class="n">email</span><span class="o">.</span><span class="n">to</span> <span class="o">=~</span> <span class="s1">&#39;joe@work.com&#39;</span>
</span><span class='line'>    <span class="n">send_to</span> <span class="ss">:spam_filter</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">router</span> <span class="ss">:spam_filter</span><span class="p">,</span> <span class="ss">:lenses</span> <span class="o">=&gt;</span> <span class="o">[</span><span class="ss">:spam</span><span class="o">]</span> <span class="k">do</span>
</span><span class='line'>    <span class="n">send_to</span> <span class="ss">:trash</span> <span class="k">if</span> <span class="n">email</span><span class="o">.</span><span class="n">spam</span>
</span><span class='line'>    <span class="n">send_to</span> <span class="ss">:personal</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>The above is a pretty straightforward example of how sortah handles email.
Things to notice include how &#8216;lenses&#8217; &#8211; which are like filters your email will
pass through, which may &#8216;color&#8217; the email with additional data &#8211; are specified
as dependencies of &#8216;routers&#8217; which provide a way to specify routing logic. The
main idea is separation of email <em>processing</em> from email <em>routing</em>. The former
being tasks like running an email through a bayseian filter, or inspecting for
presence in a blacklist. The latter being tasks which use that information to
determine where things go on the system. Sortah is smart about how it runs
lens-dependencies, so that they only ever get run once (a bit like rake task
dependencies), this allows you to build up a library of lenses which you can
keep around even when you need to change sorting logic, and vice versa &#8211;
encaspulation, it works!</p>

<h2>Enough about what it is, why is it?</h2>

<p>I wrote sortah because things like procmail and seive &#8211; while (at least the
former) is venerable and still very powerful &#8211; have utterly arcane syntax, and
often make even the simplest of processing tasks very difficult. For instance,
look at this seive example:</p>

<pre><code># Sieve filter

# Declare the extensions used by this script.
#
require ["fileinto", "reject"];

# Messages bigger than 100K will be rejected with an error message
#
if size :over 100K {
  reject "I'm sorry, I do not accept mail over 100kb in size. 
  Please upload larger files to a server and send me a link.
  Thanks.";
}

# Mails from a mailing list will be put into the folder "mailinglist" 
#
elsif address :is ["From", "To"] "mailinglist@blafasel.invalid" {
  fileinto "INBOX.mailinglist";
}

# Spam Rule: Message does not contain my address in To, CC or Bcc
# header, or subject is something with "money" or "Viagra".
#
elsif anyof (not address :all :contains ["To", "Cc", "Bcc"] "me@blafasel.invalid", 
             header :matches "Subject" ["*money*","*Viagra*"]) {
    fileinto "INBOX.spam";
}
</code></pre>

<p>This example is similar in complexity to the sortah example above, and while it
is miles ahead syntactually, it&#8217;s also ugly as sin. I wrote sortah because I
couldn&#8217;t understand why anyone thought this:</p>

<pre><code>:0:   # Deliver to a file, let Procmail figure out how to lock it
* ^From scooby
scooby

:0    # Forwarding; no locking required
* ^TO dogbert
! bofh@dilbert.com

:0:snoopy.lock  # Explicitly name a file to use as a lock
* ^Subject:.*snoopy.*
| $HOME/bin/woodstock-enhancer.pl &gt;&gt;snoopy.mbox
</code></pre>

<p>was a good idea. It&#8217;s, frankly, impossible for me to wrap my brain around this
language &#8211; seive is better, but it has the unfortunate design choice of mixing
business (routing) with pleasure (processing) &#8211; I think sortah excels here.</p>

<p>One of the most fundamental things I thought should be available to the intrepid
email sorting loon is the full weight of a <em>real live programming language</em>.
Sortah provides one, Ruby. You can happily write a lens which provides you with a
piece of email metadata in the form of a custom class &#8211; I actually outline such
a case in the README on <a href="http://github.com/jfredett/sortah">github</a>, where I use
a <code>Contact</code> class to help sort email to appropriate folders in a contact list.</p>

<p>Further, Sortah is declarative, which makes it <em>much</em> easier to compose than
procmail or seive. In fact, in generally boils down to calling <code>load</code> somewhere,
and routing into the library you&#8217;re loading. This means it&#8217;s <em>much</em> easier to
share common code. Rather than needing to manually bind to SpamAssassin, we
could bind to it once, and share, or &#8211; even better &#8211; make it available
directly in ruby.</p>

<h2>Alright, what&#8217;s the catch.</h2>

<p>Well, it&#8217;s a bit slow at the moment, mosty because each email loads your sortahrc
every time it&#8217;s called. A future release will fix that by letting sortah cache a
few emails, or maybe run as a server, or &#8211; well I haven&#8217;t figured out how I
want to solve that problem yet. It also doesn&#8217;t provide a way to &#8220;re-sort&#8221; an
inbox, though this should actually be pretty easy to do with <code>find</code> and some
ingenuity.</p>

<p>It also doesn&#8217;t natively support maildir or mbox or anything, it just writes
files to the filesystem. You should be able to make it work with anything you
like in fairly short order, but it does take a bit of work at the moment.</p>

<p>Finally, this assumes you&#8217;re using getmail, it assumes you send mail from
getmail to sortah as a <code>MDA_external</code>. I haven&#8217;t tested other uses of it, so
YMMV if you try something novel (if you do, tell me about it!)</p>

<h2>Where can I get it?</h2>

<p>You can get it from my <a href="http://github.com/jfredett/sortah">github</a> if you want
the source, or you can do</p>

<pre><code>gem install sortah
</code></pre>

<p>in a gemset somewhere and use rvm exec, etc. There&#8217;s a tutorial for setting it
up in the <a href="http://github.com/jfredett/sortah">github</a> repo, the setup worked
for me, but it&#8217;s not particularly optimized or highly tested.</p>

<p>I hope you find sortah useful, I&#8217;ve had a lot of fun building it. I really hope
if finds some use amongst you few who found that mutt + procmail|sieve + getmail +
blahblahemailtoolsblah was just too much work to get delicious commandline
email management find this to be a nice weight off your shoulders. I know it was
one of the things holding me up.</p>

<hr />

<p>[1] I&#8217;m making this a thing.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[A little static site in the meantime]]></title>
    <link href="http://recurs.es/blog/2011/10/25/a-little-static-site-in-the-meantime/"/>
    <updated>2011-10-25T23:55:00-04:00</updated>
    <id>http://recurs.es/blog/2011/10/25/a-little-static-site-in-the-meantime</id>
    <content type="html"><![CDATA[<p>For now, this is a bit of a placeholder site to alleviate my blogging addiction.
I have bigger plans in the works for my own site, but I wanted somewhere to
hang out in the meantime.</p>

<p>Occurs to me, didn&#8217;t tell you who I am. I&#8217;m Joe Fredette, Mathematician, Haskell Hacker,
Rubyist, Web Developer, and generally amazing person. I like to do math, write
software, play video games, and talk to much. This is my blog, it will house
many things, including words from my brain. You have been warned.</p>

<p>Hope you like it around here!</p>
]]></content>
  </entry>
  
</feed>
