<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>Clojure and me</title>
	
	<link>http://clj-me.cgrand.net</link>
	<description>When the pupil is ready to learn, a teacher will appear.</description>
	<lastBuildDate>Thu, 10 Jun 2010 13:11:51 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/ClojureAndMe" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="clojureandme" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Primitive types support for fns coming to a Clojure branch near you</title>
		<link>http://clj-me.cgrand.net/2010/06/10/primitive-types-support-for-fns-coming-to-a-clojure-branch-near-you/</link>
		<comments>http://clj-me.cgrand.net/2010/06/10/primitive-types-support-for-fns-coming-to-a-clojure-branch-near-you/#comments</comments>
		<pubDate>Thu, 10 Jun 2010 06:57:32 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[unsorted]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=382</guid>
		<description><![CDATA[Rich Hickey is working on primitive support in the prim branch. As of now, one can write:
(defn ^:static fib ^long [^long n]
  (if (&#62;= (long 1) n)
    (long 1)
    (+ (fib (dec n)) (fib (- n (long 2))))))
and computes (fib 38) on my laptop in 650ms where my [...]]]></description>
			<content:encoded><![CDATA[<p>Rich Hickey is working on primitive support in <a href="http://github.com/richhickey/clojure/commits/prim">the <code>prim</code> branch</a>. As of now, one can write:</p>
<pre class="highlight"><span class="p">(</span><span class="k">defn </span><span class="nv">^:static</span> <span class="nv">fib</span> <span class="nv">^long</span> <span class="p">[</span><span class="nv">^long</span> <span class="nv">n</span><span class="p">]</span>
  <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">&gt;= </span><span class="p">(</span><span class="nb">long </span><span class="mi">1</span><span class="p">)</span> <span class="nv">n</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">long </span><span class="mi">1</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">+ </span><span class="p">(</span><span class="nf">fib</span> <span class="p">(</span><span class="nb">dec </span><span class="nv">n</span><span class="p">))</span> <span class="p">(</span><span class="nf">fib</span> <span class="p">(</span><span class="nb">- </span><span class="nv">n</span> <span class="p">(</span><span class="nb">long </span><span class="mi">2</span><span class="p">))))))</span></pre>
<p>and computes (fib 38) on my laptop in 650ms where my (or even Rich&#8217;s) best <a href="http://clj-me.cgrand.net/2010/06/04/primitive-support-for-fns/">attempt took about 2s!</a> If I tweak the above code to use unchecked ops (regular arithmetic ops on primitive types in Clojure throw an exception on overflow, unchecked ones don&#8217;t), the performance comes real real close (< 5%) to the equivalent Java code.</p>
<h2>What&#8217;s this <code class="highlight"><span class="nv">^:static</span></code> thing?</h2>
<p>Primitive (double and long only: they subsume any other type) args and return values are only allowed on <i>statics</i> (note that the return type hint is put on the arglist so as to allow different hints for different arities). Statics are still fns in vars but they are backed by a static method and, when called by name, a direct static method call is emitted rather than going through the var and the <ode lang="java">IFn</code> interface &mdash; as such static calls replace direct binding.</p>
<pre class="highlight"><span class="p">(</span><span class="nf">my-static</span> <span class="mi">42</span><span class="p">)</span> <span class="c1">; direct call</span>
<span class="p">(</span><span class="nb">apply </span><span class="nv">my-static</span> <span class="mi">42</span> <span class="nv">nil</span><span class="p">)</span> <span class="c1">; regular call through the var</span></pre>
<p>About the syntax: <code class="highlight"><span class="nv">^:keyword</span></code> is a new reader shorthand for <code class="highlight"><span class="nv">^</span><span class="p">{</span><span class="nv">:keyword</span> <span class="nv">true</span><span class="p">}</span></code> (and keep in mind that in Clojure 1.2 <code class="highlight"><span class="nv">^</span></code> is the new <code class="highlight"><span class="o">#</span><span class="nv">^</span></code>), and metadata are merged: <code class="highlight"><span class="nv">^:static</span> <span class="nv">^long</span> <span class="nv">^</span><span class="p">{</span><span class="nv">:doc</span> <span class="s">&quot;docstring&quot;</span><span class="p">}</span> <span class="nv">x</span></code> is now equivalent to <code class="highlight"><span class="nv">^</span><span class="p">{</span><span class="nv">:static</span> <span class="nv">true</span> <span class="nv">:tag</span> <span class="nv">long</span> <span class="nv">:doc</span> <span class="s">&quot;docstring&quot;</span><span class="p">}</span> <span class="nv">x</span></code>.</p>
<p>Interesting times... as usual in the Clojure community. Thanks Rich!</p>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/7bn3d-ZxMNg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2010/06/10/primitive-types-support-for-fns-coming-to-a-clojure-branch-near-you/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Primitive types support for fns</title>
		<link>http://clj-me.cgrand.net/2010/06/04/primitive-support-for-fns/</link>
		<comments>http://clj-me.cgrand.net/2010/06/04/primitive-support-for-fns/#comments</comments>
		<pubDate>Fri, 04 Jun 2010 08:25:16 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[unsorted]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=368</guid>
		<description><![CDATA[Follow up See here.

Update: I was wrong and Rich Hickey set me right: I didn&#8217;t measure the gains I&#8217;m expecting because the inline-expanded form still go through the var lookup. See here (or the comments) for real gains (around 800ms on my laptop).

This is a quick and dirty hack to emulate primitive types support for [...]]]></description>
			<content:encoded><![CDATA[<p><b>Follow up</b> <a href="http://clj-me.cgrand.net/2010/06/10/primitive-types-support-for-fns-coming-to-a-clojure-branch-near-you/">See here.</a><br />
<hr/>
<p><b>Update:</b> I was wrong and Rich Hickey <a href="http://clojure-log.n01se.net/date/2010-06-04.html#06:57-08:28">set me right</a>: I didn&#8217;t measure the gains I&#8217;m expecting because the inline-expanded form still go through the var lookup. <a href="http://gist.github.com/425352#comments">See here</a> (or <a href="http://gist.github.com/425352#gistcomment-3339">the comments</a>) for real gains (around 800ms on my laptop).<br />
<hr/>
<p>This is a quick and dirty hack to emulate primitive types support for globally-bound fns:</p>
<pre class="highlight"><span class="p">(</span><span class="k">defmacro </span><span class="nv">defhintedfn</span> <span class="p">[</span><span class="nv">name</span> <span class="nv">args</span> <span class="nv">&amp;</span> <span class="nv">body</span><span class="p">]</span>
  <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">iface</span> <span class="p">(</span><span class="nb">gensym </span><span class="s">&quot;HintedFn&quot;</span><span class="p">)</span>
        <span class="nv">hname</span> <span class="p">(</span><span class="nf">vary-meta</span> <span class="nv">name</span> <span class="nv">assoc</span> <span class="nv">:tag</span> <span class="nv">iface</span><span class="p">)</span>
        <span class="nv">vname</span> <span class="p">(</span><span class="nf">vary-meta</span> <span class="nv">name</span> <span class="nv">assoc</span>
                <span class="nv">:inline</span> <span class="p">(</span><span class="k">fn </span><span class="p">[</span><span class="nv">&amp;</span> <span class="nv">args</span><span class="p">]</span> <span class="o">`</span><span class="p">(</span><span class="o">.</span><span class="nv">invoke</span> <span class="nv">~hname</span> <span class="nv">~@args</span><span class="p">)))]</span>
    <span class="o">`</span><span class="p">(</span><span class="nf">do</span>
       <span class="p">(</span><span class="nf">definterface</span> <span class="nv">~iface</span>
         <span class="p">(</span><span class="nf">~</span><span class="p">(</span><span class="nb">with-meta </span><span class="ss">&#39;invoke</span> <span class="p">{</span><span class="nv">:tag</span> <span class="p">(</span><span class="nf">:tag</span> <span class="nv">name</span> <span class="nv">Object</span><span class="p">)})</span> <span class="nv">~args</span><span class="p">))</span>
       <span class="p">(</span><span class="k">def </span><span class="nv">~vname</span> <span class="nv">nil</span><span class="p">)</span> <span class="c1">; workaround for a soon-to-be-fixed bug</span>
       <span class="p">(</span><span class="k">def </span><span class="nv">~vname</span>
          <span class="p">(</span><span class="nf">reify</span>
            <span class="nv">~iface</span>
              <span class="p">(</span><span class="nf">invoke</span> <span class="p">[</span><span class="nv">this</span><span class="o">#</span> <span class="nv">~@args</span><span class="p">]</span>
                <span class="nv">~@body</span><span class="p">)</span>
            <span class="nv">clojure</span><span class="o">.</span><span class="nv">lang</span><span class="o">.</span><span class="nv">IFn</span>
              <span class="p">(</span><span class="nf">^Object</span> <span class="nv">invoke</span> <span class="p">[</span><span class="nv">this</span><span class="o">#</span> <span class="nv">~@</span><span class="p">(</span><span class="nb">map </span><span class="o">#</span><span class="p">(</span><span class="nv">vary-meta</span> <span class="nv">%</span> <span class="nv">dissoc</span> <span class="nv">:tag</span><span class="p">)</span> <span class="nv">args</span><span class="p">)]</span>
                 <span class="nv">~@body</span><span class="p">))))))</span></pre>
<p>As you can see the trick is to generate a dedicated interface and to inline calls to the defined fn to go through the specific interface rather than through IFn.</p>
<p>Let&#8217;s define a dumb numeric fn generating tons of calls: the fibonacci function! Below it comes in three flavors: hinted as int, hinted as long and plain.</p>
<pre class="highlight"><span class="p">(</span><span class="nf">defhintedfn</span> <span class="nv">^int</span> <span class="nv">hfib</span> <span class="p">[</span><span class="nv">^int</span> <span class="nv">n</span><span class="p">]</span> <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">&gt;= </span><span class="p">(</span><span class="nb">int </span><span class="mi">1</span><span class="p">)</span> <span class="nv">n</span><span class="p">)</span> <span class="p">(</span><span class="nb">int </span><span class="mi">1</span><span class="p">)</span> <span class="p">(</span><span class="nb">+ </span><span class="p">(</span><span class="nf">hfib</span> <span class="p">(</span><span class="nb">dec </span><span class="nv">n</span><span class="p">))</span> <span class="p">(</span><span class="nf">hfib</span> <span class="p">(</span><span class="nb">- </span><span class="nv">n</span> <span class="p">(</span><span class="nb">int </span><span class="mi">2</span><span class="p">))))))</span>
<span class="p">(</span><span class="nf">defhintedfn</span> <span class="nv">^long</span> <span class="nv">lfib</span> <span class="p">[</span><span class="nv">^long</span> <span class="nv">n</span><span class="p">]</span> <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">&gt;= </span><span class="p">(</span><span class="nb">long </span><span class="mi">1</span><span class="p">)</span> <span class="nv">n</span><span class="p">)</span> <span class="p">(</span><span class="nb">long </span><span class="mi">1</span><span class="p">)</span> <span class="p">(</span><span class="nb">+ </span><span class="p">(</span><span class="nf">lfib</span> <span class="p">(</span><span class="nb">dec </span><span class="nv">n</span><span class="p">))</span> <span class="p">(</span><span class="nf">lfib</span> <span class="p">(</span><span class="nb">- </span><span class="nv">n</span> <span class="p">(</span><span class="nb">long </span><span class="mi">2</span><span class="p">))))))</span>
<span class="p">(</span><span class="k">defn </span><span class="nv">fib</span> <span class="p">[</span><span class="nv">n</span><span class="p">]</span> <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">&gt;= </span><span class="mi">1</span> <span class="nv">n</span><span class="p">)</span> <span class="mi">1</span> <span class="p">(</span><span class="nb">+ </span><span class="p">(</span><span class="nf">fib</span> <span class="p">(</span><span class="nb">dec </span><span class="nv">n</span><span class="p">))</span> <span class="p">(</span><span class="nf">fib</span> <span class="p">(</span><span class="nb">- </span><span class="nv">n</span> <span class="mi">2</span><span class="p">)))))</span></pre>
<p>And here are the timings:</p>
<pre class="highlight"><span class="nv">user=&gt;</span> <span class="p">(</span><span class="nb">time </span><span class="p">(</span><span class="nf">hfib</span> <span class="mi">38</span><span class="p">))</span>
<span class="s">&quot;Elapsed time: 2016.128098 msecs&quot;</span>
<span class="mi">63245986</span>
<span class="nv">user=&gt;</span> <span class="p">(</span><span class="nb">time </span><span class="p">(</span><span class="nf">lfib</span> <span class="mi">38</span><span class="p">))</span>
<span class="s">&quot;Elapsed time: 2896.46198 msecs&quot;</span>
<span class="mi">63245986</span>
<span class="nv">user=&gt;</span> <span class="p">(</span><span class="nb">time </span><span class="p">(</span><span class="nf">fib</span> <span class="mi">38</span><span class="p">))</span>
<span class="s">&quot;Elapsed time: 4704.449867 msecs&quot;</span>
<span class="mi">63245986</span></pre>
<p>Please note that hinted fns are still regular fns:</p>
<pre class="highlight"><span class="nv">user=&gt;</span> <span class="p">(</span><span class="nb">map </span><span class="nv">hfib</span> <span class="p">(</span><span class="nb">range </span><span class="mi">10</span><span class="p">))</span>
<span class="p">(</span><span class="mi">1</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span> <span class="mi">5</span> <span class="mi">8</span> <span class="mi">13</span> <span class="mi">21</span> <span class="mi">34</span> <span class="mi">55</span><span class="p">)</span></pre>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/cDYEKI8vV88" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2010/06/04/primitive-support-for-fns/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Destructuring, records, protocols and named arguments</title>
		<link>http://clj-me.cgrand.net/2010/05/08/destructuring-records-prototypes-and-named-arguments/</link>
		<comments>http://clj-me.cgrand.net/2010/05/08/destructuring-records-prototypes-and-named-arguments/#comments</comments>
		<pubDate>Sat, 08 May 2010 10:19:31 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[optimization]]></category>
		<category><![CDATA[pondering]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=319</guid>
		<description><![CDATA[Warning: this post is full of microbenchmarks so take it with a pinch of salt.
Destructuring a record
Field access through keyword-lookups on records is fast:
user=&#62; (defrecord Foo [a b])
user.Foo
user=&#62; (let [x (Foo. 1 2)] (dotimes [_ 5] (time (dotimes [_ 1e7] (let [a (:a x) b (:b x)] [a b])))))
&#34;Elapsed time: 114.787424 msecs&#34;
&#34;Elapsed time: 102.568273 msecs&#34;
&#34;Elapsed [...]]]></description>
			<content:encoded><![CDATA[<p>Warning: this post is full of microbenchmarks so take it with a pinch of salt.</p>
<h3>Destructuring a record</h3>
<p>Field access through keyword-lookups on records is fast:
<pre class="highlight"><span class="nv">user=&gt;</span> <span class="p">(</span><span class="nf">defrecord</span> <span class="nv">Foo</span> <span class="p">[</span><span class="nv">a</span> <span class="nv">b</span><span class="p">])</span>
<span class="nv">user</span><span class="o">.</span><span class="nv">Foo</span>
<span class="nv">user=&gt;</span> <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">x</span> <span class="p">(</span><span class="nf">Foo</span><span class="o">.</span> <span class="mi">1</span> <span class="mi">2</span><span class="p">)]</span> <span class="p">(</span><span class="nb">dotimes </span><span class="p">[</span><span class="nv">_</span> <span class="mi">5</span><span class="p">]</span> <span class="p">(</span><span class="nb">time </span><span class="p">(</span><span class="nb">dotimes </span><span class="p">[</span><span class="nv">_</span> <span class="mi">1</span><span class="nv">e7</span><span class="p">]</span> <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">a</span> <span class="p">(</span><span class="nf">:a</span> <span class="nv">x</span><span class="p">)</span> <span class="nv">b</span> <span class="p">(</span><span class="nf">:b</span> <span class="nv">x</span><span class="p">)]</span> <span class="p">[</span><span class="nv">a</span> <span class="nv">b</span><span class="p">])))))</span>
<span class="s">&quot;Elapsed time: 114.787424 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 102.568273 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 71.150593 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 72.217418 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 70.127489 msecs&quot;</span>
<span class="nv">nil</span></pre>
<p>But as far as I know <code class="highlight"><span class="nv">destructure</span></code> still emits <code class="highlight"><span class="p">(</span><span class="nb">get </span><span class="nv">x</span> <span class="nv">:k</span><span class="p">)</span></code>, let check:
<pre class="highlight"><span class="nv">user=&gt;</span> <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">x</span> <span class="p">(</span><span class="nf">Foo</span><span class="o">.</span> <span class="mi">1</span> <span class="mi">2</span><span class="p">)]</span> <span class="p">(</span><span class="nb">dotimes </span><span class="p">[</span><span class="nv">_</span> <span class="mi">5</span><span class="p">]</span> <span class="p">(</span><span class="nb">time </span><span class="p">(</span><span class="nb">dotimes </span><span class="p">[</span><span class="nv">_</span> <span class="mi">1</span><span class="nv">e7</span><span class="p">]</span> <span class="p">(</span><span class="k">let </span><span class="p">[{</span><span class="nv">:keys</span> <span class="p">[</span><span class="nv">a</span> <span class="nv">b</span><span class="p">]}</span> <span class="nv">x</span><span class="p">]</span> <span class="p">[</span><span class="nv">a</span> <span class="nv">b</span><span class="p">])))))</span>
<span class="s">&quot;Elapsed time: 968.616612 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 945.704133 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 911.290751 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 927.658125 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 916.796408 msecs&quot;</span>
<span class="nv">nil</span></pre>
<p>Actually it&#8217;s slightly slower than lookup on <i>small</i> maps:
<pre class="highlight"><span class="nv">user=&gt;</span> <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">x</span> <span class="p">{</span><span class="nv">:a</span> <span class="mi">1</span> <span class="nv">:b</span> <span class="mi">2</span><span class="p">}]</span> <span class="p">(</span><span class="nb">dotimes </span><span class="p">[</span><span class="nv">_</span> <span class="mi">5</span><span class="p">]</span> <span class="p">(</span><span class="nb">time </span><span class="p">(</span><span class="nb">dotimes </span><span class="p">[</span><span class="nv">_</span> <span class="mi">1</span><span class="nv">e7</span><span class="p">]</span> <span class="p">(</span><span class="k">let </span><span class="p">[{</span><span class="nv">:keys</span> <span class="p">[</span><span class="nv">a</span> <span class="nv">b</span><span class="p">]}</span> <span class="nv">x</span><span class="p">]</span> <span class="p">[</span><span class="nv">a</span> <span class="nv">b</span><span class="p">])))))</span>
<span class="s">&quot;Elapsed time: 866.942377 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 746.273968 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 734.366239 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 729.346188 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 746.96393 msecs&quot;</span>
<span class="nv">nil</span></pre>
<h3>One patch later</h3>
<p>I <a href="http://github.com/cgrand/clojure/commit/fa130144e4466472b45db2e393ca3c3704036174">patched <code class="highlight"><span class="nv">destructure</span></code></a> to emit keyword-lookups:
<pre class="highlight"><span class="nv">user=&gt;</span> <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">x</span> <span class="p">(</span><span class="nf">Foo</span><span class="o">.</span> <span class="mi">1</span> <span class="mi">2</span><span class="p">)]</span> <span class="p">(</span><span class="nb">dotimes </span><span class="p">[</span><span class="nv">_</span> <span class="mi">5</span><span class="p">]</span> <span class="p">(</span><span class="nb">time </span><span class="p">(</span><span class="nb">dotimes </span><span class="p">[</span><span class="nv">_</span> <span class="mi">1</span><span class="nv">e7</span><span class="p">]</span> <span class="p">(</span><span class="k">let </span><span class="p">[{</span><span class="nv">:keys</span> <span class="p">[</span><span class="nv">a</span> <span class="nv">b</span><span class="p">]}</span> <span class="nv">x</span><span class="p">]</span> <span class="p">[</span><span class="nv">a</span> <span class="nv">b</span><span class="p">])))))</span>
<span class="s">&quot;Elapsed time: 479.911064 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 488.895167 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 464.617431 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 480.944575 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 464.969779 msecs&quot;</span>
<span class="nv">nil</span></pre>
<p>It&#8217;s better but still slower than without destructuring. Let see what slows us:
<pre class="highlight"><span class="nv">user=&gt;</span> <span class="p">(</span><span class="nb">macroexpand-1 </span><span class="o">&#39;</span><span class="p">(</span><span class="k">let </span><span class="p">[{</span><span class="nv">:keys</span> <span class="p">[</span><span class="nv">a</span> <span class="nv">b</span><span class="p">]}</span> <span class="nv">x</span><span class="p">]</span> <span class="p">[</span><span class="nv">a</span> <span class="nv">b</span><span class="p">]))</span>
<span class="p">(</span><span class="nf">let*</span> <span class="p">[</span><span class="nv">map__3838</span> <span class="nv">x</span> <span class="nv">map__3838</span> <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nf">clojure</span><span class="o">.</span><span class="nv">core/seq?</span> <span class="nv">map__3838</span><span class="p">)</span> <span class="p">(</span><span class="nf">clojure</span><span class="o">.</span><span class="nv">core/apply</span> <span class="nv">clojure</span><span class="o">.</span><span class="nv">core/hash-map</span> <span class="nv">map__3838</span><span class="p">)</span> <span class="nv">map__3838</span><span class="p">)</span> <span class="nv">b</span> <span class="p">(</span><span class="nf">:b</span> <span class="nv">map__3838</span><span class="p">)</span> <span class="nv">a</span> <span class="p">(</span><span class="nf">:a</span> <span class="nv">map__3838</span><span class="p">)]</span> <span class="p">[</span><span class="nv">a</span> <span class="nv">b</span><span class="p">])</span></pre>
<p>My bet is on the <code class="highlight"><span class="nv">if+seq?</span></code> so I remove it:
<pre class="highlight"><span class="nv">user=&gt;</span> <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">x</span> <span class="p">(</span><span class="nf">Foo</span><span class="o">.</span> <span class="mi">1</span> <span class="mi">2</span><span class="p">)]</span> <span class="p">(</span><span class="nb">dotimes </span><span class="p">[</span><span class="nv">_</span> <span class="mi">5</span><span class="p">]</span> <span class="p">(</span><span class="nb">time </span><span class="p">(</span><span class="nb">dotimes </span><span class="p">[</span><span class="nv">_</span> <span class="mi">1</span><span class="nv">e7</span><span class="p">]</span> <span class="p">(</span><span class="nf">let*</span> <span class="p">[</span><span class="nv">map__3838</span> <span class="nv">x</span> <span class="nv">map__3838</span> <span class="nv">map__3838</span> <span class="nv">b</span> <span class="p">(</span><span class="nf">:b</span> <span class="nv">map__3838</span><span class="p">)</span> <span class="nv">a</span> <span class="p">(</span><span class="nf">:a</span> <span class="nv">map__3838</span><span class="p">)]</span> <span class="p">[</span><span class="nv">a</span> <span class="nv">b</span><span class="p">])))))</span>
<span class="s">&quot;Elapsed time: 125.188397 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 103.041099 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 70.061558 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 70.793984 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 69.759146 msecs&quot;</span>
<span class="nv">nil</span></pre>
<p>This <code class="highlight"><span class="nv">if+seq?</span></code> allows for <a href="http://groups.google.com/group/clojure/browse_thread/thread/a032e4cba6398776/5504a45b73cc0d42">named arguments</a>. I wonder if this behaviour should be an option of map-destructuring (eg <code class="highlight"><span class="p">{</span><span class="nv">:keys</span> <span class="p">[</span><span class="nv">a</span> <span class="nv">b</span><span class="p">]</span> <span class="nv">:named-args</span> <span class="nv">true</span><span class="p">}</span></code>). Anyway I had in mind that such a dispatch could be optimized with protocols.</p>
<h3>Optimizing dispatch with protocols</h3>
<pre class="highlight"><span class="nv">user=&gt;</span> <span class="p">(</span><span class="nf">defprotocol</span> <span class="nv">Seq</span> <span class="p">(</span><span class="nf">my-seq</span> <span class="p">[</span><span class="nv">this</span><span class="p">])</span> <span class="p">(</span><span class="nf">my-seq?</span> <span class="p">[</span><span class="nv">this</span><span class="p">]))</span>
<span class="nv">Seq</span>
<span class="nv">user=&gt;</span> <span class="p">(</span><span class="nf">extend-protocol</span> <span class="nv">Seq</span>
<span class="nv">clojure</span><span class="o">.</span><span class="nv">lang</span><span class="o">.</span><span class="nv">ISeq</span>
<span class="p">(</span><span class="nf">my-seq</span> <span class="p">[</span><span class="nv">this</span><span class="p">]</span> <span class="p">(</span><span class="o">.</span><span class="nv">seq</span> <span class="nv">this</span><span class="p">))</span>
<span class="p">(</span><span class="nf">my-seq?</span> <span class="p">[</span><span class="nv">this</span><span class="p">]</span> <span class="nv">true</span><span class="p">)</span>
<span class="nv">Object</span>
<span class="p">(</span><span class="nf">my-seq</span> <span class="p">[</span><span class="nv">this</span><span class="p">]</span> <span class="p">(</span><span class="nf">clojure</span><span class="o">.</span><span class="nv">lang</span><span class="o">.</span><span class="nv">RT/seq</span> <span class="nv">this</span><span class="p">))</span>
<span class="p">(</span><span class="nf">my-seq?</span> <span class="p">[</span><span class="nv">this</span><span class="p">]</span> <span class="nv">false</span><span class="p">))</span>
<span class="nv">nil</span></pre>
<p>Let see how my-seq? compares to seq?
<pre class="highlight"><span class="nv">user=&gt;</span> <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">x</span> <span class="p">(</span><span class="nf">Foo</span><span class="o">.</span> <span class="mi">1</span> <span class="mi">2</span><span class="p">)]</span> <span class="p">(</span><span class="nb">dotimes </span><span class="p">[</span><span class="nv">_</span> <span class="mi">5</span><span class="p">]</span> <span class="p">(</span><span class="nb">time </span><span class="p">(</span><span class="nb">dotimes </span><span class="p">[</span><span class="nv">_</span> <span class="mi">1</span><span class="nv">e7</span><span class="p">]</span> <span class="p">(</span><span class="nf">let*</span> <span class="p">[</span><span class="nv">map__3838</span> <span class="nv">x</span> <span class="nv">map__3838</span> <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nf">my-seq?</span> <span class="nv">map__3838</span><span class="p">)</span> <span class="p">(</span><span class="nf">clojure</span><span class="o">.</span><span class="nv">core/apply</span> <span class="nv">clojure</span><span class="o">.</span><span class="nv">core/hash-map</span> <span class="nv">map__3838</span><span class="p">)</span> <span class="nv">map__3838</span><span class="p">)</span> <span class="nv">b</span> <span class="p">(</span><span class="nf">:b</span> <span class="nv">map__3838</span><span class="p">)</span> <span class="nv">a</span> <span class="p">(</span><span class="nf">:a</span> <span class="nv">map__3838</span><span class="p">)]</span> <span class="p">[</span><span class="nv">a</span> <span class="nv">b</span><span class="p">])))))</span>
<span class="s">&quot;Elapsed time: 179.282982 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 161.781526 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 154.307042 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 155.567677 msecs&quot;</span>
<span class="s">&quot;Elapsed time: 153.716604 msecs&quot;</span>
<span class="nv">nil</span></pre>
<p>Hence <code class="highlight"><span class="nv">my-seq?</span></code> is 3x faster than <code class="highlight"><span class="nv">seq?</span></code> which means that protocols are indeed speedy: yet another incredible piece of work by Rich Hickey!</p>
<p>I&#8217;m still exploring how low-level protocols fns behave in a concurrent setting, stay tuned! </p>
<p>Meanwhile don&#8217;t forget to register to the next <a href="http://conj-labs.eu/">European Clojure training session</a> taught by <a href="http://www.bestinclass.dk/">Lau</a> and me.<br />
<!--
<pre class="highlight"></pre>
<p><code class="highlight"></code> --></p>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/VUChURWX6Is" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2010/05/08/destructuring-records-prototypes-and-named-arguments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>European Clojure Training, Brussels, late June</title>
		<link>http://clj-me.cgrand.net/2010/04/14/european-clojure-training-brussels-late-june/</link>
		<comments>http://clj-me.cgrand.net/2010/04/14/european-clojure-training-brussels-late-june/#comments</comments>
		<pubDate>Wed, 14 Apr 2010 10:29:04 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[unsorted]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=305</guid>
		<description><![CDATA[Following a recent tweet, I&#8217;m setting up a Clojure training session with Lau B. Jensen and we&#8217;d like to know more about our potential attendees. Please fill this short survey:
Loading&#8230;
(click here if you don&#8217;t see the above form.)
]]></description>
			<content:encoded><![CDATA[<p>Following a <a href="http://twitter.com/cgrand/status/11473920276">recent tweet</a>, I&#8217;m setting up a Clojure training session with <a href="http://www.bestinclass.dk/index.php/blog/">Lau B. Jensen</a> and we&#8217;d like to know more about our potential attendees. Please fill this short survey:</p>
<p><iframe src="http://spreadsheets.google.com/embeddedform?formkey=dFVqa2pqZ0ZDQU5wOHFSZTgxUTlhQVE6MA" width="700" height="760" frameborder="0" marginheight="0" marginwidth="0">Loading&#8230;</iframe><br />
(<a href="http://spreadsheets.google.com/formResponse?formkey=dFVqa2pqZ0ZDQU5wOHFSZTgxUTlhQVE6MA&#038;theme=0AX42CRMsmRFbUy03NTAzM2Q4My03ODU1LTQ2NzItODI2YS1kZmU5YzdiMzZjOGQ&#038;ptok=9092854397959694515&#038;ifq">click here</a> if you don&#8217;t see the above form.)</p>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/N0LPFkr5GUU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2010/04/14/european-clojure-training-brussels-late-june/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pipe dreams aren’t necessarily made of promises</title>
		<link>http://clj-me.cgrand.net/2010/04/02/pipe-dreams-are-not-necessarily-made-of-promises/</link>
		<comments>http://clj-me.cgrand.net/2010/04/02/pipe-dreams-are-not-necessarily-made-of-promises/#comments</comments>
		<pubDate>Fri, 02 Apr 2010 12:31:35 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[unsorted]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=293</guid>
		<description><![CDATA[Because of the spinning nature of atoms, it&#8217;s kind of a hack (a fun hack but still a hack) to build queues on it. Here is the same pipe function built on Java queues:
(defn pipe []
  (let [q (java.util.concurrent.LinkedBlockingQueue.)
        EOQ (Object.)
       [...]]]></description>
			<content:encoded><![CDATA[<p>Because of the spinning nature of atoms, it&#8217;s kind of <a href="http://clj-me.cgrand.net/2009/11/18/are-pipe-dreams-made-of-promises/">a hack (a fun hack but still a hack) to build queues on it</a>. Here is the same <code land="clj">pipe</code> function built on Java queues:</p>
<pre class="highlight"><span class="p">(</span><span class="k">defn </span><span class="nv">pipe</span> <span class="p">[]</span>
  <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">q</span> <span class="p">(</span><span class="nf">java</span><span class="o">.</span><span class="nv">util</span><span class="o">.</span><span class="nv">concurrent</span><span class="o">.</span><span class="nv">LinkedBlockingQueue</span><span class="o">.</span><span class="p">)</span>
        <span class="nv">EOQ</span> <span class="p">(</span><span class="nf">Object</span><span class="o">.</span><span class="p">)</span>
        <span class="nv">NIL</span> <span class="p">(</span><span class="nf">Object</span><span class="o">.</span><span class="p">)</span>
        <span class="nv">s</span> <span class="p">(</span><span class="k">fn </span><span class="nv">s</span> <span class="p">[]</span> <span class="p">(</span><span class="nf">lazy-seq</span> <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">x</span> <span class="p">(</span><span class="o">.</span><span class="nv">take</span> <span class="nv">q</span><span class="p">)]</span>
                               <span class="p">(</span><span class="nb">when-not </span><span class="p">(</span><span class="nb">= </span><span class="nv">EOQ</span> <span class="nv">x</span><span class="p">)</span>
                                 <span class="p">(</span><span class="nb">cons </span><span class="p">(</span><span class="nb">when-not </span><span class="p">(</span><span class="nb">= </span><span class="nv">NIL</span> <span class="nv">x</span><span class="p">)</span> <span class="nv">x</span><span class="p">)</span> <span class="p">(</span><span class="nf">s</span><span class="p">))))))]</span>
    <span class="p">[(</span><span class="nf">s</span><span class="p">)</span> <span class="p">(</span><span class="k">fn </span><span class="p">([]</span> <span class="p">(</span><span class="o">.</span><span class="nv">put</span> <span class="nv">q</span> <span class="nv">EOQ</span><span class="p">))</span> <span class="p">([</span><span class="nv">x</span><span class="p">]</span> <span class="p">(</span><span class="o">.</span><span class="nv">put</span> <span class="nv">q</span> <span class="p">(</span><span class="nb">or </span><span class="nv">x</span> <span class="nv">NIL</span><span class="p">))))]))</span></pre>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/i3cKR6leoQU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2010/04/02/pipe-dreams-are-not-necessarily-made-of-promises/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>The reasons why Enlive templates return seqs of strings</title>
		<link>http://clj-me.cgrand.net/2010/02/10/why-enlive-templates-return-seqs-of-strings/</link>
		<comments>http://clj-me.cgrand.net/2010/02/10/why-enlive-templates-return-seqs-of-strings/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 10:03:29 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[unsorted]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=276</guid>
		<description><![CDATA[The main reasons behind Enlive templates returning seqs of strings are:

Ring does not expose the output stream (and I think it is a good thing)
I don&#8217;t want to allocate the whole response as a single string

 Hence it seemed to me the simplest thing to do. (Simpler than implementing InputStream or making templates and Ring [...]]]></description>
			<content:encoded><![CDATA[<p>The main reasons behind Enlive templates returning seqs of strings are:
<ul>
<li><a href="http://github.com/mmcgrana/ring/blob/master/SPEC">Ring</a> does not expose the output stream (and I think it is a good thing)</li>
<li>I don&#8217;t want to allocate the whole response as a single string</li>
</ul>
<p> Hence it seemed to me the simplest thing to do. (Simpler than implementing InputStream or making templates and Ring to communicate through a kind of reduce-based IO.)</p>
<p>Nodes serializations are cached when the source of the template is read:
<pre class="highlight"><span class="nv">user=&gt;</span> <span class="p">(</span><span class="nf">deftemplate</span> <span class="nv">hello</span> <span class="p">(</span><span class="nb">-&gt; </span><span class="s">&quot;&lt;h1&gt;This is a static title&lt;h2&gt;This is a dynamic title&quot;</span> <span class="nv">java</span><span class="o">.</span><span class="nv">io</span><span class="o">.</span><span class="nv">StringReader</span><span class="o">.</span> <span class="nv">html-resource</span><span class="p">)</span> <span class="p">[</span><span class="nv">name</span><span class="p">]</span> <span class="p">[</span><span class="nv">:h2</span><span class="p">]</span> <span class="p">(</span><span class="nf">content</span> <span class="nv">name</span><span class="p">))</span>
<span class="o">#</span><span class="ss">&#39;user/hello</span>
<span class="nv">user=&gt;</span> <span class="p">(</span><span class="nf">hello</span> <span class="s">&quot;Replaced dynamic title&quot;</span><span class="p">)</span>
<span class="p">(</span><span class="s">&quot;&lt;html&gt;&quot;</span> <span class="s">&quot;&lt;body&gt;&quot;</span> <span class="s">&quot;&lt;h1&gt;This is a static title&lt;/h1&gt;&quot;</span> <span class="s">&quot;&lt;h2&gt;&quot;</span> <span class="s">&quot;Replaced dynamic title&quot;</span> <span class="s">&quot;&lt;/h2&gt;&quot;</span> <span class="s">&quot;&lt;/body&gt;&quot;</span> <span class="s">&quot;&lt;/html&gt;&quot;</span><span class="p">)</span>
<span class="nv">user=&gt;</span> <span class="p">(</span><span class="nf">hello</span> <span class="s">&quot;Replaced dynamic title II&quot;</span><span class="p">)</span>
<span class="p">(</span><span class="s">&quot;&lt;html&gt;&quot;</span> <span class="s">&quot;&lt;body&gt;&quot;</span> <span class="s">&quot;&lt;h1&gt;This is a static title&lt;/h1&gt;&quot;</span> <span class="s">&quot;&lt;h2&gt;&quot;</span> <span class="s">&quot;Replaced dynamic title II&quot;</span> <span class="s">&quot;&lt;/h2&gt;&quot;</span> <span class="s">&quot;&lt;/body&gt;&quot;</span> <span class="s">&quot;&lt;/html&gt;&quot;</span><span class="p">)</span>
<span class="nv">user=&gt;</span> <span class="p">(</span><span class="nb">map </span><span class="nv">identical?</span> <span class="nv">*1</span> <span class="nv">*2</span><span class="p">)</span>
<span class="p">(</span><span class="nf">true</span> <span class="nv">true</span> <span class="nv">true</span> <span class="nv">true</span> <span class="nv">false</span> <span class="nv">true</span> <span class="nv">true</span> <span class="nv">true</span><span class="p">)</span></pre>
<p>Thus no string allocation except for the dynamic parts but the real <i>raison d&#8217;être</i> of the static nodes serializations cache is to reduce the time spent traversing the tree and the number of allocated Cons (since the strings are longer).</p>
<p>Even without this cache there&#8217;s no String allocation when serializing a tree (but many Cons instances are allocated):
<pre class="highlight"><span class="nv">user=&gt;</span> <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">x</span> <span class="p">{</span><span class="nv">:tag</span> <span class="nv">:html</span> <span class="nv">:content</span> <span class="p">[{</span><span class="nv">:tag</span> <span class="nv">:body</span> <span class="nv">:content</span> <span class="p">[{</span><span class="nv">:tag</span> <span class="nv">:h1</span> <span class="nv">:content</span> <span class="p">[</span><span class="s">&quot;This is a static title&quot;</span><span class="p">]}</span> <span class="p">{</span><span class="nv">:tag</span> <span class="nv">:h2</span> <span class="nv">:content</span> <span class="p">[</span><span class="s">&quot;This is a dynamic title&quot;</span><span class="p">]}]}]}]</span>
         <span class="p">(</span><span class="nb">every? </span><span class="p">(</span><span class="nb">partial </span><span class="nv">apply</span> <span class="nv">identical?</span><span class="p">)</span> <span class="p">(</span><span class="nb">map </span><span class="nv">vector</span> <span class="p">(</span><span class="nf">emit*</span> <span class="nv">x</span><span class="p">)</span> <span class="p">(</span><span class="nf">emit*</span> <span class="nv">x</span><span class="p">))))</span>
<span class="nv">true</span></pre>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/8ctrzS2Cpnc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2010/02/10/why-enlive-templates-return-seqs-of-strings/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Clojure refactoring: flattening reduces</title>
		<link>http://clj-me.cgrand.net/2010/01/19/clojure-refactoring-flattening-reduces/</link>
		<comments>http://clj-me.cgrand.net/2010/01/19/clojure-refactoring-flattening-reduces/#comments</comments>
		<pubDate>Tue, 19 Jan 2010 10:48:51 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[mistakes]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=270</guid>
		<description><![CDATA[This morning I wrote some code which looked like:
(reduce (fn [acc x]
          (reduce (fn [acc y]
                    (reduce f acc y)) acc x)) init xs)
 (it was slightly [...]]]></description>
			<content:encoded><![CDATA[<p>This morning I wrote some code which looked like:
<pre class="highlight"><span class="p">(</span><span class="nb">reduce </span><span class="p">(</span><span class="k">fn </span><span class="p">[</span><span class="nv">acc</span> <span class="nv">x</span><span class="p">]</span>
          <span class="p">(</span><span class="nb">reduce </span><span class="p">(</span><span class="k">fn </span><span class="p">[</span><span class="nv">acc</span> <span class="nv">y</span><span class="p">]</span>
                    <span class="p">(</span><span class="nb">reduce </span><span class="nv">f</span> <span class="nv">acc</span> <span class="nv">y</span><span class="p">))</span> <span class="nv">acc</span> <span class="nv">x</span><span class="p">))</span> <span class="nv">init</span> <span class="nv">xs</span><span class="p">)</span></pre>
<p> (it was slightly more complex with some filtering and destructuring thrown in for good measure).</p>
<p>I wasn&#8217;t happy with those nested reduces and it occured to me that I could refactor it to use a single one:
<pre class="highlight"><span class="p">(</span><span class="nb">reduce </span><span class="nv">f</span> <span class="nv">init</span> <span class="p">(</span><span class="k">for </span><span class="p">[</span><span class="nv">x</span> <span class="nv">xs,</span> <span class="nv">y</span> <span class="nv">x,</span> <span class="nv">z</span> <span class="nv">y</span><span class="p">]</span> <span class="nv">z</span><span class="p">))</span></pre>
<p> Now that reads better!</p>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/fi1UN6QlmCI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2010/01/19/clojure-refactoring-flattening-reduces/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Graph Structured Stacks in Clojure</title>
		<link>http://clj-me.cgrand.net/2010/01/16/graph-structured-stacks-in-clojure/</link>
		<comments>http://clj-me.cgrand.net/2010/01/16/graph-structured-stacks-in-clojure/#comments</comments>
		<pubDate>Sat, 16 Jan 2010 15:41:41 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[pondering]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=257</guid>
		<description><![CDATA[I am currently pondering how best to represent Graph Structured Stacks in Clojure. My first idea was to use maps.

So this GSS would be represented as:
{7 {3 {1 {0 {}}},
    4 {1 {0 {}}},
    5 {2 {0 {}}}},
 8 {6 {2 {0 {}}}}}
 Please note that repeated maps in [...]]]></description>
			<content:encoded><![CDATA[<p>I am currently pondering how best to represent <a href="http://en.wikipedia.org/wiki/Graph-structured_stack">Graph Structured Stacks</a> in Clojure. My first idea was to use maps.</p>
<p><img class="alignleft" title="An example of a graph-structured stack" src="http://upload.wikimedia.org/wikipedia/en/c/cd/Graphstructuredstack_jaredwf.png" alt="" width="251" height="209" /></p>
<p>So this GSS would be represented as:
<pre class="highlight"><span class="p">{</span><span class="mi">7</span> <span class="p">{</span><span class="mi">3</span> <span class="p">{</span><span class="mi">1</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}</span><span class="o">,</span>
    <span class="mi">4</span> <span class="p">{</span><span class="mi">1</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}</span><span class="o">,</span>
    <span class="mi">5</span> <span class="p">{</span><span class="mi">2</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}}</span><span class="o">,</span>
 <span class="mi">8</span> <span class="p">{</span><span class="mi">6</span> <span class="p">{</span><span class="mi">2</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}}}</span></pre>
<p> Please note that repeated maps in this representation would be shared by construction.</p>
<p>It is all well and good this representation allow me to easily perform stack ops but I want to also be able to traverse the stacks from the bottom. This means to make the graph cyclic so I thought that I need an <a href="http://en.wikipedia.org/wiki/Adjacency_list">adjency list</a> or, more realistically, two indexed versions (maps of sets) of this list to be able to traverse the GSS in any direction. Or the map-based representation for direct traversal and an adjency map for reverse traversal.</p>
<p>To me the more boring part with this adjency lists is that I  have to name the GSS nodes. Wait! There are natural identifiers for these nodes: their key-value pairs in the map-based representation! <code class="highlight"><span class="p">[</span><span class="mi">2</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}]</span></code> is a natural identifier for node #2 and <code class="highlight"><span class="p">[</span><span class="mi">2</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}]</span></code> the one for node #7.</p>
<p>Now I&#8217;m able to represent the GSS as:
<pre class="highlight"><span class="p">[</span><span class="c1">;; direct representation</span>
 <span class="p">{</span><span class="mi">7</span> <span class="p">{</span><span class="mi">3</span> <span class="p">{</span><span class="mi">1</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}</span><span class="o">,</span>
     <span class="mi">4</span> <span class="p">{</span><span class="mi">1</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}</span><span class="o">,</span>
     <span class="mi">5</span> <span class="p">{</span><span class="mi">2</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}}</span><span class="o">,</span>
  <span class="mi">8</span> <span class="p">{</span><span class="mi">6</span> <span class="p">{</span><span class="mi">2</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}}}</span>
 <span class="c1">;; adjency map for reverse traversal</span>
 <span class="p">{</span><span class="nv">nil</span> <span class="o">#</span><span class="p">{[</span><span class="mi">0</span> <span class="p">{}]}</span><span class="o">,</span>
  <span class="p">[</span><span class="mi">0</span> <span class="p">{}]</span> <span class="o">#</span><span class="p">{[</span><span class="mi">1</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}]</span>
           <span class="p">[</span><span class="mi">2</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}]}</span><span class="o">,</span>
  <span class="p">[</span><span class="mi">1</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}]</span> <span class="o">#</span><span class="p">{[</span><span class="mi">3</span> <span class="p">{</span><span class="mi">1</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}]</span>
               <span class="p">[</span><span class="mi">4</span> <span class="p">{</span><span class="mi">1</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}]}</span><span class="o">,</span>
  <span class="p">[</span><span class="mi">2</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}]</span> <span class="o">#</span><span class="p">{[</span><span class="mi">5</span> <span class="p">{</span><span class="mi">2</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}]</span>
               <span class="p">[</span><span class="mi">6</span> <span class="p">{</span><span class="mi">2</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}]}</span><span class="o">,</span>
  <span class="p">[</span><span class="mi">3</span> <span class="p">{</span><span class="mi">1</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}]</span> <span class="o">#</span><span class="p">{[</span><span class="mi">7</span> <span class="p">{</span><span class="mi">3</span> <span class="p">{</span><span class="mi">1</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}</span><span class="o">,</span>
                       <span class="mi">4</span> <span class="p">{</span><span class="mi">1</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}</span><span class="o">,</span>
                       <span class="mi">5</span> <span class="p">{</span><span class="mi">2</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}}]}</span><span class="o">,</span>
  <span class="p">[</span><span class="mi">4</span> <span class="p">{</span><span class="mi">1</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}]</span> <span class="o">#</span><span class="p">{[</span><span class="mi">7</span> <span class="p">{</span><span class="mi">3</span> <span class="p">{</span><span class="mi">1</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}</span><span class="o">,</span>
                       <span class="mi">4</span> <span class="p">{</span><span class="mi">1</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}</span><span class="o">,</span>
                       <span class="mi">5</span> <span class="p">{</span><span class="mi">2</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}}]}</span><span class="o">,</span>
  <span class="p">[</span><span class="mi">5</span> <span class="p">{</span><span class="mi">2</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}]</span> <span class="o">#</span><span class="p">{[</span><span class="mi">7</span> <span class="p">{</span><span class="mi">3</span> <span class="p">{</span><span class="mi">1</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}</span><span class="o">,</span>
                       <span class="mi">4</span> <span class="p">{</span><span class="mi">1</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}</span><span class="o">,</span>
                       <span class="mi">5</span> <span class="p">{</span><span class="mi">2</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}}]}</span><span class="o">,</span>
  <span class="p">[</span><span class="mi">6</span> <span class="p">{</span><span class="mi">2</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}]</span> <span class="o">#</span><span class="p">{[</span><span class="mi">8</span> <span class="p">{</span><span class="mi">6</span> <span class="p">{</span><span class="mi">2</span> <span class="p">{</span><span class="mi">0</span> <span class="p">{}}}}]}}]</span></pre>
<p> Granted the serialization is verbose but all nodes are shared in memory by construction and I find this model rather simple.</p>
<p>Does anyone have other ideas on how to functionally implement such a structure?</p>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/Ti1-Xs9hGv4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2010/01/16/graph-structured-stacks-in-clojure/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Are pipe dreams made of promises?</title>
		<link>http://clj-me.cgrand.net/2009/11/18/are-pipe-dreams-made-of-promises/</link>
		<comments>http://clj-me.cgrand.net/2009/11/18/are-pipe-dreams-made-of-promises/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 17:32:23 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[unsorted]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=242</guid>
		<description><![CDATA[follow-up: pipe dreams aren&#8217;t necessarily made of promises
(defn pipe
 &#34;Returns a pair: a seq (the read end) and a function (the write end).
  The function can takes either no arguments to close the pipe 
  or one argument which is appended to the seq. Read is blocking.&#34;
 []
  (let [promises (atom (repeatedly [...]]]></description>
			<content:encoded><![CDATA[<p><b>follow-up:</b> <a href="http://clj-me.cgrand.net/2010/04/02/pipe-dreams-are-not-necessarily-made-of-promises/">pipe dreams aren&#8217;t necessarily made of promises</a></p>
<pre class="highlight"><span class="p">(</span><span class="k">defn </span><span class="nv">pipe</span>
 <span class="s">&quot;Returns a pair: a seq (the read end) and a function (the write end).</span>
<span class="s">  The function can takes either no arguments to close the pipe </span>
<span class="s">  or one argument which is appended to the seq. Read is blocking.&quot;</span>
 <span class="p">[]</span>
  <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">promises</span> <span class="p">(</span><span class="nf">atom</span> <span class="p">(</span><span class="nf">repeatedly</span> <span class="nv">promise</span><span class="p">))</span>
        <span class="nv">p</span> <span class="p">(</span><span class="nb">second </span><span class="nv">@promises</span><span class="p">)]</span>
    <span class="p">[(</span><span class="nf">lazy-seq</span> <span class="nv">@p</span><span class="p">)</span>
     <span class="p">(</span><span class="k">fn </span>
       <span class="p">([]</span> <span class="c1">;close the pipe</span>
         <span class="p">(</span><span class="k">let </span><span class="p">[[</span><span class="nv">a</span><span class="p">]</span> <span class="p">(</span><span class="nf">swap!</span> <span class="nv">promises</span> <span class="o">#</span><span class="p">(</span><span class="nv">vector</span> <span class="p">(</span><span class="nb">second </span><span class="nv">%</span><span class="p">)))]</span>
           <span class="p">(</span><span class="k">if </span><span class="nv">a</span>
             <span class="p">(</span><span class="nf">deliver</span> <span class="nv">a</span> <span class="nv">nil</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">throw</span> <span class="p">(</span><span class="nf">Exception</span><span class="o">.</span> <span class="s">&quot;Pipe already closed&quot;</span><span class="p">)))))</span>
       <span class="p">([</span><span class="nv">x</span><span class="p">]</span> <span class="c1">;enqueue x</span>
         <span class="p">(</span><span class="k">let </span><span class="p">[[</span><span class="nv">a</span> <span class="nv">b</span><span class="p">]</span> <span class="p">(</span><span class="nf">swap!</span> <span class="nv">promises</span> <span class="nv">next</span><span class="p">)]</span>
           <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">and </span><span class="nv">a</span> <span class="nv">b</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">do</span>
               <span class="p">(</span><span class="nf">deliver</span> <span class="nv">a</span> <span class="p">(</span><span class="nb">cons </span><span class="nv">x</span> <span class="p">(</span><span class="nf">lazy-seq</span> <span class="nv">@b</span><span class="p">)))</span>
               <span class="nv">x</span><span class="p">)</span>
             <span class="p">(</span><span class="nf">throw</span> <span class="p">(</span><span class="nf">Exception</span><span class="o">.</span> <span class="s">&quot;Pipe already closed&quot;</span><span class="p">))))))]))</span></pre>
<p>Beware of not printing the seq while the pipe is still open!</p>
<pre class="highlight"><span class="p">(</span><span class="k">let </span><span class="p">[[</span><span class="nv">q</span> <span class="nv">f</span><span class="p">]</span> <span class="p">(</span><span class="nf">pipe</span><span class="p">)]</span>
  <span class="p">(</span><span class="nf">future</span> <span class="p">(</span><span class="nb">doseq </span><span class="p">[</span><span class="nv">x</span> <span class="nv">q</span><span class="p">]</span> <span class="p">(</span><span class="nb">println </span><span class="nv">x</span><span class="p">))</span> <span class="p">(</span><span class="nb">println </span><span class="s">&quot;that&#39;s all folks!&quot;</span><span class="p">))</span>
  <span class="p">(</span><span class="nb">doseq </span><span class="p">[</span><span class="nv">x</span> <span class="p">(</span><span class="nb">range </span><span class="mi">10</span><span class="p">)]</span>
    <span class="p">(</span><span class="nf">f</span> <span class="nv">x</span><span class="p">))</span>
  <span class="p">(</span><span class="nf">f</span><span class="p">))</span> <span class="c1">;close the pipe</span></pre>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/COK5FHhUwqc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2009/11/18/are-pipe-dreams-made-of-promises/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>An optimization job is never done</title>
		<link>http://clj-me.cgrand.net/2009/11/18/an-optimization-job-is-never-done/</link>
		<comments>http://clj-me.cgrand.net/2009/11/18/an-optimization-job-is-never-done/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 10:26:01 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[optimization]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=230</guid>
		<description><![CDATA[&#8230; when you don&#8217;t set measurable goals.
Yesterday, in Life of Brian I showed several tricks to make an implementation of Brian&#8217;s Brain faster. I tought it was enough but since some disagree here comes another perf boost.
Repetitive lookups
In neighbours-count the first arg (which happens to be a seq of 3 items) is destructured:
(defn neighbours-count [[above [...]]]></description>
			<content:encoded><![CDATA[<p>&hellip; when you don&#8217;t set measurable goals.</p>
<p>Yesterday, in <a href="http://clj-me.cgrand.net/2009/11/17/life-of-brian/">Life of Brian</a> I showed several tricks to make an implementation of <a href="http://en.wikipedia.org/wiki/Brian's_Brain">Brian&#8217;s Brain</a> faster. I tought it was enough but since some disagree here comes another perf boost.</p>
<h2>Repetitive lookups</h2>
<p>In <code class="highlight"><span class="nv">neighbours-count</span></code> the first arg (which happens to be a seq of 3 items) is destructured:</p>
<pre class="highlight"><span class="p">(</span><span class="k">defn </span><span class="nv">neighbours-count</span> <span class="p">[[</span><span class="nv">above</span> <span class="nv">current</span> <span class="nv">below</span><span class="p">]</span> <span class="nv">i</span> <span class="nv">w</span><span class="p">]</span></pre>
<p>which means that there&#8217;s 3 lookups per <code class="highlight"><span class="nv">:off</span></code> cell while these lookups results are constant for a given row!</p>
<p>So let&#8217;s move these lookups in step1:</p>
<pre class="highlight"><span class="p">(</span><span class="k">defn </span><span class="nv">neighbours-count</span> <span class="p">[</span><span class="nv">above</span> <span class="nv">current</span> <span class="nv">below</span> <span class="nv">i</span> <span class="nv">w</span><span class="p">]</span>
  <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">j</span> <span class="p">(</span><span class="nf">mod</span> <span class="p">(</span><span class="nb">inc </span><span class="nv">i</span><span class="p">)</span> <span class="nv">w</span><span class="p">)</span>
        <span class="nv">k</span> <span class="p">(</span><span class="nf">mod</span> <span class="p">(</span><span class="nb">dec </span><span class="nv">i</span><span class="p">)</span> <span class="nv">w</span><span class="p">)</span>
        <span class="nv">s</span> <span class="o">#</span><span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">= </span><span class="p">(</span><span class="nb">aget </span><span class="o">#</span><span class="nv">^objects</span> <span class="nv">%1</span> <span class="p">(</span><span class="nb">int </span><span class="nv">%2</span><span class="p">))</span> <span class="nv">:on</span><span class="p">)</span> <span class="mi">1</span> <span class="mi">0</span><span class="p">)]</span>
    <span class="p">(</span><span class="nb">+ </span><span class="p">(</span><span class="nb">+ </span><span class="p">(</span><span class="nb">+ </span><span class="p">(</span><span class="nf">s</span> <span class="nv">above</span> <span class="nv">j</span><span class="p">)</span> <span class="p">(</span><span class="nf">s</span> <span class="nv">above</span> <span class="nv">i</span><span class="p">))</span>
         <span class="p">(</span><span class="nb">+ </span><span class="p">(</span><span class="nf">s</span> <span class="nv">above</span> <span class="nv">k</span><span class="p">)</span> <span class="p">(</span><span class="nf">s</span> <span class="nv">current</span> <span class="nv">j</span><span class="p">)))</span>
      <span class="p">(</span><span class="nb">+ </span><span class="p">(</span><span class="nb">+ </span><span class="p">(</span><span class="nf">s</span> <span class="nv">current</span> <span class="nv">k</span><span class="p">)</span> <span class="p">(</span><span class="nf">s</span> <span class="nv">below</span> <span class="nv">j</span><span class="p">))</span>
        <span class="p">(</span><span class="nb">+ </span><span class="p">(</span><span class="nf">s</span> <span class="nv">below</span> <span class="nv">i</span><span class="p">)</span> <span class="p">(</span><span class="nf">s</span> <span class="nv">below</span> <span class="nv">k</span><span class="p">))))))</span>

<span class="p">(</span><span class="k">defn </span><span class="nv">step1</span> <span class="p">[[</span><span class="nv">above</span> <span class="o">#</span><span class="nv">^objects</span> <span class="nv">current</span> <span class="nv">below</span><span class="p">]]</span>
  <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">w</span> <span class="p">(</span><span class="nb">count </span><span class="nv">current</span><span class="p">)]</span>
    <span class="p">(</span><span class="nb">loop </span><span class="p">[</span><span class="nv">i</span> <span class="p">(</span><span class="nb">int </span><span class="p">(</span><span class="nb">dec </span><span class="nv">w</span><span class="p">))</span><span class="o">,</span> <span class="o">#</span><span class="nv">^objects</span> <span class="nv">row</span> <span class="p">(</span><span class="nf">aclone</span> <span class="nv">current</span><span class="p">)]</span>
      <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">neg? </span><span class="nv">i</span><span class="p">)</span>
        <span class="nv">row</span>
        <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">c</span> <span class="p">(</span><span class="nb">aget </span><span class="nv">current</span> <span class="nv">i</span><span class="p">)]</span>
          <span class="p">(</span><span class="nf">cond</span>
            <span class="p">(</span><span class="nb">= </span><span class="nv">c</span> <span class="nv">:on</span><span class="p">)</span>
              <span class="p">(</span><span class="nf">recur</span> <span class="p">(</span><span class="nb">dec </span><span class="nv">i</span><span class="p">)</span> <span class="p">(</span><span class="nb">doto </span><span class="nv">row</span> <span class="p">(</span><span class="nb">aset </span><span class="nv">i</span> <span class="nv">:dying</span><span class="p">)))</span>
            <span class="p">(</span><span class="nb">= </span><span class="nv">c</span> <span class="nv">:dying</span><span class="p">)</span>
              <span class="p">(</span><span class="nf">recur</span> <span class="p">(</span><span class="nb">dec </span><span class="nv">i</span><span class="p">)</span> <span class="p">(</span><span class="nb">doto </span><span class="nv">row</span> <span class="p">(</span><span class="nb">aset </span><span class="nv">i</span> <span class="nv">:off</span><span class="p">)))</span>
            <span class="p">(</span><span class="nb">= </span><span class="mi">2</span> <span class="p">(</span><span class="nf">neighbours-count</span> <span class="nv">above</span> <span class="nv">current</span> <span class="nv">below</span> <span class="nv">i</span> <span class="nv">w</span><span class="p">))</span>
              <span class="p">(</span><span class="nf">recur</span> <span class="p">(</span><span class="nb">dec </span><span class="nv">i</span><span class="p">)</span> <span class="p">(</span><span class="nb">doto </span><span class="nv">row</span> <span class="p">(</span><span class="nb">aset </span><span class="nv">i</span> <span class="nv">:on</span><span class="p">)))</span>
            <span class="nv">:else</span>
              <span class="p">(</span><span class="nf">recur</span> <span class="p">(</span><span class="nb">dec </span><span class="nv">i</span><span class="p">)</span> <span class="nv">row</span><span class="p">)))))))</span></pre>
<p>Benchmark:</p>
<pre class="highlight"><span class="nv">user=&gt;</span> <span class="p">(</span><span class="nf">do</span>  <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">b</span> <span class="p">(</span><span class="nf">rand-board</span> <span class="mi">80</span> <span class="mi">80</span><span class="p">)]</span> <span class="p">(</span><span class="nb">time </span><span class="p">((</span><span class="nb">apply </span><span class="nv">comp</span> <span class="p">(</span><span class="nb">repeat </span><span class="mi">1000</span> <span class="nv">step</span><span class="p">))</span> <span class="nv">b</span><span class="p">)))</span> <span class="nv">nil</span><span class="p">)</span>
<span class="s">&quot;Elapsed time: 2058.372014 msecs&quot;</span>
<span class="nv">nil</span>
<span class="nv">user=&gt;</span> <span class="p">(</span><span class="nf">do</span>  <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">b</span> <span class="p">(</span><span class="nf">rand-board</span> <span class="mi">200</span> <span class="mi">200</span><span class="p">)]</span> <span class="p">(</span><span class="nb">time </span><span class="p">((</span><span class="nb">apply </span><span class="nv">comp</span> <span class="p">(</span><span class="nb">repeat </span><span class="mi">100</span> <span class="nv">step</span><span class="p">))</span> <span class="nv">b</span><span class="p">)))</span> <span class="nv">nil</span><span class="p">)</span>
<span class="s">&quot;Elapsed time: 1105.499303 msecs&quot;</span>
<span class="nv">nil</span></pre>
<p>Wow, twice as fast! Again. 2.1ms/step on a 80*80 board, <strong>11.1ms/step on a 200*200 board</strong>.</p>
<p><a href="http://gist.github.com/237700">This version</a> on a 200*200 board is then nearly 10x faster than my first one!</p>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/jxvx26Wv8Vk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2009/11/18/an-optimization-job-is-never-done/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>
