<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Luke Randall</title>
 <link href="http://lukerandall.github.com/atom.xml" rel="self"/>
 <link href="http://lukerandall.github.com/"/>
 <updated>2012-04-20T03:15:23-07:00</updated>
 <id>http://lukerandall.github.com/</id>
 <author>
   <name>Luke Randall</name>
   <email>luke.randall@gmail.com</email>
 </author>

 
 <entry>
   <title>Implementing the reservoir algorithm in Haskell</title>
   <link href="http://lukerandall.github.com/2012/04/20/implementing-the-reservoir-algorithm-in-haskell.html"/>
   <updated>2012-04-20T00:00:00-07:00</updated>
   <id>http://lukerandall.github.com/2012/04/20/implementing-the-reservoir-algorithm-in-haskell</id>
   <content type="html">&lt;h1&gt;&lt;a href=&quot;/2012/04/20/implementing-the-reservoir-algorithm-in-haskell.html&quot;&gt;Implementing the reservoir algorithm in Haskell&lt;/a&gt;&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;20 April 2012 &amp;#8211; Cape Town&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been working on a small project lately, for which I&amp;#8217;ve been using Haskell. Part of it entailed implementing Vitter&amp;#8217;s &lt;a href=&quot;http://www.cs.umd.edu/~samir/498/vitter.pdf&quot; title=&quot;PDF&quot;&gt;Algorithm R&lt;/a&gt; for reservoir sampling. It&amp;#8217;s a simple enough algorithm: given a list with &lt;em&gt;n&lt;/em&gt; items (where &lt;em&gt;n&lt;/em&gt; is unknown), it allows us to randomly choose &lt;em&gt;k&lt;/em&gt; samples from this list.&lt;/p&gt;
&lt;p&gt;It works by utilizing a reservoir of randomly selected items of size &lt;em&gt;k&lt;/em&gt;. Initially, we populate our reservoir with the first &lt;em&gt;k&lt;/em&gt; items from the list. Thereafter, with &lt;em&gt;k/i&lt;/em&gt; probability (where &lt;em&gt;i&lt;/em&gt; is the number of items we&amp;#8217;ve seen) we replace an item in our reservoir. We do this by taking a random number &lt;em&gt;r&lt;/em&gt; between 1 and &lt;em&gt;i&lt;/em&gt;, and if it falls between 1 and &lt;em&gt;k&lt;/em&gt; we replace the &lt;em&gt;r&lt;/em&gt; th element with the new item.&lt;/p&gt;
&lt;p&gt;If all of that still sounds complicated, it&amp;#8217;s only because I managed to complicate my explanation. The &lt;a href=&quot;http://en.wikipedia.org/wiki/Reservoir_sampling&quot;&gt;wikipedia page&lt;/a&gt; has a nice pseudocode implementation which should make things clear.&lt;/p&gt;
&lt;p&gt;I found a number of existing Haskell implementations, but all of them seemed to rely on performing a single pass over the input data before returning the randomly selected elements. That&amp;#8217;s suitable for most use cases, but I need this to take a sample on an ongoing basis, where I can at any point retrieve the current samples, but still continue to add new ones. While this obviously isn&amp;#8217;t impossible with the implementations I found, it would require replicating the list (or array, etc.) of samples each time I added a new one, which is undesirable for performance reasons.&lt;/p&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;p&gt;Knowing that for my use case I needed to take a relatively large number of samples I decided to use a mutable array as the container for the reservoir. This entails some trade-offs:&lt;/p&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;provides fast indexed lookup of elements (as opposed to O(n) lookup of lists)&lt;/li&gt;
	&lt;li&gt;does not require duplicating elements every time a change is made (as opposed to an immutable array)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;lives in the IO monad&lt;/li&gt;
	&lt;li&gt;changes are destructive&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The cons are both related to not duplicating the data structure on updates: updating the array would have to require either duplicating it or mutating it. Whilst this should make sense logically, it is also confirmed by looking at the &lt;code&gt;array&lt;/code&gt; source, which provides two functions for converting IArrays to MArrays, &lt;code&gt;thaw&lt;/code&gt; and &lt;code&gt;unsafeThaw&lt;/code&gt;. &lt;code&gt;thaw&lt;/code&gt; copies the contents of the IArray to an MArray, whilst &lt;code&gt;unsafeThaw&lt;/code&gt; provides mutable access to the array, either in-place or by copying the array&amp;#8217;s contents (it makes no guarantees about which).&lt;/p&gt;
&lt;p&gt;As an aside, another approach would be to use a &lt;code&gt;DiffArray&lt;/code&gt;, which provides a pure &amp;#8211; ostensibly immutable &amp;#8211; interface but uses a mutable array under the surface. As updates are made to the array, they happen in-place and the changes required to return it to its prior state is recorded. This means that references to the old array return the old contents as expected, but at the cost of having to compute it by applying the list of changes needed to undo any updates that were made. However, since I had no need of this (&lt;strong&gt;and&lt;/strong&gt; because the current &lt;code&gt;DiffArray&lt;/code&gt; implementations performance is &lt;a href=&quot;http://trac.haskell.org/diffarray/ticket/2&quot;&gt;horrible&lt;/a&gt;) I didn&amp;#8217;t try this approach.&lt;/p&gt;
&lt;p&gt;Since an update mutates the array, the only option was to put it in the IO monad. However, this led to complications in that parts of the data structure &amp;#8211; the array of samples &amp;#8211; were mutable, whilst the rest &amp;#8211; current pool size and total sample count &amp;#8211; weren&amp;#8217;t. This meant if you added a sample then referenced the original reservoir instead of the new reservoir it returned you would find the sample had been updated, but the size and count hadn&amp;#8217;t. This seemed pretty horrible to me: since the sample had been updated a casual examination of the reservoir would indicate that it had updated in place, and the average user could easily make the false assumption of thinking they didn&amp;#8217;t need to do anything with the return value of &lt;code&gt;addElem&lt;/code&gt;. To rectify this, I decided to make &lt;code&gt;reservoirSize&lt;/code&gt; an &lt;code&gt;IORef&lt;/code&gt;, so that I could likewise update it in-place. This hopefully makes the behaviour more consistent for the user.&lt;/p&gt;
&lt;h2&gt;What&amp;#8217;s next&lt;/h2&gt;
&lt;p&gt;At this point, the biggest thing I&amp;#8217;ve gotten out of this is really the knowledge gained. The code itself will likely all be thrown away in the next few weeks (when I hope to have a bit of free time again). Future work will probably be:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;measure performance&lt;/li&gt;
	&lt;li&gt;try using vectors&lt;/li&gt;
	&lt;li&gt;write some decent tests&lt;/li&gt;
	&lt;li&gt;make the code less likely to make people cry&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Right now I have no idea of the performance of the implementation. This means that for the reservoir sizes I&amp;#8217;ll be using, immutable data structures could prove to be fast enough, or conceivably even faster than the current structure with its use of &lt;code&gt;IORef&lt;/code&gt;s and the like. An important first step then is writing benchmarks. With the new release of cabal and its support for benchmarking, this is a perfect chance to do it. Having benchhmarks also means writing an implementation using vectors will allow me to compare their performance instead of just going on the assumption that they should be faster. If this all seems obvious I suppose it&amp;#8217;s because it is.&lt;/p&gt;
&lt;p&gt;After that, I&amp;#8217;ll have a chance to finally use &lt;a href=&quot;http://hackage.haskell.org/package/QuickCheck&quot;&gt;QuickCheck&lt;/a&gt; and write some tests. Assuming of course that I can figure out how to use it to test non-deterministic data structures.&lt;/p&gt;
&lt;p&gt;At the end of my hacking, it was satisfying to have implemented something in Haskell, but at the same time slightly disheartening for it to have taken so long to achieve such a basic task. I think it&amp;#8217;ll always be true that using languages you know well makes you more productive than using a new language, and I think that&amp;#8217;s especially so with something as different to what I&amp;#8217;m used to as Haskell is. At least with this done I&amp;#8217;ve gotten a few steps closer to making Haskell one of my productive languages.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Architecting a Rails App</title>
   <link href="http://lukerandall.github.com/2012/02/03/architecting-a-rails-app.html"/>
   <updated>2012-02-03T00:00:00-08:00</updated>
   <id>http://lukerandall.github.com/2012/02/03/architecting-a-rails-app</id>
   <content type="html">&lt;h1&gt;&lt;a href=&quot;/2012/02/03/architecting-a-rails-app.html&quot;&gt;Architecting a Rails App&lt;/a&gt;&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;3 February 2012 &amp;#8211; Cape Town&lt;/p&gt;
&lt;p&gt;I gave a talk yesterday at &lt;a href=&quot;http://rubyfuza.org&quot;&gt;Rubyfuza&lt;/a&gt; about Architecting Rails Applications. Primarily I spoke about how the focus on &lt;span class=&quot;caps&quot;&gt;MVC&lt;/span&gt; alone has provided an insufficient level of abstraction, causing our models to become a dumping ground for application logic. Using &lt;a href=&quot;http://en.wikipedia.org/wiki/Data,_context_and_interaction&quot;&gt;&lt;span class=&quot;caps&quot;&gt;DCI&lt;/span&gt;&lt;/a&gt; allows us to decompose and manage this complexity. By turning the algorithm into a first-class object in our code, we can better reason about it, more easily test it, and encapsulate it. Like any design pattern, it&amp;#8217;s not always applicable, and won&amp;#8217;t solve every problem, but it is a useful tool. My slides won&amp;#8217;t be as meaningful without the talk, but here they are:&lt;/p&gt;
&lt;script src=&quot;http://speakerdeck.com/embed/4f2a83126a1774001f016ebc.js&quot;&gt;&lt;/script&gt;&lt;p&gt;I think an extra ten minutes would have been useful &amp;#8211; there were certain things I had to hurry through to fit into the time slot and still have a couple minutes to answer questions. Chatting to &lt;a href=&quot;http://nicksda.apotomo.de&quot;&gt;Nick Sutterer&lt;/a&gt; afterwards, he mentioned that he would have liked to see a bit more time spent discussing contexts specifically. I agree &amp;#8211; for a concept that&amp;#8217;s so vital I didn&amp;#8217;t spend enough time examining it. That&amp;#8217;s something I will try rectify by exploring it in more detail here.&lt;/p&gt;
&lt;p&gt;After the conference was done for the day, &lt;a href=&quot;http://svenfuchs.com&quot;&gt;Sven Fuchs&lt;/a&gt; and I chatted for a bit, and he raised (not for the first time) the issue of whether &lt;code&gt;#extend&lt;/code&gt; is too expensive to call during each request/response lifecycle. I was aware that it might be an issue with JRuby due to it clobbering the constants lookup cache (see &lt;a href=&quot;http://blog.headius.com/2011/08/invokedynamic-in-jruby-constant-lookup.html&quot;&gt;this blog post by Charles Nutter&lt;/a&gt; for some details on why this is), and he said it was likely an issue with Rubinius as well. I don&amp;#8217;t know, and I think it&amp;#8217;s something worth investigating. I&amp;#8217;ve seen some microbenchmarks on the matter, but I don&amp;#8217;t know how much faith one can put in them. It seems to me they benchmark the cost of calling &lt;code&gt;#extend&lt;/code&gt; itself, without taking into account the long term cost (ie across multiple requests).&lt;/p&gt;
&lt;p&gt;Two things strike me whilst writing this &amp;#8211; firstly, it&amp;#8217;s possible (likely even) that for the average application the extra cost to lookup constants is not going to be what determines whether or not the system performs adequately, and secondly, there is nothing inherent in &lt;span class=&quot;caps&quot;&gt;DCI&lt;/span&gt; that requires that we use &lt;code&gt;#extend&lt;/code&gt;. The fact that &lt;span class=&quot;caps&quot;&gt;DCI&lt;/span&gt; is happily used in statically typed languages would suggest that this is the case. There are various alternatives that have already occured to me, none of which I&amp;#8217;ve thought through particularly well, and none of which I like, but nonetheless I think with further thought at least one idea would be found to be a workable solution. I&amp;#8217;m interested to see what ideas others have on the matter.&lt;/p&gt;
&lt;p&gt;One thing that came up in the questions at the end of the talk was that someone (as I recall Sven) asked about the usage of &lt;code&gt;#call&lt;/code&gt; for the context. I was glad it was raised, as it&amp;#8217;s something I forgot to mention during the talk. I owe the insight (as I indeed owe &lt;a href=&quot;http://mikepackdev.com/blog_posts/24-the-right-way-to-code-dci-in-ruby&quot;&gt;the code in question&lt;/a&gt;) to Mike Pack. He suggests &lt;code&gt;#call&lt;/code&gt; in lieu of &lt;code&gt;#execute&lt;/code&gt;, &lt;code&gt;#run&lt;/code&gt; or the various other verbiage that others have suggested as it retains the same calling semantics were one to use a Proc instead of a class based approach to Contexts.&lt;/p&gt;
&lt;p&gt;When it comes to &lt;span class=&quot;caps&quot;&gt;DCI&lt;/span&gt;, I owe the understanding I have &amp;#8211; but certainly not any misconceptions &amp;#8211; to a wide variety of sources, but some I found particularly helpful were: &lt;a href=&quot;http://mikepackdev.com/blog_posts/24-the-right-way-to-code-dci-in-ruby&quot;&gt;Mike Pack&lt;/a&gt;, &lt;a href=&quot;http://andrzejonsoftware.blogspot.com/2011/02/dci-and-rails.html&quot;&gt;Andrzej Krzywda&lt;/a&gt; and &lt;a href=&quot;http://saturnflyer.com/blog/jim/2011/10/04/oop-dci-and-ruby-what-your-system-is-vs-what-your-system-does/&quot;&gt;Jim Gay&lt;/a&gt;; as well as the obvious duo of &lt;a href=&quot;http://www.artima.com/articles/dci_vision.html&quot;&gt;Trygve Reenskaug and James Coplien&lt;/a&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Rubyfuza Again</title>
   <link href="http://lukerandall.github.com/2012/02/02/rubyfuza-again.html"/>
   <updated>2012-02-02T00:00:00-08:00</updated>
   <id>http://lukerandall.github.com/2012/02/02/rubyfuza-again</id>
   <content type="html">&lt;h1&gt;&lt;a href=&quot;/2012/02/02/rubyfuza-again.html&quot;&gt;Rubyfuza Again&lt;/a&gt;&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;2 February 2012 &amp;#8211; Cape Town&lt;/p&gt;
&lt;p&gt;Later today I&amp;#8217;ll be giving a talk at Rubyfuza. I&amp;#8217;ll be posting the slides when I&amp;#8217;m done.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Feedburner</title>
   <link href="http://lukerandall.github.com/2011/05/26/feedburner.html"/>
   <updated>2011-05-26T00:00:00-07:00</updated>
   <id>http://lukerandall.github.com/2011/05/26/feedburner</id>
   <content type="html">&lt;h1&gt;&lt;a href=&quot;/2011/05/26/feedburner.html&quot;&gt;Feedburner&lt;/a&gt;&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;26 May 2011 &amp;#8211; Cape Town&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve changed my Atom feed to use Feedburner, so for the 2 (hmm, that might be a generous total) of you following my blog, please point your feed reader at &lt;a href=&quot;http://feeds.feedburner.com/lukerandall&quot;&gt;http://feeds.feedburner.com/lukerandall&lt;/a&gt; so that you can stay up to date. Thanks.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Monoids</title>
   <link href="http://lukerandall.github.com/2011/05/22/monoids.html"/>
   <updated>2011-05-22T00:00:00-07:00</updated>
   <id>http://lukerandall.github.com/2011/05/22/monoids</id>
   <content type="html">&lt;h1&gt;&lt;a href=&quot;/2011/05/22/monoids.html&quot;&gt;Monoids&lt;/a&gt;&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;22 May 2011 &amp;#8211; Cape Town&lt;/p&gt;
&lt;p&gt;In an effort to break the usual Haskell newbie cycle of writing another blog post on monads, my inaugural Haskell themed blog post will be about &lt;strong&gt;monoids&lt;/strong&gt;, which I&amp;#8217;ve found to be surprisingly interesting.&lt;/p&gt;
&lt;h2&gt;What is a monoid?&lt;/h2&gt;
&lt;p&gt;Simply put, a monoid is an algebraic type with an associative binary operation &amp;#8211; ie an operation that has two operands &amp;#8211; called mappend, and an identity element &amp;#8211; an element that, when combined with another element using the aforementioned binary operation, leaves the element unchanged &amp;#8211; called mempty. Disregarding the unfortunate choice of names, some examples might help to illustrate the concept:&lt;/p&gt;
&lt;p&gt;The natural numbers form a monoid under addition, with the binary operation obviously being addition, and the identity element 0. Likewise, they form a monoid under multiplication, with the identity element being 1. In both cases, the truthfulness of this can be trivially tested. Addition and multiplication both take two operands. Further adding 0 to any number returns that number; multiplying any number by 1 returns that number.&lt;/p&gt;
&lt;h2&gt;What&amp;#8217;s the point?&lt;/h2&gt;
&lt;p&gt;With such simple examples, one might wonder what utility there is in creating a type class for monoids. In truth, I feel the power of monoids comes from the fact that they are 1. rather general, and 2. very simple. Since there is no limitation on the binary operation beyond that it be associative, many things can be represented as a monoid. Looking at the &lt;a href=&quot;http://hackage.haskell.org/packages/archive/base/latest/doc/html/Data-Monoid.html&quot;&gt;Data.Monoid documentation&lt;/a&gt; one finds a number of monoid instances.&lt;/p&gt;
&lt;h2&gt;Folding with monoids&lt;/h2&gt;
&lt;p&gt;To illustrate the utility of monoids, let&amp;#8217;s try using foldMap and a few monoid instances. For example, the Sum monoid can be used thusly:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;nf&quot;&gt;foldMap&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Sum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;foldMap&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Sum&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;which return respectively Sum 0 and Sum 6. &amp;#8220;So what?&amp;#8221;, I hear you ask. Well, consider the situation where you want to compute the sum and the product of a list. No problem:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;nf&quot;&gt;foldMap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Sum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Product&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;which returns a tuple containing Sum 10 and Product 24. I suppose it would be more accurate to say it returns:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Sum&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getSum&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Product&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getProduct&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The getSum and getProduct wrappers are because there can only exist one monoid instance per data type, so Sum and Product are newtype wrappers around Num.&lt;/p&gt;
&lt;h2&gt;I&amp;#8217;m still not impressed&lt;/h2&gt;
&lt;p&gt;Gosh, you really lack imagination, don&amp;#8217;t you? Anything that obeys our monoid laws can be made a monoid. For example, consider two functions with type signature Monoid b =&amp;gt; a &amp;#8594; b. There exists a monoid for said functions, which means you can combine these two functions with mappend. What does this mean for you? As &lt;a href=&quot;http://www.reddit.com/r/programming/comments/7cf4r/monoids_in_my_programming_language/c06adnx&quot;&gt;cgibbard wonderfully demonstrates&lt;/a&gt; &amp;#8211; and indeed this is what first helped me to recognise the universal utility of monoids &amp;#8211; using the Ordering data type, you can order a list using a variety of criteria simply and succinctly. To wit, Ordering forms a monoid under the following usage:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;kt&quot;&gt;LT&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mappend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LT&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;GT&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mappend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;GT&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;EQ&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mappend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;mempty&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EQ&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Suppose then that we have a list containing integers, and we wish to sort it first by the sum of the list, then by list length, then by ordinary numerical sorting of the elements, one can do the following:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;nf&quot;&gt;sortBy&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;comparing&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mappend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comparing&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mappend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;returning [[1,1,1,1],[5,1],[1,2,3],[3,2,1],[1,1,1,1,1,1],[4,2,1]]. As you can see, the list was sorted by sum, then length, then by comparison (hence [1,2,3] coming before [3,2,1]). Now consider how much code it would have taken to do this without using monoids.&lt;/p&gt;
&lt;h2&gt;You&amp;#8217;d better be impressed&lt;/h2&gt;
&lt;p&gt;Although these examples barely skim the surface of all you can do with monoids, I hope demonstrated how much simpler your code could be by recognising and using monoids appropriately. Since first learning about them, it&amp;#8217;s surprised me how this simple pattern appears in code I write &lt;strong&gt;every single day&lt;/strong&gt;, and how often I could have written far simpler code if I had but recognised it for what it was &amp;#8211; a simple, lowly monoid.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Haskell Again</title>
   <link href="http://lukerandall.github.com/2011/04/21/haskell-again.html"/>
   <updated>2011-04-21T00:00:00-07:00</updated>
   <id>http://lukerandall.github.com/2011/04/21/haskell-again</id>
   <content type="html">&lt;h1&gt;&lt;a href=&quot;/2011/04/21/haskell-again.html&quot;&gt;Haskell Again&lt;/a&gt;&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;21 April 2011 &amp;#8211; Cape Town&lt;/p&gt;
&lt;p&gt;It struck me, as I started typing this page, that I don&amp;#8217;t move around nearly enough to warrant including a location in each blog post. Maybe once every few years when I move I can write &amp;#8220;the next 5 years of blogging coming to you from &lt;em&gt;city name&lt;/em&gt;&amp;#8221; or something to that effect. Anyhow&amp;#8230;  As usual, I realised I haven&amp;#8217;t blogged in ages. Like most blogs, mine seems to be a sort of metablog about blogging (or the absence thereof) rather than content. Perhaps this is the start of something more. Time will tell.&lt;/p&gt;
&lt;p&gt;As usual, I&amp;#8217;ve spent the last year suffering from technology-induced &lt;span class=&quot;caps&quot;&gt;ADD&lt;/span&gt;. This includes starting 2 books on Scala, a book on Clojure, one on Common Lisp, another on JavaScript, etc. I&amp;#8217;d say the JavaScript one was most successful in that I actually read enough of it for it to have affected my understanding (and writing) of JavaScript. I&amp;#8217;ve since realised that, as much as there are 100 different subjects that fascinate me, I&amp;#8217;m never going to master any of them unless I&amp;#8217;m willing to accept that I need to focus on one or two at a time.&lt;/p&gt;
&lt;p&gt;With that in mind, I&amp;#8217;ve decided my primary focus &amp;#8211; outside of whatever I&amp;#8217;m doing at work, which will likely be a combination of Ruby and Objective-C &amp;#8211; will be Haskell. I&amp;#8217;m tired of having to resolve problems and rediscover things I&amp;#8217;ve learnt before, so I&amp;#8217;m going to try catalogue things as I learn them.&lt;/p&gt;
&lt;h2&gt;Starting today&lt;/h2&gt;
&lt;p&gt;I watched some presentations given by &lt;a href=&quot;http://vimeo.com/user4351020/videos/sort:date&quot;&gt;Nick Partridge&lt;/a&gt; on Haskell, and learnt about or was reminded of a few things. Briefly:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Use &lt;a href=&quot;http://hackage.haskell.org/package/pointful&quot;&gt;pointful&lt;/a&gt; to help you make sense of complex point-free expressions.&lt;/li&gt;
	&lt;li&gt;Use &lt;a href=&quot;http://hackage.haskell.org/package/pointfree&quot;&gt;pointfree&lt;/a&gt; to turn pointful expressions into (complex, at times) pointfree expressions.&lt;/li&gt;
	&lt;li&gt;Use &lt;a href=&quot;http://community.haskell.org/~ndm/hlint/&quot;&gt;hlint&lt;/a&gt; on your source code for suggestions on how to improve it.&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.haskell.org/hoogle/&quot;&gt;Hoogle&lt;/a&gt; can be installed locally.&lt;/li&gt;
	&lt;li&gt;First look in hackage for libraries that do what you are trying to accomplish before writing your own code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those were the salient points for me. Now I&amp;#8217;m off to try my hand at getting Yesod up and running.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Some rambling thoughts on type inference</title>
   <link href="http://lukerandall.github.com/2010/12/02/some-rambling-thoughts-on-type-inference.html"/>
   <updated>2010-12-02T00:00:00-08:00</updated>
   <id>http://lukerandall.github.com/2010/12/02/some-rambling-thoughts-on-type-inference</id>
   <content type="html">&lt;h1&gt;&lt;a href=&quot;/2010/12/02/some-rambling-thoughts-on-type-inference.html&quot;&gt;Some rambling thoughts on type inference&lt;/a&gt;&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;02 Dec 2010 &amp;#8211; Cape Town&lt;/p&gt;
&lt;p&gt;O&amp;#8217;Reilly were having one of their site-wide ebook discounts, and as usual I scoured the very comprehensive list of books to see what I should buy. It&amp;#8217;s funny how something will suddenly become a necessity when you can get 60% off the purchase price. Needless to say I wound up buying &lt;a href=&quot;http://programmingscala.com/&quot;&gt;Programming Scala&lt;/a&gt;, in spite of already owning a perfectly good &amp;#8211; and unread &amp;#8211; copy of &lt;a href=&quot;http://www.artima.com/shop/programming_in_scala&quot;&gt;Programming in Scala&lt;/a&gt;. Admittedly, I did find the latter somewhat slow going, which has not helped in my efforts to try and learn the language.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve always (for the last 6 months at least!) considered my lack of knowledge of Scala to be an unfortunate shortcoming, and so I reasoned if I bought Just One More Book on it, I might read enough of it to learn a sufficent portion of the language to start enjoying it, allowing me to stick it out and learn further. It&amp;#8217;s frustrating to me how many programming books start out by detailing minutiae of a language instead of getting on with teaching us about it&amp;#8217;s style and strengths. I enjoy being given a complex, idiomatic piece of code in a language and having to figure out what it does, as well as identify the strange (or familiar) programming idioms. I find it fascinating to learn the different styles and patterns that become best practice in different languages.&lt;/p&gt;
&lt;p&gt;Anyway, as I started reading, I was wondering how Scala performs it&amp;#8217;s type inference. All the languages that perform type inference that I have a knowledge of use Hindley-Milner (or Damas-Milner to the pedantic), or some derivative of that. This is true of Haskell, ML, F#, etc.&lt;/p&gt;
&lt;p&gt;While searching for an answer, I came across &lt;a href=&quot;http://www.codecommit.com/blog/scala/universal-type-inference-is-a-bad-thing&quot;&gt;an article&lt;/a&gt; which suggests that H-M type inference is a bad thing. It contrasts two equivalent pieces of code &amp;#8211; written in ML and Scala &amp;#8211; and posits that the Scala version is somehow superior to the ML version, precisely because it is more verbose. Okay, it&amp;#8217;s on the verbosity per se, but the type annotations necessitated by Scala performing only local type inference. Reading on, the author reasons that, due to the extensive use of type annotations in the Scala version, it is safer and more useful than the ML version. I must say, I find this argument to be rather absurd.&lt;/p&gt;
&lt;p&gt;In Haskell, I&amp;#8217;ve found type inference to be hugely useful. It gives the code you write a feel more akin to dynamically typed languages than the verbose, boilerplate filled code one normally associates with statically typed languages. Letting the compiler figure out the types lets you focus on solving the problem, not babysitting the compiler.&lt;/p&gt;
&lt;p&gt;However, I have found it very useful when writing a function to start by thinking about its type signature. It accomplishes a number of things:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;It forces you to formalise the problem in your head, and helps ensure your solution is actually solving the problem.&lt;/li&gt;
	&lt;li&gt;It gives you and others reading your code a succint explanation of what the code is doing.&lt;/li&gt;
	&lt;li&gt;It prevents errors of the sort the author complains about, where your function behaves differently to your expectations.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;#8217;m not sure if this just reflects a difference in culture between Haskell and ML, but I&amp;#8217;ve found (from my admittedly limited experience with Haskell) that there is an emphasis on manually writing the type signature for all but the most basic functions, to ensure that your function isn&amp;#8217;t just internally consistent, but also consistent with your expectations of it. It provides numerous benefits, adds a single line of code above the function, and obviates the need for scattering ugly type annotations throughout your code.&lt;/p&gt;
&lt;p&gt;If, as the author says, there is a tendency in ML to only include the type signature when necessary, I can see why this might cause frustration. But, it seems to be a case of throwing out the baby with the bathwater when the problem can be solved quite simply, and not by &amp;#8220;protecting&amp;#8221; ourselves by using a dumbed down type inference algorithm.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Could it be</title>
   <link href="http://lukerandall.github.com/2010/11/28/could-it-be.html"/>
   <updated>2010-11-28T00:00:00-08:00</updated>
   <id>http://lukerandall.github.com/2010/11/28/could-it-be</id>
   <content type="html">&lt;h1&gt;&lt;a href=&quot;/2010/11/28/could-it-be.html&quot;&gt;Could it be&lt;/a&gt;&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;28 Nov 2010 &amp;#8211; Cape Town&lt;/p&gt;
&lt;p&gt;Lately I&amp;#8217;ve been trying to learn a lot of new (at least for me) technologies and languages, and I&amp;#8217;ve wanted a place to keep track of my thoughts and progress. So I&amp;#8217;ve decided it makes sense for my to dust off the cobwebs and see if I can try make blogging stick. Time will tell.&lt;/p&gt;
&lt;h2&gt;What&amp;#8217;s new?&lt;/h2&gt;
&lt;p&gt;I&amp;#8217;ve changed things up a bit. Mostly by swapping out my dull sans serif font stack for Skolar. TypeKit is great, and I&amp;#8217;m glad to finally have a site where I can use it.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve swapped out the most of the blue in the old style for red. It&amp;#8217;s a work in progress, but I think it&amp;#8217;s an improvement.&lt;/p&gt;
&lt;h2&gt;What I&amp;#8217;ll be writing about&lt;/h2&gt;
&lt;p&gt;Lately I&amp;#8217;ve finally taken it upon myself to improve my JavaScript. I&amp;#8217;ll be doing some pretty interesting things in the coming months.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m also taking the time to learn more about functional programming, and in particular Haskell, so I&amp;#8217;ll probably have some very rudimentary posts about Haskell from time to time.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Time travelling with Jekyll</title>
   <link href="http://lukerandall.github.com/2009/02/11/time-travelling-with-jekyll.html"/>
   <updated>2009-02-11T00:00:00-08:00</updated>
   <id>http://lukerandall.github.com/2009/02/11/time-travelling-with-jekyll</id>
   <content type="html">&lt;h1&gt;&lt;a href=&quot;/2009/02/11/time-travelling-with-jekyll.html&quot;&gt;Time travelling with Jekyll&lt;/a&gt;&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;11 Feb 2009 &amp;#8211; Johannesburg&lt;/p&gt;
&lt;p&gt;So I went ahead and changed the front page so that it showed my last couple of posts. I didn&amp;#8217;t like it though, so I changed it back. At the end of the day the whole thing is something of a hack since I just truncate the content of the post, which means that the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; has a 99% chance of missing a closing p tag or something. Anyway, it works for now&amp;#8230;&lt;/p&gt;
&lt;p&gt;One thing that I haven&amp;#8217;t figured out with Jekyll is how to have multiple entries from the same day appear in the correct order. I suppose I haven&amp;#8217;t really tried to figure it out. I suppose the obvious thing to do would be to add in a timestamp. I dunno if Jekyll supports anything but the date. So in the meantime I&amp;#8217;ve just resorted to back dating and post dating entries if the order is important. Hence the title of this post&amp;#8230;&lt;/p&gt;
&lt;p&gt;I was looking back at my old, abandoned blog (with all of two entries) and it struck me how quickly things move. I was busy blogging about Git and how I planned to look into GitHub. That was back in the days when you needed an invite to get onto GitHub. And that was less than a year ago. In less than a year GitHub has completely revolutionised open source, and more specifically Ruby, development.&lt;/p&gt;
&lt;p&gt;Anyway, I hadn&amp;#8217;t intended for this to be long. I&amp;#8217;m hoping for once to get a decent night&amp;#8217;s rest.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>A few new additions</title>
   <link href="http://lukerandall.github.com/2009/02/10/a-few-new-additions.html"/>
   <updated>2009-02-10T00:00:00-08:00</updated>
   <id>http://lukerandall.github.com/2009/02/10/a-few-new-additions</id>
   <content type="html">&lt;h1&gt;&lt;a href=&quot;/2009/02/10/a-few-new-additions.html&quot;&gt;A few new additions&lt;/a&gt;&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;10 Feb 2009 &amp;#8211; Johannesburg&lt;/p&gt;
&lt;p&gt;Well, more like one new addition. Since I don&amp;#8217;t blog all that often, and I don&amp;#8217;t have anything else I&amp;#8217;m linking to, I disliked the fact that my latest blog entry wasn&amp;#8217;t displayed on the home page. So, searching the net for a liquid cheat sheet (since I&amp;#8217;ve never used it before), I hacked away at my index page for a few minutes and now have a truncated version of my newest post displayed on the home page. I&amp;#8217;m thinking I&amp;#8217;ll probably do that for the last 3 &amp;#8211; 5 posts, and then display links to the older ones, but I&amp;#8217;ll get to that soon enough.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Someone reminded me to update my blog</title>
   <link href="http://lukerandall.github.com/2009/02/09/someone-reminded-me-to-update-my-blog.html"/>
   <updated>2009-02-09T00:00:00-08:00</updated>
   <id>http://lukerandall.github.com/2009/02/09/someone-reminded-me-to-update-my-blog</id>
   <content type="html">&lt;h1&gt;&lt;a href=&quot;/2009/02/09/someone-reminded-me-to-update-my-blog.html&quot;&gt;Someone reminded me to update my blog&lt;/a&gt;&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;09 Feb 2009 &amp;#8211; Johannesburg&lt;/p&gt;
&lt;p&gt;Today, someone tweeted me and reminded me that my blog is one of the most shamefully neglected corners of cyberspace. Since I&amp;#8217;ve never had anyone express interest in my blog before, I&amp;#8217;ve never really felt too bad. But the fact that someone actually took notice means that I need to repent and become a more devout blogger.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been using Rails 2.3 for the past week or two. Well, 2.3 RC1 to be precise. It seems more than stable &amp;#8211; certainly I&amp;#8217;ve yet to run into any issues with it. And truly, the output of rake routes is a joy to behold now that all the formatted routes crap is gone. I don&amp;#8217;t know that we use enough routes in any of our projects for it to make a &lt;strong&gt;huge&lt;/strong&gt; difference memory-wise, but I&amp;#8217;ll test that when I upgrade one of our older projects from Rails 2.1 to 2.3. Mostly I haven&amp;#8217;t because I&amp;#8217;ve just been a bit lazy. Considering it&amp;#8217;s about 10 minutes worth of work (plus a few more to test), I really just need to buckle down and do it.&lt;/p&gt;
&lt;p&gt;In other news, since I&amp;#8217;ve been working more closely with other developers, I&amp;#8217;ve actually started remembering to switch out to branches before I add features. When you&amp;#8217;re pretty much the only person working on a particular code base, working on the master branch causes problems rarely enough that you tend to just do it. However, it&amp;#8217;s one of those things that I&amp;#8217;ve known I shouldn&amp;#8217;t be doing for a while, so I&amp;#8217;m glad I&amp;#8217;ve finally had something to push me to remember. Now finally I can stop abusing git stash.&lt;/p&gt;
&lt;p&gt;Anyway, I&amp;#8217;m really going to try and make time for a few blog posts a week, since I often have things I think I should blog about but neglect to. Let&amp;#8217;s see how that goes.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Things I think I'll like about Jekyll</title>
   <link href="http://lukerandall.github.com/2008/12/22/things-i-think-ill-like-about-jekyll.html"/>
   <updated>2008-12-22T00:00:00-08:00</updated>
   <id>http://lukerandall.github.com/2008/12/22/things-i-think-ill-like-about-jekyll</id>
   <content type="html">&lt;h1&gt;&lt;a href=&quot;/2008/12/22/things-i-think-ill-like-about-jekyll.html&quot;&gt;Things I think I&amp;#8217;ll like about Jekyll&lt;/a&gt;&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;22 Dec 2008 &amp;#8211; Johannesburg&lt;/p&gt;
&lt;p&gt;Well, it&amp;#8217;s been all of ten minutes. No wait, maybe fifteen. Anyway, with that much exposure to it, this is a real first impressions type post. But here&amp;#8217;s what seems cool thus far.&lt;/p&gt;
&lt;h2&gt;Uses Git (and integrates with GitHub)&lt;/h2&gt;
&lt;p&gt;I like the fact that I can edit blog posts from TextMate. I think a big reason for me never blogging is the fact that I have to think of going to my Wordpress site, logging into the admin section, and then composing a new entry. Now, this doesn&amp;#8217;t sound like much work (it really isn&amp;#8217;t), but I suppose I&amp;#8217;m lazy, and so being able to do things from TextMate (which &amp;#8211; on my machine &amp;#8211; is open 95% of the time) makes the workflow just that little bit cleaner. Plus, I can push the changes out to GitHub with just a couple of keystrokes.&lt;/p&gt;
&lt;p&gt;Admittedly, this is not solely a Jekyll feature, since much of it&amp;#8217;s utility depends on GitHub&amp;#8230; Still, I&amp;#8217;m viewing Jekyll from the angle of GitHub pages, so I think it&amp;#8217;s a fair point.&lt;/p&gt;
&lt;h2&gt;You can hack on it. Easily&lt;/h2&gt;
&lt;p&gt;The code for this blog is pretty much straight &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; or Textile, with maybe 2 loops (using Liquid) to display the list of blog posts. You can&amp;#8217;t get simpler than that.&lt;/p&gt;
&lt;h2&gt;And&amp;#8230;?&lt;/h2&gt;
&lt;p&gt;Okay, so that&amp;#8217;s only two points. But what more could you ask for in a blogging engine? Basically, the features &lt;span class=&quot;caps&quot;&gt;TPW&lt;/span&gt; wanted it to have are really useful, and seem to be exactly what I need to start blogging more often. Time will tell I suppose.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>My newest blog</title>
   <link href="http://lukerandall.github.com/2008/12/22/my-newest-blog.html"/>
   <updated>2008-12-22T00:00:00-08:00</updated>
   <id>http://lukerandall.github.com/2008/12/22/my-newest-blog</id>
   <content type="html">&lt;h1&gt;&lt;a href=&quot;/2008/12/22/my-newest-blog.html&quot;&gt;My newest blog&lt;/a&gt;&lt;/h1&gt;
&lt;p class=&quot;meta&quot;&gt;22 Dec 2008 &amp;#8211; Johannesburg&lt;/p&gt;
&lt;p&gt;Well, I&amp;#8217;m at it again &amp;#8211; creating a new blog. I think my blog:posts ratio is close enough to 1:1 that the actual variance is negligible. It&amp;#8217;s shocking really. My last blog contained exactly 1 post, as did the one before it, etc. Plus to offset the few blogs that have contained multiple posts, I&amp;#8217;ve created a few blogs that never even got their first post. For shame!&lt;/p&gt;
&lt;p&gt;Anyway, this is a shameless rip-off of &lt;a href=&quot;http://mojombo.github.com&quot;&gt;Mojombo&amp;#8217;s blog&lt;/a&gt;, which he has happily invited us all to rip-off. I&amp;#8217;m initially just interested in seeing my own name in Shiny letters on my GitHub page. I have high hopes of &amp;#8211; in time &amp;#8211; making this my own little creation. We&amp;#8217;ll see I suppose.&lt;/p&gt;</content>
 </entry>
 
 
</feed>