<?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>Mon, 09 Apr 2012 14:08:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<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>Fair conjunction: status report</title>
		<link>http://clj-me.cgrand.net/2012/04/06/fair-conjunction-status-report/</link>
		<comments>http://clj-me.cgrand.net/2012/04/06/fair-conjunction-status-report/#comments</comments>
		<pubDate>Fri, 06 Apr 2012 13:54:14 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[unsorted]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=526</guid>
		<description><![CDATA[Shameless plugs: Clojure Programming is out! Available now as an ebook and in a few days in paper! Come to my Clojure training in Geneva it will be in a mixed language (French/English) setting — for an English-only training stay tuned! Making conjunction fair is the reason why I messed up with core.logic, and this [...]]]></description>
			<content:encoded><![CDATA[<div style="background: #ffb; padding: 5px;">Shameless plugs:<br />
<b><a href="http://www.clojurebook.com/">Clojure Programming</a> is out!</b> Available now as an ebook and in a few days in paper!<br />
Come to my <b><a href="http://clojure.inagua.ch/formation/formation_clojure.html">Clojure training in Geneva</a></b> it will be in a mixed language (French/English) setting — for an English-only training stay tuned!</ul>
</div>
<p>Making conjunction fair is the reason why I messed up with core.logic, and this post document the approach I explore in the <a href="https://github.com/clojure/core.logic/tree/fair-conj2">fair-conj2 branch</a>.</p>
<p>In <a href="http://clj-me.cgrand.net/2012/01/30/the-reasoned-scheduler/">The Reasoned Scheduler</a> I said that conjunction is easy: you wait for the first stream to provide a answer that you pass to the next goal. It looks easy but it suffers from being ordered: when the first goal diverges (produces an infinite stream of results or never halts) and the next goal is known to fail, the conjuction diverges too! This is unfair conjunction.</p>
<p>Changing the order of the goals would fix this particular example but like noted by <a href="http://blip.tv/clojure/dan-friedman-and-william-byrd-minikanren-5936333">William Byrd</a> in <a href="https://scholarworks.iu.edu/dspace/bitstream/handle/2022/8777/Byrd_indiana_0093A_10344.pdf?sequence=1">Relational Programming in miniKanren: Techniques, Applications, and Implementations</a> (page 53 and 54):</p>
<p><quote>However, reordering goals has its disadvantages. For many programs, no ordering of goals will result in finite failure (see the remaining example in this chapter). Also, by committing to a certain goal ordering we are giving up on the declarative nature of relational programming: we are specifying how the program computes, rather than only what it computes. For these reasons, we should consider alternative solutions.</quote></p>
<p><quote>[T]he goal ordering we picked might diverge when we ask for a second answer, while the other ordering may fail finitely after producing a single answer.</quote>  </p>
<p>So, to make conjunction fair (commutative), one has to not commit to an ordering of goal, which means that both goals must be executed in parallel (interleaved execution or even <a href="http://www.clojure.net/2012/03/26/Messin-with-core.logic/">true parallelism</a>). As soon as one of the goal produces an answer, this substitution has to be communicated to the other <del>thread</del>goal so as to <em>narrow</em> its search space.</p>
<p>As a consequence of the disappearance of ordering, the distinction between a goal and a stream disappears too. I introduced a <code>Search</code> abstraction. A <code>Search</code> may <code>yield</code> a substitution (or nil)<br />
and progress with <code>step</code>. It sounds awfully familiar with <code>first</code> and <code>next</code>.</p>
<p>Let&#8217;s name <code>plus</code>, <code>join</code> and  <code>narrow</code> respectively the disjunction, conjunction and narrowing operators. Conjunction is distributive over disjunction as usual and narrowing is distributive over both. </p>
<p>Here is how the key expression is derived:</p>
<pre class="highlight"><span class="p">(</span><span class="nb">join </span><span class="nv">a</span> <span class="nv">b</span><span class="p">)</span>
<span class="p">(</span><span class="nb">join </span><span class="p">(</span><span class="nf">plus</span> <span class="p">(</span><span class="nf">yield</span> <span class="nv">a</span><span class="p">)</span> <span class="p">(</span><span class="nf">step</span> <span class="nv">a</span><span class="p">))</span> <span class="nv">b</span><span class="p">)</span> <span class="c1">; decompose a </span>
<span class="p">(</span><span class="nf">plus</span> <span class="p">(</span><span class="nb">join </span><span class="p">(</span><span class="nf">yield</span> <span class="nv">a</span><span class="p">)</span> <span class="nv">b</span><span class="p">)</span> <span class="p">(</span><span class="nb">join </span><span class="p">(</span><span class="nf">step</span> <span class="nv">a</span><span class="p">)</span> <span class="nv">b</span><span class="p">))</span> <span class="c1">; distribute join</span>
<span class="p">(</span><span class="nf">plus</span> <span class="p">(</span><span class="nf">narrow</span> <span class="nv">b</span> <span class="p">(</span><span class="nf">yield</span> <span class="nv">a</span><span class="p">))</span> <span class="p">(</span><span class="nb">join </span><span class="p">(</span><span class="nf">step</span> <span class="nv">a</span><span class="p">)</span> <span class="nv">b</span><span class="p">))</span> <span class="c1">; joining with a substitution (or nil) is narrowing</span>
<span class="p">(</span><span class="nf">plus</span> <span class="p">(</span><span class="nf">narrow</span> <span class="nv">b</span> <span class="p">(</span><span class="nf">yield</span> <span class="nv">a</span><span class="p">))</span> <span class="p">(</span><span class="nb">join </span><span class="nv">b</span> <span class="p">(</span><span class="nf">step</span> <span class="nv">a</span><span class="p">)))</span> <span class="c1">; commute the operands of join for interleaving</span></pre>
<p>This expression can be found <a href="https://github.com/clojure/core.logic/blob/30172be9ee422747d572d17724870cb526dbb192/src/main/clojure/clojure/core/logic.clj#L826">nearly as-is in the code</a>.</p>
<p>Narrowing is performed lazily: when one steps a suspended narrowing (a <code>Narrow</code> instance), the narrowing is propagated (thanks to its distributivity) to the children searches of its argument.</p>
<p>To make narrowing efficient, I introduced the <code>min-yield</code> function which, given a Search, returns the minimal substitution yielded by this search. That is: if this Search ever yield results they will be extensions of the min-yield substitution. This allows to discard a Search in its entirety when the narrowing substitution and the min-yield substitutions are not compatible!</p>
<p>To compute min-yield substitutions, the narrowing process leaves nodes (<code>Scope</code> instances) in the computation tree labeled with the narrowing substitution. By default <code>min-yield</code> returns <code>empty-s</code> the empty substitution.</p>
<p>This is the gist of my approach to fair conjunction. In a subsequent post, I&#8217;ll cover heuristics I use to prioritize execution of Searches.</p>
<p>Practically, what does it mean? It means that logic programs are easier to write, it also means that, at the moment, a program written with unfair conjunction in mind run slower with fair conjunction. Interestingly, under fair conjunction, naive <code>pluso</code> (p. 63) seems refutationally complete.</p>
<p>I intend to explore how constraints can be added to this branch and how it will impact (positively) performance.</p>
<p>If you feel like dabbling with this branch, I&#8217;ll be more than happy to hear your feedback. Thanks! </p>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/ZndjJvduYi4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2012/04/06/fair-conjunction-status-report/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A poor man’s interval tree</title>
		<link>http://clj-me.cgrand.net/2012/03/16/a-poor-mans-interval-tree/</link>
		<comments>http://clj-me.cgrand.net/2012/03/16/a-poor-mans-interval-tree/#comments</comments>
		<pubDate>Fri, 16 Mar 2012 20:49:44 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[unsorted]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=517</guid>
		<description><![CDATA[Sorted collections can be put to good (ab)use, here I define interval-lt a partial order on intervals and points &#8212; where an interval is a vector [from to] (from inclusive, to exclusive; they can be nil to denote infinity) and a point is [n n]. (defn interval-lt [[a b] [c d]] (boolean (and b c [...]]]></description>
			<content:encoded><![CDATA[<p>Sorted collections can be put to good (ab)use, here I define <code class="highlight"><span class="nv">interval-lt</span></code> a partial order on intervals and points &mdash; where an interval is a vector <code class="highlight"><span class="p">[</span><span class="nv">from</span> <span class="nv">to</span><span class="p">]</span></code> (<code class="highlight"><span class="nv">from</span></code> inclusive, <code class="highlight"><span class="nv">to</span></code> exclusive; they can be <code class="highlight"><span class="nv">nil</span></code> to denote infinity) and a point is <code class="highlight"><span class="p">[</span><span class="nv">n</span> <span class="nv">n</span><span class="p">]</span></code>.</p>
<pre class="highlight"><span class="p">(</span><span class="k">defn </span><span class="nv">interval-lt</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="nv">c</span> <span class="nv">d</span><span class="p">]]</span>
  <span class="p">(</span><span class="nb">boolean </span><span class="p">(</span><span class="nb">and </span><span class="nv">b</span> <span class="nv">c</span>
                <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">= </span><span class="nv">a</span> <span class="nv">b</span><span class="p">)</span>
                  <span class="p">(</span><span class="nb">neg? </span><span class="p">(</span><span class="nf">compare</span> <span class="nv">b</span> <span class="nv">c</span><span class="p">))</span>
                  <span class="p">(</span><span class="nb">&lt;= </span><span class="p">(</span><span class="nf">compare</span> <span class="nv">b</span> <span class="nv">c</span><span class="p">)</span> <span class="mi">0</span><span class="p">)))))</span></pre>
<p>Using this partial order and a sorted-map, I can build an interval tree:</p>
<pre class="highlight"><span class="p">(</span><span class="k">def </span><span class="nv">empty-interval-map</span>
  <span class="p">(</span><span class="nb">sorted-map-by </span><span class="nv">interval-lt</span> <span class="p">[</span><span class="nv">nil</span> <span class="nv">nil</span><span class="p">]</span> <span class="o">#</span><span class="p">{}))</span>

<span class="p">(</span><span class="k">defn- </span><span class="nv">isplit-at</span> <span class="p">[</span><span class="nv">interval-map</span> <span class="nv">x</span><span class="p">]</span>
  <span class="p">(</span><span class="k">if </span><span class="nv">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="nv">:as</span> <span class="nv">k</span><span class="p">]</span> <span class="nv">vs</span><span class="p">]</span> <span class="p">(</span><span class="nb">find </span><span class="nv">interval-map</span> <span class="p">[</span><span class="nv">x</span> <span class="nv">x</span><span class="p">])]</span>
      <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">or </span><span class="p">(</span><span class="nb">= </span><span class="nv">a</span> <span class="nv">x</span><span class="p">)</span> <span class="p">(</span><span class="nb">= </span><span class="nv">b</span> <span class="nv">x</span><span class="p">))</span>
        <span class="nv">interval-map</span>
        <span class="p">(</span><span class="nb">-&gt; </span><span class="nv">interval-map</span> <span class="p">(</span><span class="nb">dissoc </span><span class="nv">k</span><span class="p">)</span> <span class="p">(</span><span class="nb">assoc </span><span class="p">[</span><span class="nv">a</span> <span class="nv">x</span><span class="p">]</span> <span class="nv">vs</span> <span class="p">[</span><span class="nv">x</span> <span class="nv">b</span><span class="p">]</span> <span class="nv">vs</span><span class="p">))))</span>
    <span class="nv">interval-map</span><span class="p">))</span>

<span class="p">(</span><span class="k">defn- </span><span class="nv">ialter</span> <span class="p">[</span><span class="nv">interval-map</span> <span class="nv">from</span> <span class="nv">to</span> <span class="nv">f</span> <span class="nv">&amp;</span> <span class="nv">args</span><span class="p">]</span>
  <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">interval-map</span> <span class="p">(</span><span class="nb">-&gt; </span><span class="nv">interval-map</span> <span class="p">(</span><span class="nf">isplit-at</span> <span class="nv">from</span><span class="p">)</span> <span class="p">(</span><span class="nf">isplit-at</span> <span class="nv">to</span><span class="p">))</span>
        <span class="nv">kvs</span> <span class="p">(</span><span class="k">for </span><span class="p">[[</span><span class="nv">r</span> <span class="nv">vs</span><span class="p">]</span>
                  <span class="p">(</span><span class="k">cond </span>
                    <span class="p">(</span><span class="nb">and </span><span class="nv">from</span> <span class="nv">to</span><span class="p">)</span>
                    <span class="p">(</span><span class="nf">subseq</span> <span class="nv">interval-map</span> <span class="nv">&gt;=</span> <span class="p">[</span><span class="nv">from</span> <span class="nv">from</span><span class="p">]</span> <span class="nv">&lt;</span> <span class="p">[</span><span class="nv">to</span> <span class="nv">to</span><span class="p">])</span>
                    <span class="nv">from</span>
                    <span class="p">(</span><span class="nf">subseq</span> <span class="nv">interval-map</span> <span class="nv">&gt;=</span> <span class="p">[</span><span class="nv">from</span> <span class="nv">from</span><span class="p">])</span>
                    <span class="nv">to</span>
                    <span class="p">(</span><span class="nf">subseq</span> <span class="nv">interval-map</span> <span class="nv">&lt;</span> <span class="p">[</span><span class="nv">to</span> <span class="nv">to</span><span class="p">])</span>
                    <span class="nv">:else</span>
                    <span class="nv">interval-map</span><span class="p">)]</span>
              <span class="p">[</span><span class="nv">r</span> <span class="p">(</span><span class="nb">apply </span><span class="nv">f</span> <span class="nv">vs</span> <span class="nv">args</span><span class="p">)])]</span>
    <span class="p">(</span><span class="nb">into </span><span class="nv">interval-map</span> <span class="nv">kvs</span><span class="p">)))</span>

<span class="p">(</span><span class="k">defn </span><span class="nv">iassoc</span> <span class="p">[</span><span class="nv">interval-map</span> <span class="nv">from</span> <span class="nv">to</span> <span class="nv">v</span><span class="p">]</span>
  <span class="p">(</span><span class="nf">ialter</span> <span class="nv">interval-map</span> <span class="nv">from</span> <span class="nv">to</span> <span class="nv">conj</span> <span class="nv">v</span><span class="p">))</span>

<span class="p">(</span><span class="k">defn </span><span class="nv">idissoc</span> <span class="p">[</span><span class="nv">interval-map</span> <span class="nv">from</span> <span class="nv">to</span> <span class="nv">v</span><span class="p">]</span>
  <span class="p">(</span><span class="nf">ialter</span> <span class="nv">interval-map</span> <span class="nv">from</span> <span class="nv">to</span> <span class="nv">disj</span> <span class="nv">v</span><span class="p">))</span>

<span class="p">(</span><span class="k">defn </span><span class="nv">iget</span> <span class="p">[</span><span class="nv">interval-map</span> <span class="nv">x</span><span class="p">]</span>
  <span class="p">(</span><span class="nb">get </span><span class="nv">interval-map</span> <span class="p">[</span><span class="nv">x</span> <span class="nv">x</span><span class="p">]))</span></pre>
<p>Demo, let&#8217;s state who&#8217;s present and at which time:</p>
<pre class="highlight"><span class="p">(</span><span class="nb">-&gt; </span><span class="nv">empty-interval-map</span>
  <span class="p">(</span><span class="nf">iassoc</span> <span class="mi">9</span> <span class="mi">17</span> <span class="s">&quot;Ethel&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">iassoc</span> <span class="mi">7</span> <span class="mi">12</span> <span class="s">&quot;Lucy&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nf">iassoc</span> <span class="mi">11</span> <span class="mi">20</span> <span class="s">&quot;Fred&quot;</span><span class="p">))</span>
<span class="c1">; {[nil 7] #{}, [7 9] #{&quot;Lucy&quot;}, </span>
<span class="c1">;  [9 11] #{&quot;Ethel&quot; &quot;Lucy&quot;}, </span>
<span class="c1">;  [11 12] #{&quot;Ethel&quot; &quot;Fred&quot; &quot;Lucy&quot;}, </span>
<span class="c1">;  [12 17] #{&quot;Ethel&quot; &quot;Fred&quot;}, </span>
<span class="c1">;  [17 20] #{&quot;Fred&quot;}, </span>
<span class="c1">;  [29 nil] #{}}</span></pre>
<p>And now one can query by time:</p>
<pre class="highlight"><span class="p">(</span><span class="nf">iget</span> <span class="nv">*1</span> <span class="mi">8</span><span class="p">)</span>
<span class="c1">; #{&quot;Lucy&quot;}</span>
<span class="p">(</span><span class="nf">iget</span> <span class="nv">*2</span> <span class="mi">15</span><span class="p">)</span>
<span class="c1">; #{&quot;Ethel&quot; &quot;Fred&quot;}</span>
<span class="p">(</span><span class="nf">iget</span> <span class="nv">*3</span> <span class="mi">20</span><span class="p">)</span>
<span class="c1">; #{}</span></pre>
<p>Sure, this is not the best interval tree implementation ever, it suffers from severe fragmentation and not ideal update complexity. However if what only matters is lookup, it works nicely in O(log n) &#8212; each <code>iassoc</code> adds at most two entries to the map so for n intervals you have at most 1+2n entries, lookup is O(log (2n+1)), that is O(log n). </p>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/60jH1_AcnuQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2012/03/16/a-poor-mans-interval-tree/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The Reasoned Scheduler</title>
		<link>http://clj-me.cgrand.net/2012/01/30/the-reasoned-scheduler/</link>
		<comments>http://clj-me.cgrand.net/2012/01/30/the-reasoned-scheduler/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 17:28:02 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[unsorted]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=497</guid>
		<description><![CDATA[tl;dr How I realized that core.logic (or miniKanren) is essentially a scheduler. Some times ago I wanted to experiment with core.logic&#8217;s codebase and the best way to get intimate with a codebase is to mess with it. Doing so I repeatedly failed but I had several epiphanies on the essence of core.logic (or miniKanren) implementation. [...]]]></description>
			<content:encoded><![CDATA[<p><em>tl;dr How I realized that core.logic (or miniKanren) is essentially a scheduler.</em></p>
<p>Some times ago I wanted to experiment with core.logic&#8217;s codebase and the best way to get intimate with a codebase is to mess with it. Doing so I repeatedly failed but I had several epiphanies on the essence of core.logic (or miniKanren) implementation. Epiphanies that I&#8217;m going to share here.</p>
<p>At first glance, when I looked at this codebase (codebase which started as a faithful port from Scheme), I noticed a lazy stream implementation, a substitutions type and a monadic structure. A lazy stream impl? in Clojure? Let me change this to use a good old lazy sequence!</p>
<p>Before diving in, let me explain what core.logic does: given a problem specification (a program) and some unknowns it tries to solve the <del>equation</del> program. One executes a program with <code>run</code> or  <code>run*</code> which returns a lazy sequence of values for the specified unknown. So the magic happens inside <code>run</code>.</p>
<p><code>run</code> calls the program &mdash; because the program is just a function  &mdash; which returns a lazy stream of <em>substitutions</em> maps. A subsitutions map is a map from unknowns to their values, values which may involve other unknowns. A program is made of <em>goals</em> &mdash; functions of one substitutions map to a lazy stream of substitutions maps. A program is kickstarted with an empty subsitutions map.</p>
<p>The crux of miniKanren or core.logic is then how to combine goals and lazy streams. The two basic combinations are the disjunction (<code>conde</code>) and the conjunction (<code>fresh</code>, <code>all</code> and the implicit conjunction inside each <code>conde</code> clause).</p>
<p>Conjunction is easy: it takes a lazy stream and a goal, if the lazy-stream has come to an end then the conjunction too, in the other case, take the next substitutions map returned by the stream, pass it to the goal, you get another stream that you concatenate to the sream returned by the conjunction of the beheaded stream and the goal &mdash; in truth concatenation happens through disjunction.</p>
<p>Disjunction takes two lazy streams and returns another lazy stream but is a bit tricky to get right. The naive approach is to simply concatenate the two streams but this is problematic: if the first stream is infinite, results contributed by the second stream are never returned &mdash; but at least some results keep being returend. The problem gets even worse if the first stream does not terminate (because its search space is infinite and all solutions has already been found): it simply blocks the evaluation of the second stream. The right approach is to interleave the two streams so as to consume them concurrently.</p>
<p>So I happily proceeded to the conversion of all core.logic&#8217;s lazy stream code to lazy sequences&#8230; and it failed on some tests; the cause of this failure led to my first <em>ahah</em> moment.</p>
<p>The reason is to be found in the interleaving: if at some point one of the sequences diverges (a call to <code>seq</code> never returns) then one can&#8217;t call <code>first</code> on it and interaleaves its items with those of the other sequence! </p>
<p>How did the interleaving manage to work for lazy streams? Streams are either <code>nil</code>, a thunk or an instance of <code>Choice</code> (the lazy stream pendant of <code>Cons</code>). When you call a thunk to force the lazy stream you may get another thunk, which means that you don&#8217;t have realized the stream but you have advanced towards its realization. So to really force the stream you have to trampoline until a <code>Choice</code> or <code>nil</code> is returned. On the other hand, lazy sequences, when forced, always return <code>nil</code> or a <code>Cons</code> because the trampolining happens <a href="https://github.com/clojure/clojure/blob/9ec2031d8643e2a3fc3774d482ceabcde2d82ed5/src/jvm/clojure/lang/LazySeq.java#L59">inside <code>LazySeq</code></a>.</p>
<p>Hence miniKanren lazy streams give more control on their evaluation to the user and that&#8217;s why they can&#8217;t be replaced by Clojure lazy sequences! This means that <code>mplus</code> (the interleaving function) is all about <strong>scheduling</strong> evaluation of the two streams. This realization struck me: at its heart core.logic business is process management, not about streams mangling!</p>
<p>A disjunction for example can be seen a process forking two child processes and directly passing children results to its own parent process. One can certainly even make a toy implementation on top of agents&#8230;</p>
<p>I said that conjunction was easy a few paragraphs ago, it&#8217;s a lie but it may be the subject of a subsequent post.</p>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/sCeRXT8V7ME" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2012/01/30/the-reasoned-scheduler/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Valued functions</title>
		<link>http://clj-me.cgrand.net/2011/10/17/valued-functions/</link>
		<comments>http://clj-me.cgrand.net/2011/10/17/valued-functions/#comments</comments>
		<pubDate>Mon, 17 Oct 2011 12:55:51 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[unsorted]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=482</guid>
		<description><![CDATA[Functions are black boxes and determining when two functions are equivalent is undecidable. That&#8217;s why:(= (fn [x] x) (fn [x] x)) is false (a clever compiler could sove this naive specific case but not all). However from time to time I&#8217;d like functions constructed the same way be considered equals. For example (= (comp inc [...]]]></description>
			<content:encoded><![CDATA[<p>Functions are black boxes and determining when two functions are equivalent is undecidable. That&#8217;s why:<code class="highlight"><span class="p">(</span><span class="nb">= </span><span class="p">(</span><span class="k">fn </span><span class="p">[</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="k">fn </span><span class="p">[</span><span class="nv">x</span><span class="p">]</span> <span class="nv">x</span><span class="p">))</span></code> is false (a clever compiler could sove this naive specific case but not all).</p>
<p>However from time to time I&#8217;d like functions constructed the same way be considered equals. For example <code class="highlight"><span class="p">(</span><span class="nb">= </span><span class="p">(</span><span class="nb">comp </span><span class="nv">inc</span> <span class="nv">inc</span><span class="p">)</span> <span class="p">(</span><span class="nb">comp </span><span class="nv">inc</span> <span class="nv">inc</span><span class="p">))</span></code> could be true and it wouldn&#8217;t necessitate a smart enough compiler or memoization.</p>
<p>It&#8217;s not without precedent: keywords, symbols, maps, sets and vectors are functions and also have value semantics: <code class="highlight"><span class="p">(</span><span class="nb">= </span><span class="p">(</span><span class="nb">hash-set </span><span class="mi">1</span><span class="p">)</span> <span class="p">(</span><span class="nb">hash-set </span><span class="mi">1</span><span class="p">))</span></code> is true!</p>
<p>In <a href="https://github.com/cgrand/indexed-set">indexed-set</a> I use maps whose values are functions, sometimes functions returned by higher-order functions and the user having no reference to the function returned by the hof can&#8217;t look it up in the map &mdash; if she calls the hof agin with the same arguments she gets another function which is not equal to the first one. This means that I should always let the user call the hof by herself and keep the result around. It may be ok for a low-level API but not for more user-friendly functions.</p>
<p>Helpfully, records have value semantics, can implement Java interfaces and do not already implement <code class="highlight"><span class="nv">clojure</span><span class="o">.</span><span class="nv">lang</span><span class="o">.</span><span class="nv">IFn</span></code> and <a href="https://github.com/cgrand/indexed-set/blob/6031fa1e9ffdf482bdae44345752cda2217e51d4/src/net/cgrand/indexed_set/core.clj#L195">that&#8217;s what I have done</a>:
<pre class="highlight"><span class="p">(</span><span class="nf">defrecord</span> <span class="nv">Op-By</span> <span class="p">[</span><span class="nv">key</span> <span class="nv">f</span> <span class="nv">init</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">invoke</span> <span class="p">[</span><span class="nv">this</span> <span class="nv">m</span> <span class="nv">v</span><span class="p">]</span>
    <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">k</span> <span class="p">(</span><span class="nb">key </span><span class="nv">v</span><span class="p">)]</span>
      <span class="p">(</span><span class="nb">assoc </span><span class="nv">m</span> <span class="nv">k</span> <span class="p">(</span><span class="nf">f</span> <span class="p">(</span><span class="nf">m</span> <span class="nv">k</span> <span class="nv">init</span><span class="p">)</span> <span class="nv">v</span><span class="p">)))))</span>

<span class="p">(</span><span class="k">defn- </span><span class="nv">op-by</span> <span class="p">[</span><span class="nv">key</span> <span class="nv">f</span> <span class="nv">init</span><span class="p">]</span> <span class="p">(</span><span class="nf">Op-By</span><span class="o">.</span> <span class="nv">key</span> <span class="nv">f</span> <span class="nv">init</span><span class="p">))</span></pre>
<p> instead of
<pre class="highlight"><span class="p">(</span><span class="k">defn- </span><span class="nv">op-by</span> <span class="p">[</span><span class="nv">key</span> <span class="nv">f</span> <span class="nv">init</span><span class="p">]</span>
  <span class="p">(</span><span class="k">fn </span><span class="p">[</span><span class="nv">m</span> <span class="nv">v</span><span class="p">])</span>
    <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">k</span> <span class="p">(</span><span class="nb">key </span><span class="nv">v</span><span class="p">)]</span>
      <span class="p">(</span><span class="nb">assoc </span><span class="nv">m</span> <span class="nv">k</span> <span class="p">(</span><span class="nf">f</span> <span class="p">(</span><span class="nf">m</span> <span class="nv">k</span> <span class="nv">init</span><span class="p">)</span> <span class="nv">v</span><span class="p">))))</span></pre>
<p>I&#8217;m still not happy with that I&#8217;d like something more fluid (closer to fn, maybe built on reify but ideally a metadata flag  on <code class="highlight"><span class="nv">fn</span></code> e.g. <code class="highlight"><span class="p">(</span><span class="nf">^:valued</span> <span class="k">fn </span><span class="p">[</span><span class="nv">m</span> <span class="nv">v</span><span class="p">]</span> <span class="o">...</span><span class="p">)</span></code>) ; I don&#8217;t think the type name is valueable, I&#8217;m on the fence concerning features I get <em>for free</em> from <code class="highlight"><span class="nv">defrecord</span></code> (namely <code class="highlight"><span class="nv">conj</span></code>, <code class="highlight"><span class="nv">assoc</span></code> and <code class="highlight"><span class="nv">dissoc</span></code>).</p>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/qBJvkoDdWvs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2011/10/17/valued-functions/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>A world in a ref</title>
		<link>http://clj-me.cgrand.net/2011/10/06/a-world-in-a-ref/</link>
		<comments>http://clj-me.cgrand.net/2011/10/06/a-world-in-a-ref/#comments</comments>
		<pubDate>Thu, 06 Oct 2011 11:00:30 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[unsorted]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=463</guid>
		<description><![CDATA[At times I struggle deciding on the granularity I should give to my refs. If I put a big map in a single ref (what I call a megaref), updates to unrelated parts of the map may conflict and cause transactions to retry, but it&#8217;s dead easy to snapshot the whole state. If I use [...]]]></description>
			<content:encoded><![CDATA[<p>At times I struggle deciding on the granularity I should give to my refs. If I put a big map in a single ref (what I call a <em>megaref</em>), updates to unrelated parts of the map may conflict and cause transactions to retry, but it&#8217;s dead easy to snapshot the whole state. If I use a ref for every entry of the map, concurrency is excellent again but snapshotting the whole state may be tricky (you need to tune the ref to have a history long enough) when there is a large number of rapidly changing refs or when the system is slow/loaded.</p>
<p>What I&#8217;d like is an <code class="highlight"><span class="nv">alter-in</span></code> function, a mix of <code class="highlight"><span class="nv">alter</span></code> and <code class="highlight"><span class="nv">update-in</span></code>, with the following guarantee: <em>two <code class="highlight"><span class="nv">alter-in</span></code>s conflict when their paths are either equal or prefix from one another</em>.</p>
<p>This is not something new: this problem bugs me since 2008 I think. I had several (failed/unfinished and private) attempts to patch the STM to accommodate for a new reference type.</p>
<p>Some weeks ago I realized that I didn&#8217;t need to hack the STM to create such a new reference type.</p>
<p>The basic idea behind all my attempts was to use lock-striping. What I didn&#8217;t realize is that I can leverage the existing STM by using ref-striping!</p>
<p>Let&#8217;s say the whole map is stored in a single ref, the <em>root</em> ref and you have N guard refs (whose value is <code class="highlight"><span class="nv">nil</span></code>). When I want to alter the value for a given key, I compute its hash modulo N which gives me an index into the guards vector. I <code class="highlight"><span class="nv">ref-set</span></code> the corresponding guard ref (to <code class="highlight"><span class="nv">nil</span></code>, the actual value doesn&#8217;t matter) thus claiming exclusive commit rights for this key. Once that done I simply <code class="highlight"><span class="nv">commute</span></code> on the root ref being sure that the operation will only commute with non-conflicting other ops.</p>
<p>NB: An alternative design is to simply have N roots and no guards and to merge the N maps on <code class="highlight"><span class="nv">deref</span></code> — efficient merging would need a didcated map implementation. However it doesn&#8217;t help much with nested maps but it helps a lot with concurrency since in the other design everything is serialized on the single root. I think an hybrid solution (N roots, each roots having M guards) woud bring an interesting trade-off between concurrency, number of retries and ease of snapshotting.</p>
<p>To support nested maps, instead of a single key, one has to deal with a path, eg <code class="highlight"><span class="p">[</span><span class="nv">:a</span> <span class="nv">:b</span> <span class="nv">:c</span><span class="p">]</span></code>. Here the idea is to <code class="highlight"><span class="nv">ensure</span></code> guards for path prefixes (<code class="highlight"><span class="p">[</span><span class="nv">:a</span><span class="p">]</span></code> and <code class="highlight"><span class="p">[</span><span class="nv">:a</span> <span class="nv">:b</span><span class="p">]</span></code>) and to <code class="highlight"><span class="nv">ref-set</span></code> the guard for the full-path as before.</p>
<pre class="highlight"><span class="c1">;; except ensure-in and alter-in, the others are here because</span>
<span class="c1">;; they can be optimized in a mega ref wth several roots</span>
<span class="p">(</span><span class="nf">defprotocol</span> <span class="nv">AssociativeRef</span>
  <span class="p">(</span><span class="nf">-alter-in</span> <span class="p">[</span><span class="nv">aref</span> <span class="nv">ks</span> <span class="nv">f</span> <span class="nv">args</span><span class="p">])</span>
  <span class="p">(</span><span class="nf">-commute-in</span> <span class="p">[</span><span class="nv">aref</span> <span class="nv">ks</span> <span class="nv">f</span> <span class="nv">args</span><span class="p">])</span>
  <span class="p">(</span><span class="nf">ref-set-in</span> <span class="p">[</span><span class="nv">aref</span> <span class="nv">ks</span> <span class="nv">v</span><span class="p">])</span>
  <span class="p">(</span><span class="nf">ensure-in</span> <span class="p">[</span><span class="nv">aref</span> <span class="nv">ks</span><span class="p">])</span>
  <span class="p">(</span><span class="nf">deref-in</span> <span class="p">[</span><span class="nv">aref</span> <span class="nv">ks</span><span class="p">]))</span>

<span class="p">(</span><span class="k">defn </span><span class="nv">alter-in</span> <span class="p">[</span><span class="nv">aref</span> <span class="nv">ks</span> <span class="nv">f</span> <span class="nv">&amp;</span> <span class="nv">args</span><span class="p">]</span>
  <span class="p">(</span><span class="nf">-alter-in</span> <span class="nv">aref</span> <span class="nv">ks</span> <span class="nv">f</span> <span class="nv">args</span><span class="p">))</span>

<span class="p">(</span><span class="k">defn </span><span class="nv">commute-in</span> <span class="p">[</span><span class="nv">aref</span> <span class="nv">ks</span> <span class="nv">f</span> <span class="nv">&amp;</span> <span class="nv">args</span><span class="p">]</span>
  <span class="p">(</span><span class="nf">-commute-in</span> <span class="nv">aref</span> <span class="nv">ks</span> <span class="nv">f</span> <span class="nv">args</span><span class="p">))</span>

<span class="p">(</span><span class="k">defn- </span><span class="nv">ensure-path</span> <span class="p">[</span><span class="nv">guard-for</span> <span class="nv">path</span><span class="p">]</span>
  <span class="p">(</span><span class="nb">loop </span><span class="p">[</span><span class="nv">path</span> <span class="nv">path</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="p">[]</span> <span class="nv">path</span><span class="p">)</span>
      <span class="p">(</span><span class="nb">ensure </span><span class="p">(</span><span class="nf">guard-for</span> <span class="nv">path</span><span class="p">))</span>
      <span class="p">(</span><span class="nf">recur</span> <span class="p">(</span><span class="nb">pop </span><span class="nv">path</span><span class="p">)))))</span>

<span class="p">(</span><span class="k">defn- </span><span class="nv">guards-fn</span> <span class="p">[</span><span class="nv">guards</span><span class="p">]</span>
  <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">n</span> <span class="p">(</span><span class="nb">count </span><span class="nv">guards</span><span class="p">)]</span>
    <span class="o">#</span><span class="p">(</span><span class="nv">nth</span> <span class="nv">guards</span> <span class="p">(</span><span class="nf">mod</span> <span class="p">(</span><span class="nf">hash</span> <span class="nv">%</span><span class="p">)</span> <span class="nv">n</span><span class="p">))))</span>

<span class="p">(</span><span class="nf">deftype</span> <span class="nv">MegaRef</span> <span class="p">[</span><span class="nv">r</span> <span class="nv">guards</span><span class="p">]</span>
  <span class="nv">AssociativeRef</span>
  <span class="p">(</span><span class="nf">-alter-in</span> <span class="p">[</span><span class="nv">this</span> <span class="nv">ks</span> <span class="nv">f</span> <span class="nv">args</span><span class="p">]</span>
    <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">seq </span><span class="nv">ks</span><span class="p">)</span>
      <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">guard-for</span> <span class="p">(</span><span class="nf">guards-fn</span> <span class="nv">guards</span><span class="p">)]</span>
        <span class="p">(</span><span class="nf">ensure-path</span> <span class="nv">guard-for</span> <span class="p">(</span><span class="nb">pop </span><span class="p">(</span><span class="nf">vec</span> <span class="nv">ks</span><span class="p">)))</span>
        <span class="p">(</span><span class="nb">ref-set </span><span class="p">(</span><span class="nf">guard-for</span> <span class="nv">ks</span><span class="p">)</span> <span class="nv">nil</span><span class="p">)</span>
        <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">v</span> <span class="p">(</span><span class="nb">apply </span><span class="nv">f</span> <span class="p">(</span><span class="nf">get-in</span> <span class="nv">@r</span> <span class="nv">ks</span><span class="p">)</span> <span class="nv">args</span><span class="p">)]</span>
          <span class="c1">; v is precomputed to not evaluate it twice because of commute</span>
          <span class="p">(</span><span class="nb">commute </span><span class="nv">r</span> <span class="nv">assoc-in</span> <span class="nv">ks</span> <span class="nv">v</span><span class="p">)))</span>
      <span class="p">(</span><span class="nf">throw</span> <span class="p">(</span><span class="nf">IllegalArgumentException</span><span class="o">.</span> <span class="s">&quot;ks must not be empty.&quot;</span><span class="p">))))</span>
  <span class="p">(</span><span class="nf">-commute-in</span> <span class="p">[</span><span class="nv">this</span> <span class="nv">ks</span> <span class="nv">f</span> <span class="nv">args</span><span class="p">]</span>
    <span class="p">(</span><span class="nb">apply </span><span class="nv">commute</span> <span class="nv">r</span> <span class="nv">update-in</span> <span class="nv">ks</span> <span class="nv">f</span> <span class="nv">args</span><span class="p">))</span>
  <span class="p">(</span><span class="nf">ref-set-in</span> <span class="p">[</span><span class="nv">this</span> <span class="nv">ks</span> <span class="nv">v</span><span class="p">]</span>
    <span class="p">(</span><span class="nf">-alter-in</span> <span class="nv">this</span> <span class="nv">ks</span> <span class="p">(</span><span class="nb">constantly </span><span class="nv">v</span><span class="p">)</span> <span class="nv">nil</span><span class="p">))</span>
  <span class="p">(</span><span class="nf">ensure-in</span> <span class="p">[</span><span class="nv">this</span> <span class="nv">ks</span><span class="p">]</span>
    <span class="p">(</span><span class="nf">ensure-path</span>  <span class="p">(</span><span class="nf">vec</span> <span class="nv">ks</span><span class="p">)</span> <span class="p">(</span><span class="nf">guards-fn</span> <span class="nv">guards</span><span class="p">))</span>
    <span class="p">(</span><span class="nf">deref-in</span> <span class="nv">this</span> <span class="nv">ks</span><span class="p">))</span>
  <span class="p">(</span><span class="nf">deref-in</span> <span class="p">[</span><span class="nv">this</span> <span class="nv">ks</span><span class="p">]</span>
    <span class="p">(</span><span class="nf">get-in</span> <span class="nv">@r</span> <span class="nv">ks</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">IDeref</span>
  <span class="p">(</span><span class="nb">deref </span><span class="p">[</span><span class="nv">this</span><span class="p">]</span>
    <span class="nv">@r</span><span class="p">))</span>

<span class="p">(</span><span class="k">defn </span><span class="nv">megaref</span> <span class="p">[</span><span class="nv">entries</span> <span class="nv">&amp;</span> <span class="nv">options</span><span class="p">]</span>
  <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">guards</span> <span class="p">(</span><span class="nf">:guards</span> <span class="nv">options</span> <span class="mi">16</span><span class="p">)</span>
        <span class="nv">root-options</span> <span class="p">(</span><span class="nb">select-keys </span><span class="nv">options</span> <span class="p">[</span><span class="nv">:validator</span> <span class="nv">:min-history</span> <span class="nv">:max-history</span><span class="p">])]</span>
    <span class="p">(</span><span class="nf">MegaRef</span><span class="o">.</span> <span class="p">(</span><span class="nb">apply </span><span class="nv">ref</span> <span class="p">(</span><span class="nb">into </span><span class="p">{}</span> <span class="nv">entries</span><span class="p">)</span> <span class="nv">root-options</span><span class="p">)</span>
              <span class="p">(</span><span class="nf">vec</span> <span class="p">(</span><span class="nf">repeatedly</span> <span class="nv">guards</span> <span class="o">#</span><span class="p">(</span><span class="nv">ref</span> <span class="nv">nil</span><span class="p">))))))</span></pre>
<p>NB: Write skew anomalies can now occur at the &#8220;sub ref&#8221; level: when you <code class="highlight"><span class="nv">deref-in</span></code> a path unrelated to the ones you update; <code class="highlight"><span class="nv">ensure-in</span></code> is the answer.</p>
<p>So, some questions:</p>
<ul>
<li>Is this of interest to anyone except me? If yes, once mature (eg multiroot) should it belong in contrib?</li>
<li>Is my implementation sound? Do I rely on implementation details?</li>
<li>Should the STM expose a &#8220;token&#8221; facility so that I don&#8217;t have to use refs as guards?</li>
</ul>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/0CrtyBqtOBI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2011/10/06/a-world-in-a-ref/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Conway’s Game of Life</title>
		<link>http://clj-me.cgrand.net/2011/08/19/conways-game-of-life/</link>
		<comments>http://clj-me.cgrand.net/2011/08/19/conways-game-of-life/#comments</comments>
		<pubDate>Fri, 19 Aug 2011 18:01:54 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[unsorted]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=447</guid>
		<description><![CDATA[APL is famous for having a 1-liner for Conway&#8217;s game of life. Being very efficient at implementing a matrix-based solution of Conway&#8217;s game of life should come to no suprise from an array-oriented language. The way you model data determines your code. Clojure encourages what I call relational-oriented programming. That is modeling with sets, natural [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://en.wikipedia.org/wiki/APL_%28programming_language%29">APL</a> is famous for having a 1-liner for Conway&#8217;s game of life.<br />
Being very efficient at implementing a matrix-based solution of Conway&#8217;s game of life should come to no suprise from an array-oriented language.</p>
<p>The way you model data determines your code. Clojure encourages what I call relational-oriented programming. That is modeling with sets, natural identifiers (thanks to composite values) and maps-as-indexes.</p>
<p>If you pick the right representation for the state of the board, you end up with a succinct implementation: </p>
<pre class="highlight"><span class="p">(</span><span class="k">defn </span><span class="nv">neighbours</span> <span class="p">[[</span><span class="nv">x</span> <span class="nv">y</span><span class="p">]]</span>
  <span class="p">(</span><span class="k">for </span><span class="p">[</span><span class="nv">dx</span> <span class="p">[</span><span class="mi">-1</span> <span class="mi">0</span> <span class="mi">1</span><span class="p">]</span> <span class="nv">dy</span> <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">zero? </span><span class="nv">dx</span><span class="p">)</span> <span class="p">[</span><span class="mi">-1</span> <span class="mi">1</span><span class="p">]</span> <span class="p">[</span><span class="mi">-1</span> <span class="mi">0</span> <span class="mi">1</span><span class="p">])]</span>
    <span class="p">[(</span><span class="nb">+ </span><span class="nv">dx</span> <span class="nv">x</span><span class="p">)</span> <span class="p">(</span><span class="nb">+ </span><span class="nv">dy</span> <span class="nv">y</span><span class="p">)]))</span>

<span class="p">(</span><span class="k">defn </span><span class="nv">step</span> <span class="p">[</span><span class="nv">cells</span><span class="p">]</span>
  <span class="p">(</span><span class="nb">set </span><span class="p">(</span><span class="k">for </span><span class="p">[[</span><span class="nv">loc</span> <span class="nv">n</span><span class="p">]</span> <span class="p">(</span><span class="nf">frequencies</span> <span class="p">(</span><span class="nb">mapcat </span><span class="nv">neighbours</span> <span class="nv">cells</span><span class="p">))</span>
             <span class="nv">:when</span> <span class="p">(</span><span class="nb">or </span><span class="p">(</span><span class="nb">= </span><span class="nv">n</span> <span class="mi">3</span><span class="p">)</span> <span class="p">(</span><span class="nb">and </span><span class="p">(</span><span class="nb">= </span><span class="nv">n</span> <span class="mi">2</span><span class="p">)</span> <span class="p">(</span><span class="nf">cells</span> <span class="nv">loc</span><span class="p">)))]</span>
         <span class="nv">loc</span><span class="p">)))</span></pre>
<p>Let&#8217;s see how it behaves with the <a href="http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life#Examples_of_patterns">&#8220;blinker&#8221;</a> configuration:</p>
<pre class="highlight"><span class="p">(</span><span class="k">def </span><span class="nv">board</span> <span class="o">#</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="mi">1</span> <span class="mi">1</span><span class="p">]</span> <span class="p">[</span><span class="mi">1</span> <span class="mi">2</span><span class="p">]})</span>
<span class="c1">; #&#39;user/board</span>
<span class="p">(</span><span class="nb">take </span><span class="mi">5</span> <span class="p">(</span><span class="nb">iterate </span><span class="nv">step</span> <span class="nv">board</span><span class="p">))</span>
<span class="c1">; (#{[1 0] [1 1] [1 2]} #{[2 1] [1 1] [0 1]} #{[1 0] [1 1] [1 2]} #{[2 1] [1 1] [0 1]} #{[1 0] [1 1] [1 2]})</span></pre>
<p>Great, it oscillates as expected!</p>
<p>From this <code class="highlight"><span class="nv">step</span></code> can be distilled a generic topology-agnostic life-like automatons stepper factory (phew!) but this is a subject for another post or &mdash; shameless plug &mdash; <a href="http://oreilly.com/catalog/0636920013754/">a book</a>. </p>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/O4-uoXdruFU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2011/08/19/conways-game-of-life/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>A flatter cond</title>
		<link>http://clj-me.cgrand.net/2011/06/17/a-flatter-cond/</link>
		<comments>http://clj-me.cgrand.net/2011/06/17/a-flatter-cond/#comments</comments>
		<pubDate>Fri, 17 Jun 2011 12:44:46 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[utilities]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=449</guid>
		<description><![CDATA[Long time, no post. I&#8217;ve had two hiatus (one of this kind and one of that kind) and I&#8217;m still going through the pile of accumulated work (including the bird book &#8212; it&#8217;s a painted snipe). To warm up, a little macro I find quite handy: (ns flatter.cond (:refer-clojure :exclude [cond])) (defmacro cond &#34;A variation [...]]]></description>
			<content:encoded><![CDATA[<p>Long time, no post. I&#8217;ve had two hiatus (one of <a href="http://disclojure.org/2011/05/08/this-weekend-in-the-intertweets-may-8th-edition/">this kind</a> and one of <a href="http://en.wikipedia.org/wiki/Spinal_disc_herniation#Surgical">that kind</a>) and I&#8217;m still going through the pile of accumulated work (including <a href="http://oreilly.com/catalog/0636920013754/">the bird book</a> &mdash; it&#8217;s a <a href="http://en.wikipedia.org/wiki/Painted_snipe">painted snipe</a>).</p>
<p>To warm up, a little macro I find quite handy:</p>
<pre class="highlight"><span class="p">(</span><span class="nf">ns</span> <span class="nv">flatter</span><span class="o">.</span><span class="nv">cond</span>
  <span class="p">(</span><span class="nf">:refer-clojure</span> <span class="nv">:exclude</span> <span class="p">[</span><span class="nv">cond</span><span class="p">]))</span>

<span class="p">(</span><span class="k">defmacro cond </span>
  <span class="s">&quot;A variation on cond which sports let bindings:</span>
<span class="s">     (cond </span>
<span class="s">       (odd? a) 1</span>
<span class="s">       :let [a (quot a 2)]</span>
<span class="s">       (odd? a) 2</span>
<span class="s">       :else 3)&quot;</span>
  <span class="p">[</span><span class="nv">&amp;</span> <span class="nv">clauses</span><span class="p">]</span>
  <span class="p">(</span><span class="nb">when-let </span><span class="p">[[</span><span class="nv">test</span> <span class="nv">expr</span> <span class="nv">&amp;</span> <span class="nv">clauses</span><span class="p">]</span> <span class="p">(</span><span class="nb">seq </span><span class="nv">clauses</span><span class="p">)]</span>
    <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">= </span><span class="nv">:let</span> <span class="nv">test</span><span class="p">)</span>
      <span class="o">`</span><span class="p">(</span><span class="k">let </span><span class="nv">~expr</span> <span class="p">(</span><span class="k">cond </span><span class="nv">~@clauses</span><span class="p">))</span>
      <span class="o">`</span><span class="p">(</span><span class="k">if </span><span class="nv">~test</span> <span class="nv">~expr</span> <span class="p">(</span><span class="k">cond </span><span class="nv">~@clauses</span><span class="p">)))))</span></pre>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/NFUfehVcQIk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2011/06/17/a-flatter-cond/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>A* in Clojure</title>
		<link>http://clj-me.cgrand.net/2010/09/04/a-in-clojure/</link>
		<comments>http://clj-me.cgrand.net/2010/09/04/a-in-clojure/#comments</comments>
		<pubDate>Sat, 04 Sep 2010 02:22:48 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[unsorted]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/?p=440</guid>
		<description><![CDATA[Thanks to Mark Engelberg there&#8217;s now a nice priority map in contrib. With such a facility, it becomes really easy to write a nice implementation of the A* algorithm. (ns net.cgrand.clj-me.a-star (:use [clojure.contrib.priority-map :only [priority-map]])) (defn A* &#34;Finds a path between start and goal inside the graph described by edges (a map of edge to [...]]]></description>
			<content:encoded><![CDATA[<p>Thanks to Mark Engelberg there&#8217;s now a nice <a href="http://github.com/clojure/clojure-contrib/blob/master/modules/priority-map/src/main/clojure/clojure/contrib/priority_map.clj">priority map in contrib</a>. With such a facility, it becomes really easy to write a nice implementation of the <a href="http://en.wikipedia.org/wiki/A*_search_algorithm">A* algorithm</a>.</p>
<pre class="highlight"><span class="p">(</span><span class="nf">ns</span> <span class="nv">net</span><span class="o">.</span><span class="nv">cgrand</span><span class="o">.</span><span class="nv">clj-me</span><span class="o">.</span><span class="nv">a-star</span>
  <span class="p">(</span><span class="nf">:use</span> <span class="p">[</span><span class="nv">clojure</span><span class="o">.</span><span class="nv">contrib</span><span class="o">.</span><span class="nv">priority-map</span> <span class="nv">:only</span> <span class="p">[</span><span class="nv">priority-map</span><span class="p">]]))</span>

<span class="p">(</span><span class="k">defn </span><span class="nv">A*</span>
 <span class="s">&quot;Finds a path between start and goal inside the graph described by edges</span>
<span class="s">  (a map of edge to distance); estimate is an heuristic for the actual</span>
<span class="s">  distance. Accepts a named option: :monotonic (default to true).</span>
<span class="s">  Returns the path if found or nil.&quot;</span>
 <span class="p">[</span><span class="nv">edges</span> <span class="nv">estimate</span> <span class="nv">start</span> <span class="nv">goal</span> <span class="nv">&amp;</span> <span class="p">{</span><span class="nv">mono</span> <span class="nv">:monotonic</span> <span class="nv">:or</span> <span class="p">{</span><span class="nv">mono</span> <span class="nv">true</span><span class="p">}}]</span>
  <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">f</span> <span class="p">(</span><span class="nf">memoize</span> <span class="o">#</span><span class="p">(</span><span class="nv">estimate</span> <span class="nv">%</span> <span class="nv">goal</span><span class="p">))</span> <span class="c1">; unsure the memoization is worthy</span>
        <span class="nv">neighbours</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">m</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="nb">assoc </span><span class="nv">m</span> <span class="nv">a</span> <span class="p">(</span><span class="nb">conj </span><span class="p">(</span><span class="nf">m</span> <span class="nv">a</span> <span class="o">#</span><span class="p">{})</span> <span class="nv">b</span><span class="p">)))</span>
                      <span class="p">{}</span> <span class="p">(</span><span class="nb">keys </span><span class="nv">edges</span><span class="p">))]</span>
    <span class="p">(</span><span class="nb">loop </span><span class="p">[</span><span class="nv">q</span> <span class="p">(</span><span class="nf">priority-map</span> <span class="nv">start</span> <span class="p">(</span><span class="nf">f</span> <span class="nv">start</span><span class="p">))</span>
           <span class="nv">preds</span> <span class="p">{}</span>
           <span class="nv">shortest</span> <span class="p">{</span><span class="nv">start</span> <span class="mi">0</span><span class="p">}</span>
           <span class="nv">done</span> <span class="o">#</span><span class="p">{}]</span>
      <span class="p">(</span><span class="nb">when-let </span><span class="p">[[</span><span class="nv">x</span> <span class="nv">hx</span><span class="p">]</span> <span class="p">(</span><span class="nb">peek </span><span class="nv">q</span><span class="p">)]</span>
        <span class="p">(</span><span class="k">if </span><span class="p">(</span><span class="nb">= </span><span class="nv">goal</span> <span class="nv">x</span><span class="p">)</span>
          <span class="p">(</span><span class="nb">reverse </span><span class="p">(</span><span class="nb">take-while </span><span class="nv">identity</span> <span class="p">(</span><span class="nb">iterate </span><span class="nv">preds</span> <span class="nv">goal</span><span class="p">)))</span>
          <span class="p">(</span><span class="k">let </span><span class="p">[</span><span class="nv">dx</span> <span class="p">(</span><span class="nb">- </span><span class="nv">hx</span> <span class="p">(</span><span class="nf">f</span> <span class="nv">x</span><span class="p">))</span>
                <span class="nv">bn</span> <span class="p">(</span><span class="k">for </span><span class="p">[</span><span class="nv">n</span> <span class="p">(</span><span class="nb">remove </span><span class="nv">done</span> <span class="p">(</span><span class="nf">neighbours</span> <span class="nv">x</span><span class="p">))</span>
                         <span class="nv">:let</span> <span class="p">[</span><span class="nv">hn</span> <span class="p">(</span><span class="nb">+ </span><span class="nv">dx</span> <span class="p">(</span><span class="nf">edges</span> <span class="p">[</span><span class="nv">x</span> <span class="nv">n</span><span class="p">])</span> <span class="p">(</span><span class="nf">f</span> <span class="nv">n</span><span class="p">))</span>
                               <span class="nv">sn</span> <span class="p">(</span><span class="nf">shortest</span> <span class="nv">n</span> <span class="nv">Double/POSITIVE_INFINITY</span><span class="p">)]</span>
                         <span class="nv">:when</span> <span class="p">(</span><span class="nb">&lt; </span><span class="nv">hn</span> <span class="nv">sn</span><span class="p">)]</span>
                     <span class="p">[</span><span class="nv">n</span> <span class="nv">hn</span><span class="p">])]</span>
            <span class="p">(</span><span class="nf">recur</span> <span class="p">(</span><span class="nb">into </span><span class="p">(</span><span class="nb">pop </span><span class="nv">q</span><span class="p">)</span> <span class="nv">bn</span><span class="p">)</span>
              <span class="p">(</span><span class="nb">into </span><span class="nv">preds</span> <span class="p">(</span><span class="k">for </span><span class="p">[[</span><span class="nv">n</span><span class="p">]</span> <span class="nv">bn</span><span class="p">]</span> <span class="p">[</span><span class="nv">n</span> <span class="nv">x</span><span class="p">]))</span>
              <span class="p">(</span><span class="nb">into </span><span class="nv">shortest</span> <span class="nv">bn</span><span class="p">)</span>
              <span class="p">(</span><span class="k">if </span><span class="nv">mono</span> <span class="p">(</span><span class="nb">conj </span><span class="nv">done</span> <span class="nv">x</span><span class="p">)</span> <span class="nv">done</span><span class="p">))))))))</span></pre>
<p>Example:</p>
<pre class="highlight"><span class="p">(</span><span class="k">defn </span><span class="nv">euclidian-distance</span> <span class="p">[</span><span class="nv">a</span> <span class="nv">b</span><span class="p">]</span> <span class="c1">; multidimensional</span>
  <span class="p">(</span><span class="nf">Math/sqrt</span> <span class="p">(</span><span class="nb">reduce </span><span class="nv">+</span> <span class="p">(</span><span class="nb">map </span><span class="o">#</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">- </span><span class="nv">%1</span> <span class="nv">%2</span><span class="p">)]</span> <span class="p">(</span><span class="nb">* </span><span class="nv">c</span> <span class="nv">c</span><span class="p">))</span> <span class="nv">a</span> <span class="nv">b</span><span class="p">))))</span>

<span class="c1">;; generate a grid graph whose outlying edges are one-way</span>
<span class="p">(</span><span class="k">defn </span><span class="nv">grid</span> <span class="p">[</span><span class="nv">x</span> <span class="nv">y</span> <span class="nv">w</span> <span class="nv">h</span><span class="p">]</span>
  <span class="p">(</span><span class="nb">into </span><span class="p">{}</span>
    <span class="p">(</span><span class="k">for </span><span class="p">[</span><span class="nv">i</span> <span class="p">(</span><span class="nb">range </span><span class="nv">w</span><span class="p">)</span> <span class="nv">j</span> <span class="p">(</span><span class="nb">range </span><span class="nv">h</span><span class="p">)</span>
          <span class="nv">:let</span> <span class="p">[</span><span class="nv">x0</span> <span class="p">(</span><span class="nb">+ </span><span class="nv">x</span> <span class="nv">i</span><span class="p">)</span> <span class="nv">y0</span> <span class="p">(</span><span class="nb">+ </span><span class="nv">y</span> <span class="nv">j</span><span class="p">)</span> <span class="nv">x1</span> <span class="p">(</span><span class="nb">inc </span><span class="nv">x0</span><span class="p">)</span> <span class="nv">y1</span> <span class="p">(</span><span class="nb">inc </span><span class="nv">y0</span><span class="p">)]]</span>
      <span class="p">{[[</span><span class="nv">x0</span> <span class="nv">y0</span><span class="p">]</span> <span class="p">[</span><span class="nv">x1</span> <span class="nv">y0</span><span class="p">]]</span> <span class="mi">1</span>
       <span class="p">[[</span><span class="nv">x1</span> <span class="nv">y0</span><span class="p">]</span> <span class="p">[</span><span class="nv">x1</span> <span class="nv">y1</span><span class="p">]]</span> <span class="mi">1</span>
       <span class="p">[[</span><span class="nv">x1</span> <span class="nv">y1</span><span class="p">]</span> <span class="p">[</span><span class="nv">x0</span> <span class="nv">y1</span><span class="p">]]</span> <span class="mi">1</span>
       <span class="p">[[</span><span class="nv">x0</span> <span class="nv">y1</span><span class="p">]</span> <span class="p">[</span><span class="nv">x0</span> <span class="nv">y0</span><span class="p">]]</span> <span class="mi">1</span><span class="p">})))</span>

<span class="p">(</span><span class="k">def </span><span class="nv">g</span> <span class="p">(</span><span class="nb">apply </span><span class="nv">dissoc</span> <span class="p">(</span><span class="nf">grid</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">4</span> <span class="mi">4</span><span class="p">)</span> <span class="p">(</span><span class="nb">keys </span><span class="p">(</span><span class="nf">grid</span> <span class="mi">1</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">2</span><span class="p">))))</span>

<span class="p">(</span><span class="nb">comment </span>
<span class="nv">user=&gt;</span> <span class="p">(</span><span class="nf">A*</span> <span class="nv">g</span> <span class="nv">euclidian-distance</span> <span class="p">[</span><span class="mi">0</span> <span class="mi">3</span><span class="p">]</span> <span class="p">[</span><span class="mi">4</span> <span class="mi">2</span><span class="p">])</span>
<span class="p">([</span><span class="mi">0</span> <span class="mi">3</span><span class="p">]</span> <span class="p">[</span><span class="mi">1</span> <span class="mi">3</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="mi">3</span><span class="p">]</span> <span class="p">[</span><span class="mi">3</span> <span class="mi">3</span><span class="p">]</span> <span class="p">[</span><span class="mi">3</span> <span class="mi">2</span><span class="p">]</span> <span class="p">[</span><span class="mi">4</span> <span class="mi">2</span><span class="p">])</span>
<span class="p">)</span></pre>
<p>Shameless plug: if you are in Europe and want to learn Clojure, don&#8217;t forget to register for the Frankfurt course, October 26-28.</p>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/JGr_BmsLypQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2010/09/04/a-in-clojure/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Quick update</title>
		<link>http://clj-me.cgrand.net/2010/08/26/quick-update/</link>
		<comments>http://clj-me.cgrand.net/2010/08/26/quick-update/#comments</comments>
		<pubDate>Wed, 25 Aug 2010 22:05:50 +0000</pubDate>
		<dc:creator>cgrand</dc:creator>
				<category><![CDATA[unsorted]]></category>

		<guid isPermaLink="false">http://clj-me.cgrand.net/2010/08/26/quick-update/</guid>
		<description><![CDATA[Long time no post. No code in this one though. However I&#8217;m pleased to announce that Lau and me are going to give another Clojure course: October 26-28 in Frankfurt, beginners welcome. So if you want to learn Clojure, register!]]></description>
			<content:encoded><![CDATA[<p>Long time no post. No code in this one though.<br />
However I&#8217;m pleased to announce that Lau and me are going to give another Clojure course: October 26-28 in Frankfurt, beginners welcome. So if you want to learn Clojure, register!</p>
<img src="http://feeds.feedburner.com/~r/ClojureAndMe/~4/ggv9xIVtFH4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://clj-me.cgrand.net/2010/08/26/quick-update/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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 (or even Rich&#8217;s) best attempt [...]]]></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>
	</channel>
</rss>

