<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>s-expressions &#187; lisp</title>
	<atom:link href="http://s-expressions.com/tag/lisp/feed/" rel="self" type="application/rss+xml" />
	<link>http://s-expressions.com</link>
	<description>Amit Rathore blogs about software development</description>
	<lastBuildDate>Tue, 17 Jan 2012 17:58:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='s-expressions.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>s-expressions &#187; lisp</title>
		<link>http://s-expressions.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://s-expressions.com/osd.xml" title="s-expressions" />
	<atom:link rel='hub' href='http://s-expressions.com/?pushpress=hub'/>
		<item>
		<title>calling recur from catch or finally</title>
		<link>http://s-expressions.com/2010/08/15/calling-recur-from-catch-or-finally/</link>
		<comments>http://s-expressions.com/2010/08/15/calling-recur-from-catch-or-finally/#comments</comments>
		<pubDate>Sun, 15 Aug 2010 15:52:52 +0000</pubDate>
		<dc:creator>Amit Rathore</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[reliability]]></category>

		<guid isPermaLink="false">https://sexp.wordpress.com/?p=314</guid>
		<description><![CDATA[Clojure doesn&#8217;t have tail recursion, but does support the recur form. Let&#8217;s take a quick look at how it&#8217;s used. Consider a function that sums up a list of numbers to an accumulator: Lets ignore all the ways this can be done without the silly implementation above. Here it is in action: And here&#8217;s the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=314&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Clojure doesn&#8217;t have tail recursion, but does support the recur form. Let&#8217;s take a quick look at how it&#8217;s used. Consider a function that sums up a list of numbers to an accumulator: </p>
<p><pre class="brush: plain;">
(defn add-numbers [acc numbers]
  (if (empty? numbers)
    acc
    (add-numbers (+ acc (first numbers)) (rest numbers))))
</pre></p>
<p>Lets ignore all the ways this can be done without the silly implementation above. Here it is in action:</p>
<p><pre class="brush: plain;">
user&gt; (add-numbers 10 (range 10))
55
</pre><br />
And here&#8217;s the problem with it:</p>
<p><pre class="brush: plain;">
user&gt; (add-numbers 10 (range 10000))
; Evaluation aborted.
No message.
  [Thrown class java.lang.StackOverflowError]
</pre></p>
<p>The reason, of course, is that being a self-recursive function that calls itself explicitly, it blows the stack. Clojure has a way to get around this, via the recur form:</p>
<p><pre class="brush: plain;">
(defn add-numbers [acc numbers]
  (if (empty? numbers)
    acc
    (recur (+ acc (first numbers)) (rest numbers))))
</pre></p>
<p>And here is proof that it works:</p>
<p><pre class="brush: plain;">
user&gt; (add-numbers 10 (range 10000))
49995010
</pre></p>
<p>Now, let&#8217;s look at a case where one might want to recurse from inside a catch or finally block. A use-case is a function like connect-to-service, that must retry the connection if the service is unavailable. An easy way to implement it is to catch the exception thrown when the attempt at connecting fails, then wait a few seconds, and try again by recursing. Here&#8217;s a contrived example of a function that recurs from catch:</p>
<p><pre class="brush: plain;">
(defn catch-recurse [n i]
  (try
    (if (&gt; n i)
      (/ i 0)
      n)
    (catch Exception e
      (recur n (inc i)))))
</pre></p>
<p>The problem, of course, is that Clojure complains:</p>
<p><pre class="brush: plain;">
Cannot recur from catch/finally
  [Thrown class java.lang.UnsupportedOperationException]
</pre></p>
<p>So what to do? One way is to make the call explicitly, and hope that it won&#8217;t blow the stack:</p>
<p><pre class="brush: plain;">
(defn catch-recurse [n i]
  (try
    (if (&gt; n i)
      (/ i 0)
      n)
    (catch Exception e
      (catch-recurse n (inc i)))))
</pre></p>
<p>It could blow the stack, though, depending:</p>
<p><pre class="brush: plain;">
user&gt; (catch-recurse 100 1)
100
user&gt; (catch-recurse 10000 1)
; Evaluation aborted.
No message.
  [Thrown class java.lang.StackOverflowError]
</pre></p>
<p>As pointed out, this may blow the stack, but it may not, depending on your situation. If you know it won&#8217;t, then this may be OK. Here&#8217;s a way to avoid this situation completely, using trampoline. First, a minor change to catch-recurse:</p>
<p><pre class="brush: plain;">
(defn catch-recurse [n i]
  (try
    (if (&gt; n i)
      (/ i 0)
      n)
    (catch Exception e
      #(catch-recurse n (inc i)))))
</pre></p>
<p>Notice that in the case of an exception, we return a thunk. Now, to use our new function:</p>
<p><pre class="brush: plain;">
user&gt; (trampoline catch-recurse 100 1)
100
user&gt; (trampoline catch-recurse 10000 1)
10000
</pre></p>
<p>And there you have it. The common use-case of trampoline is to handle mutually recursive functions where recur isn&#8217;t useful. It checks to see if the return value of the function it&#8217;s passed in is another function. If so, it calls it. It repeats the process until a non-function value is returned, which it then itself returns. Very useful!</p>
<br />Filed under: <a href='http://s-expressions.com/category/uncategorized/'>Uncategorized</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sexp.wordpress.com/314/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sexp.wordpress.com/314/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sexp.wordpress.com/314/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sexp.wordpress.com/314/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sexp.wordpress.com/314/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sexp.wordpress.com/314/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sexp.wordpress.com/314/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sexp.wordpress.com/314/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sexp.wordpress.com/314/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sexp.wordpress.com/314/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sexp.wordpress.com/314/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sexp.wordpress.com/314/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sexp.wordpress.com/314/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sexp.wordpress.com/314/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=314&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://s-expressions.com/2010/08/15/calling-recur-from-catch-or-finally/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/69c7419d10661aa2ab01de450a0127b2?s=96&#38;d=monsterid" medium="image">
			<media:title type="html">Amit Rathore</media:title>
		</media:content>
	</item>
		<item>
		<title>Announcing WorkAtRuna.com</title>
		<link>http://s-expressions.com/2010/07/24/announcing-workatruna-com/</link>
		<comments>http://s-expressions.com/2010/07/24/announcing-workatruna-com/#comments</comments>
		<pubDate>Sun, 25 Jul 2010 06:25:11 +0000</pubDate>
		<dc:creator>Amit Rathore</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[dev-ops]]></category>
		<category><![CDATA[jobs]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[runa]]></category>

		<guid isPermaLink="false">https://sexp.wordpress.com/?p=310</guid>
		<description><![CDATA[We&#8217;ve put a bunch of content together about our work here at Runa, and about what it&#8217;s like to work here. If you&#8217;re a Clojure developer, or a DevOps extraordinaire, drop us a line! &#8220;In 1995, Paul Graham and Robert Morris used Common Lisp to help online merchants. Now, 15 years later, we&#8217;re doing the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=310&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve put a bunch of content together about our work here at Runa, and about what it&#8217;s like to work here. If you&#8217;re a Clojure developer, or a DevOps extraordinaire, drop us a line! </p>
<p><em>&#8220;In 1995, Paul Graham and Robert Morris used Common Lisp to help online merchants. Now, 15 years later, we&#8217;re doing the same with Clojure.&#8221;</em></p>
<p><strong>Read more at <a href="http://www.workatruna.com">www.workatruna.com</a></strong></p>
<br />Filed under: <a href='http://s-expressions.com/category/uncategorized/'>Uncategorized</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sexp.wordpress.com/310/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sexp.wordpress.com/310/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sexp.wordpress.com/310/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sexp.wordpress.com/310/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sexp.wordpress.com/310/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sexp.wordpress.com/310/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sexp.wordpress.com/310/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sexp.wordpress.com/310/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sexp.wordpress.com/310/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sexp.wordpress.com/310/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sexp.wordpress.com/310/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sexp.wordpress.com/310/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sexp.wordpress.com/310/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sexp.wordpress.com/310/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=310&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://s-expressions.com/2010/07/24/announcing-workatruna-com/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/69c7419d10661aa2ab01de450a0127b2?s=96&#38;d=monsterid" medium="image">
			<media:title type="html">Amit Rathore</media:title>
		</media:content>
	</item>
		<item>
		<title>Medusa 0.1 &#8211; a supervised thread-pool for Clojure futures</title>
		<link>http://s-expressions.com/2010/06/08/medusa-0-1-a-supervised-thread-pool-for-clojure-futures-2/</link>
		<comments>http://s-expressions.com/2010/06/08/medusa-0-1-a-supervised-thread-pool-for-clojure-futures-2/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 07:46:15 +0000</pubDate>
		<dc:creator>Amit Rathore</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[distributed-computing]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[mutli-core]]></category>
		<category><![CDATA[parallel]]></category>

		<guid isPermaLink="false">https://sexp.wordpress.com/?p=295</guid>
		<description><![CDATA[Clojure comes with two kinds of thread-pools &#8211; a bounded thread-pool for CPU-bound operations, and one for IO-bound operations that grows as needed. The bounded thread-pool is used every time an action is sent to an agent via the send function. The unbounded thread-pool is used (for instance) every time an action is sent to [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=295&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Clojure comes with two kinds of thread-pools &#8211; a bounded thread-pool for CPU-bound operations, and one for IO-bound operations that grows as needed. The bounded thread-pool is used every time an action is sent to an agent via the send function. The unbounded thread-pool is used (for instance) every time an action is sent to an agent using the send-off function. Futures also run on this unbounded thread-pool.</p>
<p>Sometimes, however, you might need a third option. This is the case where you don&#8217;t want an unbounded pool of threads that grows so much that the system runs out of resources trying to juggle the sheer number of threads. This might happen (say) if you were using send-off to handle incoming requests for IO-bound operations. Under normal circumstances, such a system might perform in an acceptable manner. If the request load were to spike, however, you could quickly create a larger-than-manageable number of threads.</p>
<p>What you need in such a case is a separate thread-pool for IO operations &#8211; one that has more threads than the one in the thread-pool for CPU-bound operations, but still bound so that it only grows to a certain size, and then any further requests get queued. Luckily, Clojure allows you to seamlessly use underlying Java libraries.</p>
<p>Medusa is a bounded, supervised thread-pool. A supervisor function runs alongside the thread-pool and it monitors the running tasks. If they take more than a specified amount of time, they are evicted. If the thread-pool is fully occupied, Medusa will queue all further tasks submitted and will run each task as soon as a thread becomes available. The Medusa thread-pool size is thrice the number of cores available to the JVM. In future versions, this number will be configurable.</p>
<p>Here it is in action -</p>
<p><pre class="brush: plain;">
(use 'org.rathore.amit.medusa.core)

(start-supervisor)

(defn new-task [id sleep-seconds]
  (println (System/currentTimeMillis) &quot;| Starting task&quot; id &quot;will sleep for&quot; sleep-seconds)
  (Thread/sleep (* 1000 sleep-seconds))
  (println (System/currentTimeMillis) &quot;| Done task&quot; id))

(defn run-tasks [n]
  (println &quot;Will submit&quot; n &quot;jobs&quot;)
  (dotimes [i n]
    (medusa-future i #(new-task i (* 5 (inc i))))))

(run-tasks 20)
</pre></p>
<p>The output is -</p>
<p><pre class="brush: plain;">
Will submit 20 jobs
1276068494442 | Starting task 0 will sleep for 5
1276068494448 | Starting task 1 will sleep for 10
1276068494449 | Starting task 2 will sleep for 15
1276068494449 | Starting task 3 will sleep for 20
1276068494451 | Starting task 4 will sleep for 25
1276068494451 | Starting task 5 will sleep for 30
1276068499447 | Done task 0
1276068499448 | Starting task 6 will sleep for 35
1276068504448 | Done task 1
1276068504448 | Starting task 7 will sleep for 40
1276068509448 | Done task 2
1276068509448 | Starting task 8 will sleep for 45
1276068514448 | Done task 3
1276068514449 | Starting task 9 will sleep for 50
1276068519450 | Starting task 10 will sleep for 55
1276068523547 | Starting task 11 will sleep for 60
1276068523548 | Starting task 13 will sleep for 70
1276068523547 | Starting task 12 will sleep for 65
1276068523548 | Starting task 14 will sleep for 75
1276068523548 | Starting task 15 will sleep for 80
1276068523549 | Starting task 16 will sleep for 85
1276068533547 | Starting task 17 will sleep for 90
1276068533547 | Starting task 18 will sleep for 95
1276068543547 | Starting task 19 will sleep for 100
</pre></p>
<p>Notice that the first few tasks complete, since the pre-emption time is 20 seconds. The rest of the tasks get pre-empted out of the thread-pool by the supervisor since they take too long (simulated above by the sleeps). Since all the later tasks have been coded to take more than 20 seconds, they will all get pre-empted. The Medusa thread-pool is then ready for more tasks. This pre-emption is what allows the other tasks to start, as can be seen by looking at the timestamps of the log messages. This fulfills the requirement that we have a bounded-threadpool with supervised pre-emption of tasks that take too long.</p>
<p>Here&#8217;s the thread-usage when the program starts, and the supervisor has started: </p>
<p><img src="http://sexp.files.wordpress.com/2010/06/medusa-0-1-011.jpg?w=826&#038;h=304" alt="Thread-pool when the program starts" border="0" width="826" height="304" /></p>
<p>Here&#8217;s the thread-usage when the tasks complete:</p>
<p><img src="http://sexp.files.wordpress.com/2010/06/medusa-0-1-021.jpg?w=807&#038;h=316" alt="Thread-pool when the tasks complete" border="0" width="807" height="316" /></p>
<p>The semantics are still not of the standard Clojure futures &#8211; currently, Medusa &#8220;futures&#8221; only handle side-effects. A next step would be to give them the same future semantics so that they return the result of their computation &#8211; that will come in the next version. </p>
<p>The project is hosted on github, as usual &#8211; <a href="http://github.com/amitrathore/medusa">http://github.com/amitrathore/medusa</a>. Click here to see the basic <a href="http://github.com/amitrathore/medusa/blob/master/src/org/rathore/amit/medusa/core.clj">implementation</a>.</p>
<br />Filed under: <a href='http://s-expressions.com/category/uncategorized/'>Uncategorized</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sexp.wordpress.com/295/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sexp.wordpress.com/295/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sexp.wordpress.com/295/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sexp.wordpress.com/295/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sexp.wordpress.com/295/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sexp.wordpress.com/295/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sexp.wordpress.com/295/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sexp.wordpress.com/295/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sexp.wordpress.com/295/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sexp.wordpress.com/295/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sexp.wordpress.com/295/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sexp.wordpress.com/295/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sexp.wordpress.com/295/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sexp.wordpress.com/295/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=295&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://s-expressions.com/2010/06/08/medusa-0-1-a-supervised-thread-pool-for-clojure-futures-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/69c7419d10661aa2ab01de450a0127b2?s=96&#38;d=monsterid" medium="image">
			<media:title type="html">Amit Rathore</media:title>
		</media:content>

		<media:content url="http://sexp.files.wordpress.com/2010/06/medusa-0-1-011.jpg" medium="image">
			<media:title type="html">Thread-pool when the program starts</media:title>
		</media:content>

		<media:content url="http://sexp.files.wordpress.com/2010/06/medusa-0-1-021.jpg" medium="image">
			<media:title type="html">Thread-pool when the tasks complete</media:title>
		</media:content>
	</item>
		<item>
		<title>conjure &#8211; simple mocking and stubbing for Clojure unit-tests</title>
		<link>http://s-expressions.com/2010/01/24/conjure-simple-mocking-and-stubbing-for-clojure-unit-tests/</link>
		<comments>http://s-expressions.com/2010/01/24/conjure-simple-mocking-and-stubbing-for-clojure-unit-tests/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 07:28:37 +0000</pubDate>
		<dc:creator>Amit Rathore</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[DSL]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://sexp.wordpress.com/?p=281</guid>
		<description><![CDATA[Siva and I were pairing on a unit-test that involved writing something to HBase. When Siva said that mocking the call to the save-to-hbase function would make testing easier (a simple thing using JMock, he said), I decided to write a quick mocking utility for Clojure. Then later, we realized that we wanted to go [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=281&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Siva and I were pairing on a unit-test that involved writing something to HBase. When Siva said that mocking the call to the <em>save-to-hbase</em> function would make testing easier (a simple thing using JMock, he said), I decided to write a quick mocking utility for Clojure. </p>
<p>Then later, we realized that we wanted to go one step further.  The row-id that was used as the key to the object in HBase was generated using system-time. That meant that even if we wanted to confirm that the object was indeed saved, we had no way of knowing what the row-id was. One solution to such a problem is to inject the row-id in (instead of being tightly coupled to the function that generated the row-id). Instead, I wrote a stubbing utility that makes this arbitrarily easy to do.</p>
<p>So here they are &#8211; <em>mocking</em> and <em>stubbing</em> &#8211; packaged up as the <a href="http://github.com/amitrathore/conjure">conjure</a> project on github.</p>
<h2>The set up</h2>
<p>Imagine we had the following functions -</p>
<p><pre class="brush: plain;">
(defn xx [a b]
  10)

(defn yy [z]
  20)

(defn fn-under-test []
  (xx 1 2)
  (yy  &quot;blah&quot;))

(defn another-fn-under-test []
  (+ (xx nil nil) (yy nil)))
</pre></p>
<p>Also imagine that we had to test <em>fn-under-test</em> and <em>another-fn-under-test</em>, and we didn&#8217;t want to have to deal with the <em>xx</em> or <em>yy</em> functions. Maybe they&#8217;re horrible functions that open connections to computers running Windoze or something, I dunno.</p>
<h2>Mocking</h2>
<p>Here&#8217;s how we might mock them out -</p>
<p><pre class="brush: plain;">
(deftest test-basic-mocking
  (mocking [xx yy]
    (fn-under-test))
  (verify-call-times-for xx 1)
  (verify-call-times-for yy 1)
  (verify-first-call-args-for xx 1 2)
  (verify-first-call-args-for yy &quot;blah&quot;))
</pre></p>
<p>Pretty straightforward, eh? You just use the <em>mocking</em> macro, specifying all the functions that need to be mocked out. Then, within the scope of <em>mocking</em>, you call your functions that need to be tested. The calls to the specified functions will get mocked out (they won&#8217;t occur), and you can then use things like <em>verify-call-times-for</em> and <em>verify-first-call-args-for</em> to ensure things worked as expected.</p>
<h2>Stubbing</h2>
<p>As mentioned in the intro to this post, sometimes your tests need to specify values to be returned by the functions being mocked out. That&#8217;s where <em>stubbing</em> comes in. Here&#8217;s how it works -</p>
<p><pre class="brush: plain;">
(deftest test-basic-stubbing
  (is (= (another-fn-under-test) 30))
  (stubbing [xx 1 yy 2]
    (is (= (another-fn-under-test) 3))))
</pre></p>
<p>So that&#8217;s it! Pretty simple. Note how within the scope of <em>stubbing</em>, <em>xx</em> returns 1 and <em>yy</em> returns 2. Now, for the implementation.</p>
<h2>Implementation</h2>
<p>The code is almost embarrassingly straight-forward. Take a look -</p>
<p><pre class="brush: plain;">
(ns org.rathore.amit.conjure.core
  (:use clojure.test))

(def call-times (atom {}))

(defn stub-fn [function-name return-value]
  (swap! call-times assoc function-name [])
  (fn [&amp; args]
    (swap! call-times update-in [function-name] conj args)
    return-value))

(defn mock-fn [function-name]
  (stub-fn function-name nil))

(defn verify-call-times-for [fn-name number]
  (is (= number (count (@call-times fn-name)))))

(defn verify-first-call-args-for [fn-name &amp;amp;amp; args]
  (is (= args (first (@call-times fn-name)))))

(defn verify-nth-call-args-for [n fn-name &amp;amp;amp; args]
  (is (= args (nth (@call-times fn-name) (dec n)))))

(defn clear-calls []
  (reset! call-times {}))

(defmacro mocking [fn-names &amp;amp;amp; body]
  (let [mocks (map #(list 'mock-fn %) fn-names)]
    `(binding [~@(interleave fn-names mocks)]
       ~@body)))

(defmacro stubbing [stub-forms &amp;amp;amp; body]
  (let [stub-pairs (partition 2 stub-forms)
        fn-names (map first stub-pairs)
        stubs (map #(list 'stub-fn (first %) (last %)) stub-pairs)]
    `(binding [~@(interleave fn-names stubs)]
       ~@body)))
</pre></p>
<p>It&#8217;s just an hour or so of work, so it&#8217;s probably rough, and certainly doesn&#8217;t support more complex features of other mocking/stubbing libraries. But I thought the simplicity was enjoyable.</p>
<br />Posted in Uncategorized  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sexp.wordpress.com/281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sexp.wordpress.com/281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sexp.wordpress.com/281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sexp.wordpress.com/281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sexp.wordpress.com/281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sexp.wordpress.com/281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sexp.wordpress.com/281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sexp.wordpress.com/281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sexp.wordpress.com/281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sexp.wordpress.com/281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sexp.wordpress.com/281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sexp.wordpress.com/281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sexp.wordpress.com/281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sexp.wordpress.com/281/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=281&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://s-expressions.com/2010/01/24/conjure-simple-mocking-and-stubbing-for-clojure-unit-tests/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/69c7419d10661aa2ab01de450a0127b2?s=96&#38;d=monsterid" medium="image">
			<media:title type="html">Amit Rathore</media:title>
		</media:content>
	</item>
		<item>
		<title>frumiOS &#8211; a simple object-system for Clojure</title>
		<link>http://s-expressions.com/2009/12/10/frumios-a-silly-object-system-for-clojure/</link>
		<comments>http://s-expressions.com/2009/12/10/frumios-a-silly-object-system-for-clojure/#comments</comments>
		<pubDate>Thu, 10 Dec 2009 08:14:44 +0000</pubDate>
		<dc:creator>Amit Rathore</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[DSL]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[metaprogramming]]></category>

		<guid isPermaLink="false">http://sexp.wordpress.com/?p=254</guid>
		<description><![CDATA[I&#8217;ve nearly stopped blogging, because all my spare time goes into writing Clojure in Action. But I was a bit bored this weekend, and wrote this little library that can be used to write traditional looking Object-Oriented (TM) code in Clojure. Why would you do that, when you can use a rifle-oriented programming style instead? [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=254&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve nearly stopped blogging, because all my spare time goes into writing <a href="http://www.clojureinaction.com/">Clojure in Action</a>. But I was a bit bored this weekend, and wrote this little library that can be used to write traditional looking Object-Oriented (TM) code in Clojure.</p>
<p>Why would you do that, when you can use a <a href="http://blog.thinkrelevance.com/2009/8/12/rifle-oriented-programming-with-clojure-2">rifle-oriented programming</a> style instead? Think of it like using the rifle as a club&#8230; On the other had, the implementation makes plenty use of closures and macros, so it is probably a rifle-oriented program <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>The implementation is hosted on github, in a project called <a href="https://github.com/amitrathore/frumios/blob/master/src/org/rathore/amit/frumios/core.clj">frumios</a>. And if you reall want to see it now, click below.</p>
<p><pre class="brush: plain; collapse: true; light: false; toolbar: true;">
(ns org.rathore.amit.frumios.core)
 
(declare new-object find-method) 
 
(defn new-class [class-name parent methods]
  (let [klass ((comp resolve symbol name) class-name)]
    (fn [command &amp; args]
      (cond
	(= :parent command) parent
	(= :name command) klass
	(= :method-names command) (keys methods)
	(= :methods command) methods
	(= :new command) (new-object klass)
	(= :method command) 
          (let [[method-name] args]
	    (find-method method-name methods parent))
	:else (throw (RuntimeException. (str &quot;Unknown message: &quot; command)))))))
 
(def OBJECT (new-class :org.rathore.amit.frumios.core/OBJECT nil {}))
(def this)
 
(defn new-object [klass]
  (let [state (ref {})]
    (fn thiz [command &amp; args]
      (cond
        (= :class command) klass
        (= :set! command) (let [[k v] args]
			    (dosync (alter state assoc k v))
			    nil)
        (= :get command) (let [[key] args]
			   (state key))
        :else (let [method (klass :method command)]
		(if method 
		  (binding [this thiz]
		    (apply method args))))))))
 
(defn find-method [method-name instance-methods parent-class]
  (let [method (instance-methods method-name)]
    (or method
	(if-not (= #'org.rathore.amit.frumios.core/OBJECT parent-class)
	  (find-method method-name (parent-class :methods) (parent-class :parent))))))
 
(defn parent-class-spec [sexprs]
  (let [extends-spec (filter #(= :extends (first %)) sexprs)
        extends (first extends-spec)]
    (if (empty? extends)
      'org.rathore.amit.frumios.core/OBJECT
      (do 
	(if-not (= 1 (count extends-spec))
	  (throw (RuntimeException. &quot;defclass only accepts a single extends clause&quot;)))
	(if-not (= 2 (count extends))
	  (throw (RuntimeException. &quot;the extends clause only accepts a single parent class&quot;)))
	(last extends)))))
 
(defn method-spec [sexpr]
  (let [name (keyword (second sexpr))
	remaining (next sexpr)]
    {name (conj remaining 'fn)}))
 
(defn method-specs [sexprs]
  (let [method-spec? #(= 'method (first %))
	specs (filter method-spec? sexprs)]
    (apply merge (map method-spec sexprs))))
 
(defmacro defclass [class-name &amp; specs]
  (let [parent-class-symbol (parent-class-spec specs)
        this-class-name (keyword class-name)
	fns (method-specs specs)]
    `(def ~class-name 
        (new-class ~this-class-name (var ~parent-class-symbol) ~(or fns {})))))
</pre></p>
<p>But first, examples -</p>
<p><pre class="brush: plain;">
(ns frumios-spec)

(use 'org.rathore.amit.frumios.core)

(defclass animal
  (method sound []
    &quot;grr&quot;)

  (method say-something []
    (str (this :sound) &quot;, I say!&quot;))

  (method move []
    &quot;going!&quot;))

(defclass cat
  (:extends animal)

  (method sound []
    &quot;meow&quot;))
</pre></p>
<p>There, that defines a simple class hierarchy. Let&#8217;s examine these classes -</p>
<p><pre class="brush: plain;">
frumios-spec&gt; (cat :parent)
#'frumios-spec/animal

frumios-spec&gt; (animal :parent)
#'org.rathore.amit.frumios.core/OBJECT

frumios-spec&gt; (animal :method-names)
(:move :say-something :sound)

frumios-spec&gt; (cat :method-names)
(:sound)
</pre></p>
<p>Now, let&#8217;s define a couple of instances -</p>
<p><pre class="brush: plain;">
(def a (animal :new))
(def c (cat :new))
</pre></p>
<p>What can we do with these instances? Let&#8217;s explore -</p>
<p><pre class="brush: plain;">
frumios-spec&gt; (c :class)
#'frumios-spec/cat

frumios-spec&gt; (c :set! :name &quot;Mr. Muggles&quot;)
nil

frumios-spec&gt; (c :get :name)
&quot;Mr. Muggles&quot;
</pre></p>
<p>That&#8217;s the basic stuff, how about calling methods?</p>
<p><pre class="brush: plain;">
frumios-spec&gt; (a :move)
&quot;going!&quot;

frumios-spec&gt; (a :sound)
&quot;grr&quot;

frumios-spec&gt; (c :sound)
&quot;meow&quot;
</pre></p>
<p>Notice how cat overrides the sound method. OK, how about a method that calls another method? It calls for the this keyword. Here it is in action -</p>
<p><pre class="brush: plain;">
frumios-spec&gt; (a :say-something)
&quot;grr, I say!&quot;

frumios-spec&gt; (c :say-something)
&quot;meow, I say!&quot;
</pre></p>
<p>Notice how in the second call, <em>(this :sound)</em> resolved itself to the overridden <em>sound</em> method in the <em>cat</em> class. That&#8217;s subtype polymorphism, common to languages such as Java and Ruby. We could use it to implement something like the template pattern. We can do fairly arbitrary things with frumiOS -</p>
<p><pre class="brush: plain;">
(defclass person
  (method greet [visitor]
    (println &quot;Hi&quot; visitor &quot;, I'm here!&quot;))

  (method dob []
    (str &quot;I was born on &quot; (this :get :birth-date)))

  (method age []
    2)

  (method experience [years]
    (str years &quot; years&quot;))

  (method bio []
    (let [msg (str (this :dob) &quot;, and have &quot; (this :experience (this :age)) &quot; of experience.&quot;)]
      (println msg))))
</pre></p>
<p>Let&#8217;s play with it -</p>
<p><pre class="brush: plain;">
frumios-spec&gt; (def kyle (person :new))
#'frumios-spec/kyle

frumios-spec&gt; (kyle :greet &quot;rob&quot;)
Hi rob , I'm here!
nil
</pre></p>
<p>The <em>bio</em> method makes two calls using the <em>this</em> construct, one nested inside the other. It works as expected -</p>
<p><pre class="brush: plain;">
frumios-spec&gt; (kyle :set! :birth-date &quot;1977-01-01&quot;)
nil

frumios-spec&gt; (kyle :bio)
I was born on 1977-01-01, and have 2 years of experience.
nil
</pre></p>
<p>So there it is. I&#8217;m sure it doesn&#8217;t do lots of stuff a real object-system does. But at 70 lines of Clojure code, you can&#8217;t expect a whole lot more. Silly as this is, I had fun writing it! <a href="https://github.com/amitrathore/frumios/blob/master/src/org/rathore/amit/frumios/core.clj">Click here</a> to see how the frumiOS is implemented.</p>
<br />Posted in Uncategorized  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sexp.wordpress.com/254/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sexp.wordpress.com/254/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sexp.wordpress.com/254/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sexp.wordpress.com/254/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sexp.wordpress.com/254/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sexp.wordpress.com/254/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sexp.wordpress.com/254/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sexp.wordpress.com/254/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sexp.wordpress.com/254/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sexp.wordpress.com/254/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sexp.wordpress.com/254/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sexp.wordpress.com/254/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sexp.wordpress.com/254/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sexp.wordpress.com/254/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=254&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://s-expressions.com/2009/12/10/frumios-a-silly-object-system-for-clojure/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/69c7419d10661aa2ab01de450a0127b2?s=96&#38;d=monsterid" medium="image">
			<media:title type="html">Amit Rathore</media:title>
		</media:content>
	</item>
		<item>
		<title>Clojure, the REPL and test-driven development</title>
		<link>http://s-expressions.com/2009/07/28/clojure-the-repl-and-test-driven-development/</link>
		<comments>http://s-expressions.com/2009/07/28/clojure-the-repl-and-test-driven-development/#comments</comments>
		<pubDate>Wed, 29 Jul 2009 07:59:45 +0000</pubDate>
		<dc:creator>Amit Rathore</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[functional]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[unit-testing]]></category>

		<guid isPermaLink="false">http://sexp.wordpress.com/2009/07/28/clojure-the-repl-and-test-driven-development/</guid>
		<description><![CDATA[I’ve been using Clojure for nearly a year now, and something strange has been happening&#8230; I still think unit-tesitng is extremely important, but for some reason I don’t seem to be writing the same number of tests any more. I’m ashamed to say it, but there it is. And it gets stranger &#8211; this new [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=232&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I’ve been using Clojure for nearly a year now, and something strange has been happening&#8230; I still think unit-tesitng is extremely important, but for some reason I don’t seem to be writing the same number of tests any more. I’m ashamed to say it, but there it is. And it gets stranger &#8211; this new lower test count doesn’t seem to matter. </p>
<p>It seems to me that my Clojure code works right the first time more often than my Ruby or Java code ever did. And I seem to find less defects in the Clojure code over time, too.</p>
<p>This is  not just a fanboy speaking, though I am a huge fan of Clojure. I think that the reasons I’m observing this is due to a an important characteristic of the language. Instead of just talking about it, let me first walk you through an example.</p>
<p>This is something I had to do recently &#8211; we wanted to build a kind of reverse index for an HBase table. The row ids of this table are time-stamps. The idea was that this “reverse index” would allow us to answer the question of what the first time-stamp for a given day was. In other words, we needed to convert a list of time-stamps into a lookup of day vs. the first time-stamp of that day. Eg.</p>
<p>Input: </p>
<pre><code>
[“112323123” “1231231231” “123123123” “ 1231231123” ....]
 </code></pre>
<p>Output:</p>
<pre><code>
{“2009-07-01” “123123123”
 “2009-07-02” “123131213”
 “2009-07-03” “123123122”}
 </code></pre>
<p>(Note: I plucked the numbers out of the air, they aren&#8217;t accurate. But the idea is that the input is a long stream of timestamps, and possibly hundreds could correspond to each day.) </p>
<p>So I get started&#8230; thinking to myself &#8211; I know how to convert a timestamp to a day. From there, it’s easy to write a function that returns a hash containing the day vs. timestamp (Since I already had a function day-for-timestamp, it was easy) -</p>
<pre><code>
(defn day-vs-timestamp [time-stamp]
  {(day-for-time-stamp time-stamp) time-stamp})
</code></pre>
<p></p>
<p>So now, all I have to do is map the above function across the input. This gives me a list of hash-maps, each with one key-value pair. To ensure that I’m doing this in order of oldest first, I sort the input as well. Inside of a let form, all of this looks like &#8211; </p>
<pre><code>
(let [all-pairs (map day-vs-timestamp (sort input-list))]
</code></pre>
<p></p>
<p>Now, I have this list of hashes, each with one key (the day) and one corresponding value (the time-stamp itself). I want to combine these into one single hash-map which would be the final answer. But I have to deal with the issue of duplicate keys &#8211; when I find a duplicate key, I want to keep the first value associated with the key since it would be the oldest. </p>
<p>Clojure has a merge-with function which does just this &#8211; it accepts a function with 2 arguments (which are the two values in case a duplicate key is found) and the returning value is used in the merged hash-map.</p>
<pre><code>
(apply merge-with #(first [%1 %2]) all-pairs)
</code></pre>
<p></p>
<p>That’s basically it.</p>
<p>Combining everything -</p>
<pre><code>
(defn day-vs-timestamp [time-stamp]
  {(day-for-time-stamp time-stamp) time-stamp})

(defn lookup-table [input-timestamps]
  (let [all-pairs (map day-vs-timestamp (sort input-list))]
    (apply merge-with #(first [%1 %2]) all-pairs)))
</code></pre>
<p></p>
<p>When I write code like this &#8211; I often ask myself, what exactly should I test? I end up writing a few happy path tests that prove my code works. And then a couple of tests that test border cases and negative paths. And I sometimes do it test first.</p>
<p>But the REPL has spoilt me. What I used TDD for when coding with Ruby (and still do), I often do at the REPL. I build tiny functions that work &#8211; these are often single lines of code. Then I combine these into other functions, often no more than two lines of code each, sometimes three. And it all just works &#8211; leaving me wondering what to cover with tests. </p>
<p>The main reason I still write tests is for regression &#8211; if something breaks in the future, I catch it quickly. However, the other thing &#8211; the test *driven* design aspect of TDD &#8211; has been somewhat replaced by the REPL. And its very much more dynamic than a set of static tests. It really brings out the rapid, in rapid application development &#8211; especially when combined with <a href="http://homepage.mac.com/zenitani/emacs-e.html">Emacs</a> and <a href="http://common-lisp.net/project/slime/">SLIME</a>.</p>
<p>One main difference with Clojure vs. Ruby (say) is that Clojure is functional (I use very little of Clojure’s constructs for state). And in the functional world, I just don’t have to worry about state (obviously), and this tremendously simplifies code. I think in terms of map, filter, reduce, some, every, merge, etc. and the actual logic is in tiny functions used from within these other higher level constructs. The idea of first-class functions is also key &#8211; I can build up the business logic by writing small functions that do a tiny thing each &#8211; and combine them using higher-order functions.</p>
<p>This is one reason why <a href="http://runa.com">we’re</a> so productive with Clojure. We’ve moved to Clojure for 90% of our work. That said, we still use Ruby for parts of our code-base, and it’s still my favorite imperative language <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<br />Posted in Uncategorized  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sexp.wordpress.com/232/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sexp.wordpress.com/232/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sexp.wordpress.com/232/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sexp.wordpress.com/232/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sexp.wordpress.com/232/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sexp.wordpress.com/232/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sexp.wordpress.com/232/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sexp.wordpress.com/232/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sexp.wordpress.com/232/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sexp.wordpress.com/232/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sexp.wordpress.com/232/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sexp.wordpress.com/232/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sexp.wordpress.com/232/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sexp.wordpress.com/232/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=232&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://s-expressions.com/2009/07/28/clojure-the-repl-and-test-driven-development/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/69c7419d10661aa2ab01de450a0127b2?s=96&#38;d=monsterid" medium="image">
			<media:title type="html">Amit Rathore</media:title>
		</media:content>
	</item>
		<item>
		<title>Capjure: a simple HBase persistence layer &#8211; updated with documentation</title>
		<link>http://s-expressions.com/2009/05/25/capjure-a-simple-hbase-persistence-layer-updated-with-documentation/</link>
		<comments>http://s-expressions.com/2009/05/25/capjure-a-simple-hbase-persistence-layer-updated-with-documentation/#comments</comments>
		<pubDate>Tue, 26 May 2009 05:47:45 +0000</pubDate>
		<dc:creator>Amit Rathore</dc:creator>
				<category><![CDATA[clojure]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[webscale]]></category>

		<guid isPermaLink="false">http://sexp.wordpress.com/?p=228</guid>
		<description><![CDATA[This is just to let folks know I&#8217;ve (finally) written up some documentation on how to use capjure. Hope it helps!<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=228&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>This is just to let folks know I&#8217;ve (finally) written up some documentation on how to use <a href="http://github.com/amitrathore/capjure">capjure</a>. Hope it helps!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sexp.wordpress.com/228/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sexp.wordpress.com/228/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sexp.wordpress.com/228/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sexp.wordpress.com/228/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sexp.wordpress.com/228/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sexp.wordpress.com/228/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sexp.wordpress.com/228/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sexp.wordpress.com/228/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sexp.wordpress.com/228/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sexp.wordpress.com/228/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sexp.wordpress.com/228/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sexp.wordpress.com/228/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sexp.wordpress.com/228/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sexp.wordpress.com/228/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=228&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://s-expressions.com/2009/05/25/capjure-a-simple-hbase-persistence-layer-updated-with-documentation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/69c7419d10661aa2ab01de450a0127b2?s=96&#38;d=monsterid" medium="image">
			<media:title type="html">Amit Rathore</media:title>
		</media:content>
	</item>
		<item>
		<title>Startup logbook &#8211; v0.2 &#8211; distributed Clojure system in production</title>
		<link>http://s-expressions.com/2009/05/02/startup-logbook-distributed-clojure-system-in-production-v02/</link>
		<comments>http://s-expressions.com/2009/05/02/startup-logbook-distributed-clojure-system-in-production-v02/#comments</comments>
		<pubDate>Sun, 03 May 2009 04:55:09 +0000</pubDate>
		<dc:creator>Amit Rathore</dc:creator>
				<category><![CDATA[clojure]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[startup]]></category>
		<category><![CDATA[webscale]]></category>

		<guid isPermaLink="false">http://sexp.wordpress.com/?p=210</guid>
		<description><![CDATA[This past weekend, we pushed another major release into production. We&#8217;ve been working on several things and have made a few pushes since the last time I wrote about this &#8211; but this release has a bunch of interesting Clojure related stuff. Long-running processes The main thing of note is that the majority of our [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=210&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>This past weekend, we pushed another major release into production. We&#8217;ve been working on several things and have made a few pushes since the <a href="/2009/01/28/startup-logbook-clojure-in-production-release-v01/">last time</a> I wrote about this &#8211; but this release has a bunch of interesting Clojure related stuff.</p>
<h2>Long-running processes</h2>
<p>The main thing of note is that the majority of our back-end is now written in Clojure. You might recall that our online-merchant customers send us a lot of data, and we run a ton of analytics on that data. Our initial plans involved Ruby, but as we started using Clojure, it turned out that it is very well suited for this job as well (long running, message-driven processes that crunch numbers).</p>
<p>The raw data sits in HBase, and every night a &#8220;master&#8221; process starts up which kicks-off the processing of the previous day&#8217;s worth of data. The job of this master is only to coordinate the work (it doesn&#8217;t actually do any real work), it does this by breaking work into chunks and dispatching messages that each assign work to any worker process that picks it up. The master is single threaded for simplicity, but failure tolerant &#8211; it checkpoints everything in a local MySQL database, and if it crashes, it is automatically re-spawned and it recovers from where it left off.</p>
<p><img src="http://sexp.files.wordpress.com/2009/05/clojure-in-production-v02.png?w=559&#038;h=570" border="0" alt="clojure-in-production-v0.2.png" width="559" height="570" /></p>
<p>An elastic cloud of worker processes run in anticipation of the master handing out this work. The worker processes use the MySQL database to keep track of their progress as well. The rest is rather domain-specific. We use intermediate representations of the raw data, which is also stored in HBase, before finally storing the summarized version again in HBase.</p>
<h2>Swarmiji</h2>
<p>We use an in-house distributed-programming framework called Swarmiji to make such distributed programs very easy to write and run. Swarmiji implements a flavor of <a href="http://www.eecs.harvard.edu/~mdw/proj/seda/">staged event-driven architecture (SEDA)</a> to allow server processes that exhibit scalable, predictable throughput. This is especially true in the face of over-load, which we can certainly expect in our environment.</p>
<p>The reason I wrote this framework was that I wanted to create distributed, parallel programs which exploited large numbers of machines (like in a data-center) &#8211; without being limited by clojure&#8217;s in-JVM-threads-based model. So each worker process in Swarmiji gets deployed as a shared-nothing JVM process.</p>
<p>I will write up a post introducing Swarmiji in the next few weeks &#8211; once its a bit more battle-tested, and I&#8217;ve added a few more features (mainly around process management).</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sexp.wordpress.com/210/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sexp.wordpress.com/210/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sexp.wordpress.com/210/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sexp.wordpress.com/210/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sexp.wordpress.com/210/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sexp.wordpress.com/210/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sexp.wordpress.com/210/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sexp.wordpress.com/210/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sexp.wordpress.com/210/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sexp.wordpress.com/210/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sexp.wordpress.com/210/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sexp.wordpress.com/210/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sexp.wordpress.com/210/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sexp.wordpress.com/210/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=210&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://s-expressions.com/2009/05/02/startup-logbook-distributed-clojure-system-in-production-v02/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/69c7419d10661aa2ab01de450a0127b2?s=96&#38;d=monsterid" medium="image">
			<media:title type="html">Amit Rathore</media:title>
		</media:content>

		<media:content url="http://sexp.files.wordpress.com/2009/05/clojure-in-production-v02.png" medium="image">
			<media:title type="html">clojure-in-production-v0.2.png</media:title>
		</media:content>
	</item>
		<item>
		<title>The first meetup of the Bay Area Clojure User Group</title>
		<link>http://s-expressions.com/2009/02/08/the-first-meetup-of-the-bay-area-clojure-user-group/</link>
		<comments>http://s-expressions.com/2009/02/08/the-first-meetup-of-the-bay-area-clojure-user-group/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 07:20:24 +0000</pubDate>
		<dc:creator>Amit Rathore</dc:creator>
				<category><![CDATA[clojure]]></category>
		<category><![CDATA[languages]]></category>
		<category><![CDATA[learning]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[meetings]]></category>

		<guid isPermaLink="false">http://sexp.wordpress.com/?p=136</guid>
		<description><![CDATA[We held the first meeting of the BACUG (ugh, that&#8217;s a tedious acronym) last week, on Thursday the 5th of February. I was expecting about 6-8 people to show up, but we had about 12 people, quite a nice turn out! After introductions and such, Chris Turner presented his unit-testing library for clojure called Clojure [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=136&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>We held the first meeting of the <a href="http://www.meetup.com/The-Bay-Area-Clojure-User-Group/">BACUG</a> (ugh, that&#8217;s a tedious acronym) last week, on Thursday the 5th of February. I was expecting about 6-8 people to show up, but we had about 12 people, quite a nice turn out!</p>
<p>After introductions and such, Chris Turner presented his unit-testing library for clojure called <a href="http://bitbucket.org/BestFriendChris/clojure-spec/">Clojure Spec</a>. We talked about testing in general, and because he uses a lot of macro-writing macros in his code, we talked about macros in general and the difficulty in debugging macros. It was a good discussion &#8211; though I did throw in (tongue-in-cheek) that we&#8217;re using <a href="http://stuartsierra.com/software/clojure-stuff">Test Is</a> at Cinch. Thanks Chris, it was a good presentation.</p>
<p>After that talk, I gave an introduction to <a href="/2009/01/28/startup-logbook-clojure-in-production-release-v01/">how we&#8217;re presently using Clojure</a> in our startup. Since we&#8217;re using HBase as our persistent data-store, and processing that data using a bunch of clojure processes, we talked about data-modeling for HBase-like systems (I will write about my implementation of that data-model in another post).</p>
<p>An interesting thread came up &#8211; led by Joe Mikhail who works at Google and obviously does a lot of Map/Reduce/BigTable stuff &#8211; around how at least in the beginning, multi-threaded clojure processes can be used in place of Hadoop when processing HBase data. And he did mention that using systems like <a href="http://terracotta.org/">Terracotta</a>, one can scale up such solutions. We&#8217;re going to look into that next week.</p>
<p>The remainder of the meeting went by in a buzz of talking about different languages, technologies, and general geek topics. The one thing of interest here was the point that software transactional memory is no panacea (surprise!) to the whole concurrency thing. Here&#8217;s an <a href="http://mags.acm.org/queue/200809/?folio=16&amp;CFID=21585861&amp;CFTOKEN=56482284">ACM article</a> (there are several actually, just keep turning the pages) that throws some light on the issue. Here&#8217;s <a href="http://mags.acm.org/communications/200811/?folio=40&amp;CFID=21585843&amp;CFTOKEN=76434741">another</a>.</p>
<p>Overall, it was a very good meeting &#8211; we&#8217;re hoping that the next one would be attended by more people, and especially some folks that have used other Lisps in the past &#8211; we&#8217;re all curious about what such folks think about Clojure. Indeed, and we want to learn from their experience in using idiomatic Lisp.</p>
<p>I&#8217;m thinking that we&#8217;ll do another Clojure meetup in about 6 weeks or so&#8230; <a href="http://www.meetup.com/The-Bay-Area-Clojure-User-Group/">join up</a>, and stay tuned!</p>
<p>P.S. &#8211; A shout of thanks to my employer <a href="http://www.runa.com/">Runa</a>. for hosting this meeting.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sexp.wordpress.com/136/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sexp.wordpress.com/136/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sexp.wordpress.com/136/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sexp.wordpress.com/136/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sexp.wordpress.com/136/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sexp.wordpress.com/136/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sexp.wordpress.com/136/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sexp.wordpress.com/136/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sexp.wordpress.com/136/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sexp.wordpress.com/136/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sexp.wordpress.com/136/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sexp.wordpress.com/136/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sexp.wordpress.com/136/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sexp.wordpress.com/136/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=136&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://s-expressions.com/2009/02/08/the-first-meetup-of-the-bay-area-clojure-user-group/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/69c7419d10661aa2ab01de450a0127b2?s=96&#38;d=monsterid" medium="image">
			<media:title type="html">Amit Rathore</media:title>
		</media:content>
	</item>
		<item>
		<title>Startup logbook &#8211; v0.1 &#8211; Clojure in production</title>
		<link>http://s-expressions.com/2009/01/28/startup-logbook-clojure-in-production-release-v01/</link>
		<comments>http://s-expressions.com/2009/01/28/startup-logbook-clojure-in-production-release-v01/#comments</comments>
		<pubDate>Wed, 28 Jan 2009 09:44:42 +0000</pubDate>
		<dc:creator>Amit Rathore</dc:creator>
				<category><![CDATA[architecture]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[multi-paradigm]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[startup]]></category>

		<guid isPermaLink="false">http://s-expressions.com/?p=128</guid>
		<description><![CDATA[Late last night, around 3 AM to be exact, we made one of our usual releases to production (unfortunately, we&#8217;re still in semi-stealth mode, so I&#8217;m not talking a lot about our product yet &#8211; I will in a few weeks). There was nothing particularly remarkable about the release from a business point of view. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=128&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Late last night, around 3 AM to be exact, we made one of our usual releases to production (unfortunately, we&#8217;re still in semi-stealth mode, so I&#8217;m not talking a lot about our product yet &#8211; I will in a few weeks). There was nothing particularly remarkable about the release from a business point of view. It had a couple of enhancements to functionality, and a couple of bug-fixes.</p>
<p>What was rather interesting, at least to the geek in me, was that it was something of a technology milestone for us. It was the first production release of a new architecture that I&#8217;d been working on over the past 2-3 weeks. Our service contains several pieces, and until this release we had a rather traditional architecture &#8211; we were using ruby on rails for all our back-end logic (eg. real-time analytics and pricing calculations) as well as the user-facing website. And we were using mysql for our storage requirements.</p>
<p>This release has seen our production system undergo some changes. Going forward, the rails portion will continue to do what it was originally designed for &#8211; supporting a user-facing web-UI. The run-time service is now a combination of rails and a cluster of <a href="http://clojure.org">clojure</a> processes.</p>
<p>When data needs to be collected (for further analytics down the line), the rails application simply drops <a href="http://json.org">JSON</a> messages on a queue (we&#8217;re using the excellent erlang-based RabbitMQ), and one of a cluster of clojure processes picks it up, processes it, and stores it in an <a href="http://hadoop.apache.org/hbase/">HBase</a> store. Since each message can result in several actions that need to be performed (and these are mostly independent), clojure&#8217;s safe concurrency helps a lot. And since its a <a href="/2007/02/14/lisp-syntax-and-when-code-is-data/">lisp</a>, the code is just so much shorter than equivalent ruby could ever be.</p>
<p>Currently, all business rules, analytics, and pricing calculations are still being handled by the ruby/rails code. Over the next few releases we&#8217;re looking to move away from this &#8211; to instead let the clojure processes do most of the heavy lifting.</p>
<p>We&#8217;re hoping we can continue to do this in a highly incremental fashion, as the risk of trying to get this perfect the first time is too high. We absolutely need to get the feedback that only production can give us &#8211; so we&#8217;re more sure that we&#8217;re building the thing right.</p>
<p>The last few days have been the most fun I&#8217;ve had in any job so far. Besides learning clojure, and hadoop/ hbase pretty much at the same time (and getting paid for doing that!), it has also been a great opportunity to do this as <a href="http://epistemologic.com/2008/11/03/what-iteration-less-agile-really-means/">incrementally</a> as possible. I strongly believe in <a href="http://xp123.com/xplor/xp0611/index.shtml">set-based engineering</a> methods, and this is the approach I took with this as well &#8211; currently, we haven&#8217;t turned off the ruby/rails/mysql system &#8211; it is doing essentially the same thing that the new clojure/hbase system is doing. We&#8217;re looking to build the rest of the system out (incrementally), ensure it works (and repeat until it does) &#8211; before turning off the (nearly legacy) ruby system.</p>
<p>I&#8217;ll keep posting as I progress on this front. Overall, we&#8217;re very excited at the possibilities that using clojure represents &#8211; and hey, if it turns out to be a mistake &#8211; we&#8217;ll <a href="/2009/01/16/design-for-throwability/">throw</a> it out instead.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sexp.wordpress.com/128/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sexp.wordpress.com/128/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sexp.wordpress.com/128/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sexp.wordpress.com/128/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sexp.wordpress.com/128/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sexp.wordpress.com/128/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sexp.wordpress.com/128/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sexp.wordpress.com/128/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sexp.wordpress.com/128/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sexp.wordpress.com/128/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sexp.wordpress.com/128/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sexp.wordpress.com/128/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sexp.wordpress.com/128/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sexp.wordpress.com/128/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=s-expressions.com&amp;blog=4254185&amp;post=128&amp;subd=sexp&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://s-expressions.com/2009/01/28/startup-logbook-clojure-in-production-release-v01/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/69c7419d10661aa2ab01de450a0127b2?s=96&#38;d=monsterid" medium="image">
			<media:title type="html">Amit Rathore</media:title>
		</media:content>
	</item>
	</channel>
</rss>
