<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	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:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
		>
<channel>
	<title>Comments on: 7 Rules for Writing Clojure Programs</title>
	<atom:link href="http://twoguysarguing.wordpress.com/2010/07/26/7-rules-for-writing-clojure-programs/feed/" rel="self" type="application/rss+xml" />
	<link>http://twoguysarguing.wordpress.com/2010/07/26/7-rules-for-writing-clojure-programs/</link>
	<description>colorful back and forth from two highly opinionated programmers</description>
	<lastBuildDate>Fri, 17 May 2013 10:05:20 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
	<item>
		<title>By: youngnh</title>
		<link>http://twoguysarguing.wordpress.com/2010/07/26/7-rules-for-writing-clojure-programs/#comment-690</link>
		<dc:creator><![CDATA[youngnh]]></dc:creator>
		<pubDate>Tue, 28 Aug 2012 14:58:03 +0000</pubDate>
		<guid isPermaLink="false">http://twoguysarguing.wordpress.com/?p=746#comment-690</guid>
		<description><![CDATA[I&#039;m a big fan of this notation. It is almost immediately apparent what&#039;s happening because of how little actually happens. It is not hard to keep the whole thing in your head. It is a description of the solution itself, not a long recipe of how to get there. Base case, induction case. No muss, no fuss.

That said, its a bit of a trip to translate a definition like that into Clojure. The language provides (just about) everything you need to do so efficiently, but, well, see for yourself if you like where this ends up.

Here&#039;s the closest expression of the initial definition as I could make it as a simple recursive fn
[sourcecode language=&quot;clojure&quot;]
(defn Freqs [[x &amp; ys :as coll] c]
  (cond
   (empty? coll) 0
   (= x c) (inc (Freqs ys c))
   :else (Freqs ys c)))
[/sourcecode]

That definition will compute the entirety of Freqs every time you ask for c. It can avoid the repeated work by memoizing an anonymous function.
[sourcecode language=&quot;clojure&quot;]
(defn fix [f]
  ((fn [makef]
     (fn [&amp; args]
       (apply f (makef makef) args)))
   (fn [makef]
     (fn [&amp; args]
       (apply f (makef makef) args)))))

(def Freqs
  (memoize (fix (fn [recurse [x &amp; ys :as coll] c]
                  (cond
                   (empty? coll) 0
                   (= x c) (inc (recurse ys c))
                   :else (recurse ys c))))))
[/sourcecode]

Thankfully, Clojure lets you name anonymous functions so that you don&#039;t have to resort to a fixed-point combinator.
[sourcecode language=&quot;clojure&quot;]
(def Freqs
  (memoize (fn thisfn [[x &amp; ys :as coll] c]
             (cond
              (empty? coll) 0
              (= x c) (inc (thisfn ys c))
              :else (thisfn ys c)))))
[/sourcecode]

This solution still consumes stack every time we recurse and will be unable to compute Freqs on very large seqs.
[sourcecode language=&quot;clojure&quot;]
(Freqs (take 10000 (repeatedly #(rand-int 10))) 7)
=&gt; StackOverflowError
[/sourcecode]

To get around that, we can use Clojure&#039;s `trampoline` to the mix to solve it in this style.
[sourcecode language=&quot;clojure&quot;]
(defn sequentially [thunk f]
  (if (fn? thunk)
    (fn [] (sequentially (thunk) f))
    (f thunk)))

(def Freqs
  (memoize (fn [coll c]
             (trampoline
              (fn thisfn [[x &amp; ys :as coll] c]
                (cond
                 (empty? coll) 0
                 (= x c) (sequentially (fn [] (thisfn ys c)) inc)
                 :else (fn [] (thisfn ys c))))
              coll c))))
[/sourcecode]

However, we&#039;re still left computing the whole of Freqs for every unique c that we pass to the function. I believe that&#039;s still true even if we write this solution in Haskell, which will result in code that looks virtually identical to your mathematical notation and doesn&#039;t have to manually perform the memoization and trampolining backflips above But, if you only use the function once then maybe the increased readability is worth the performance hit

If you&#039;re interested in a solution that clearly communicates the idea behind the solution, use the mathematical notation, but if you want to run this code, take the advice of commenters above and use &lt;code&gt;clojure.core/frequencies&lt;/code&gt;.]]></description>
		<content:encoded><![CDATA[<p>I&#8217;m a big fan of this notation. It is almost immediately apparent what&#8217;s happening because of how little actually happens. It is not hard to keep the whole thing in your head. It is a description of the solution itself, not a long recipe of how to get there. Base case, induction case. No muss, no fuss.</p>
<p>That said, its a bit of a trip to translate a definition like that into Clojure. The language provides (just about) everything you need to do so efficiently, but, well, see for yourself if you like where this ends up.</p>
<p>Here&#8217;s the closest expression of the initial definition as I could make it as a simple recursive fn</p>
<pre class="brush: clojure; title: ; notranslate">
(defn Freqs [[x &amp; ys :as coll] c]
  (cond
   (empty? coll) 0
   (= x c) (inc (Freqs ys c))
   :else (Freqs ys c)))
</pre>
<p>That definition will compute the entirety of Freqs every time you ask for c. It can avoid the repeated work by memoizing an anonymous function.</p>
<pre class="brush: clojure; title: ; notranslate">
(defn fix [f]
  ((fn [makef]
     (fn [&amp; args]
       (apply f (makef makef) args)))
   (fn [makef]
     (fn [&amp; args]
       (apply f (makef makef) args)))))

(def Freqs
  (memoize (fix (fn [recurse [x &amp; ys :as coll] c]
                  (cond
                   (empty? coll) 0
                   (= x c) (inc (recurse ys c))
                   :else (recurse ys c))))))
</pre>
<p>Thankfully, Clojure lets you name anonymous functions so that you don&#8217;t have to resort to a fixed-point combinator.</p>
<pre class="brush: clojure; title: ; notranslate">
(def Freqs
  (memoize (fn thisfn [[x &amp; ys :as coll] c]
             (cond
              (empty? coll) 0
              (= x c) (inc (thisfn ys c))
              :else (thisfn ys c)))))
</pre>
<p>This solution still consumes stack every time we recurse and will be unable to compute Freqs on very large seqs.</p>
<pre class="brush: clojure; title: ; notranslate">
(Freqs (take 10000 (repeatedly #(rand-int 10))) 7)
=&gt; StackOverflowError
</pre>
<p>To get around that, we can use Clojure&#8217;s `trampoline` to the mix to solve it in this style.</p>
<pre class="brush: clojure; title: ; notranslate">
(defn sequentially [thunk f]
  (if (fn? thunk)
    (fn [] (sequentially (thunk) f))
    (f thunk)))

(def Freqs
  (memoize (fn [coll c]
             (trampoline
              (fn thisfn [[x &amp; ys :as coll] c]
                (cond
                 (empty? coll) 0
                 (= x c) (sequentially (fn [] (thisfn ys c)) inc)
                 :else (fn [] (thisfn ys c))))
              coll c))))
</pre>
<p>However, we&#8217;re still left computing the whole of Freqs for every unique c that we pass to the function. I believe that&#8217;s still true even if we write this solution in Haskell, which will result in code that looks virtually identical to your mathematical notation and doesn&#8217;t have to manually perform the memoization and trampolining backflips above But, if you only use the function once then maybe the increased readability is worth the performance hit</p>
<p>If you&#8217;re interested in a solution that clearly communicates the idea behind the solution, use the mathematical notation, but if you want to run this code, take the advice of commenters above and use <code>clojure.core/frequencies</code>.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: thehotelambush</title>
		<link>http://twoguysarguing.wordpress.com/2010/07/26/7-rules-for-writing-clojure-programs/#comment-688</link>
		<dc:creator><![CDATA[thehotelambush]]></dc:creator>
		<pubDate>Sat, 18 Aug 2012 01:44:57 +0000</pubDate>
		<guid isPermaLink="false">http://twoguysarguing.wordpress.com/?p=746#comment-688</guid>
		<description><![CDATA[Just mathematically, this problem is easy to express recursively:

Freqs(())[c] = 0

Freqs(x.ys)[c] = Freqs(ys)[c] + (1 if x = c else 0).

Don&#039;t underestimate the power of recursion.

Even when you&#039;re not using it explicitly, you are probably using some built-in function which does (e.g. reduce).]]></description>
		<content:encoded><![CDATA[<p>Just mathematically, this problem is easy to express recursively:</p>
<p>Freqs(())[c] = 0</p>
<p>Freqs(x.ys)[c] = Freqs(ys)[c] + (1 if x = c else 0).</p>
<p>Don&#8217;t underestimate the power of recursion.</p>
<p>Even when you&#8217;re not using it explicitly, you are probably using some built-in function which does (e.g. reduce).</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: 7 Rules for Clojure</title>
		<link>http://twoguysarguing.wordpress.com/2010/07/26/7-rules-for-writing-clojure-programs/#comment-686</link>
		<dc:creator><![CDATA[7 Rules for Clojure]]></dc:creator>
		<pubDate>Tue, 14 Aug 2012 02:17:58 +0000</pubDate>
		<guid isPermaLink="false">http://twoguysarguing.wordpress.com/?p=746#comment-686</guid>
		<description><![CDATA[[...] http://twoguysarguing.wordpress.com/2010/07/26/7-rules-for-writing-clojure-programs/ [...]]]></description>
		<content:encoded><![CDATA[<p>[...] <a href="http://twoguysarguing.wordpress.com/2010/07/26/7-rules-for-writing-clojure-programs/" rel="nofollow">http://twoguysarguing.wordpress.com/2010/07/26/7-rules-for-writing-clojure-programs/</a> [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Blogs From The Geeks &#187; Blog Archive &#187; Karate Chop Kata and coding practices in Clojure (part 1) - Intermittent insightful nuggets</title>
		<link>http://twoguysarguing.wordpress.com/2010/07/26/7-rules-for-writing-clojure-programs/#comment-656</link>
		<dc:creator><![CDATA[Blogs From The Geeks &#187; Blog Archive &#187; Karate Chop Kata and coding practices in Clojure (part 1) - Intermittent insightful nuggets]]></dc:creator>
		<pubDate>Mon, 30 Jan 2012 10:14:18 +0000</pubDate>
		<guid isPermaLink="false">http://twoguysarguing.wordpress.com/?p=746#comment-656</guid>
		<description><![CDATA[[...] that will make more sense closer near the end of this post,  everything should be immutable - here is a good read about some best practices with [...]]]></description>
		<content:encoded><![CDATA[<p>[...] that will make more sense closer near the end of this post,  everything should be immutable - here is a good read about some best practices with [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: flashuac</title>
		<link>http://twoguysarguing.wordpress.com/2010/07/26/7-rules-for-writing-clojure-programs/#comment-610</link>
		<dc:creator><![CDATA[flashuac]]></dc:creator>
		<pubDate>Mon, 02 May 2011 22:07:58 +0000</pubDate>
		<guid isPermaLink="false">http://twoguysarguing.wordpress.com/?p=746#comment-610</guid>
		<description><![CDATA[Very interesting post! :)]]></description>
		<content:encoded><![CDATA[<p>Very interesting post! :)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: youngnh</title>
		<link>http://twoguysarguing.wordpress.com/2010/07/26/7-rules-for-writing-clojure-programs/#comment-499</link>
		<dc:creator><![CDATA[youngnh]]></dc:creator>
		<pubDate>Thu, 30 Dec 2010 13:45:33 +0000</pubDate>
		<guid isPermaLink="false">http://twoguysarguing.wordpress.com/?p=746#comment-499</guid>
		<description><![CDATA[good catch, I fixed the spacing for that code snippet]]></description>
		<content:encoded><![CDATA[<p>good catch, I fixed the spacing for that code snippet</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Horst</title>
		<link>http://twoguysarguing.wordpress.com/2010/07/26/7-rules-for-writing-clojure-programs/#comment-498</link>
		<dc:creator><![CDATA[Horst]]></dc:creator>
		<pubDate>Wed, 29 Dec 2010 11:34:32 +0000</pubDate>
		<guid isPermaLink="false">http://twoguysarguing.wordpress.com/?p=746#comment-498</guid>
		<description><![CDATA[youngnh,

you should properly format the code under rule #1. The &quot;(let&quot; line needs to have the same indentation as the last line that starts with &quot;counts&quot;, otherwise it&#039;s hard to recognize as the 2 branches of the if-not.]]></description>
		<content:encoded><![CDATA[<p>youngnh,</p>
<p>you should properly format the code under rule #1. The &#8220;(let&#8221; line needs to have the same indentation as the last line that starts with &#8220;counts&#8221;, otherwise it&#8217;s hard to recognize as the 2 branches of the if-not.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: John Lawrence Aspden</title>
		<link>http://twoguysarguing.wordpress.com/2010/07/26/7-rules-for-writing-clojure-programs/#comment-240</link>
		<dc:creator><![CDATA[John Lawrence Aspden]]></dc:creator>
		<pubDate>Sun, 05 Sep 2010 22:00:22 +0000</pubDate>
		<guid isPermaLink="false">http://twoguysarguing.wordpress.com/?p=746#comment-240</guid>
		<description><![CDATA[(sort-by second (frequencies &quot;abcdaabccc&quot;))]]></description>
		<content:encoded><![CDATA[<p>(sort-by second (frequencies &#8220;abcdaabccc&#8221;))</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Top Posts &#8212; WordPress.com</title>
		<link>http://twoguysarguing.wordpress.com/2010/07/26/7-rules-for-writing-clojure-programs/#comment-206</link>
		<dc:creator><![CDATA[Top Posts &#8212; WordPress.com]]></dc:creator>
		<pubDate>Wed, 28 Jul 2010 00:08:24 +0000</pubDate>
		<guid isPermaLink="false">http://twoguysarguing.wordpress.com/?p=746#comment-206</guid>
		<description><![CDATA[[...]  7 Rules for Writing Clojure Programs Over the past 5 months, I&#8217;ve had the incredible opportunity at Revelytix to write Clojure every day and get paid [...] [...]]]></description>
		<content:encoded><![CDATA[<p>[...]  7 Rules for Writing Clojure Programs Over the past 5 months, I&#8217;ve had the incredible opportunity at Revelytix to write Clojure every day and get paid [...] [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Dave F.</title>
		<link>http://twoguysarguing.wordpress.com/2010/07/26/7-rules-for-writing-clojure-programs/#comment-205</link>
		<dc:creator><![CDATA[Dave F.]]></dc:creator>
		<pubDate>Tue, 27 Jul 2010 18:47:39 +0000</pubDate>
		<guid isPermaLink="false">http://twoguysarguing.wordpress.com/?p=746#comment-205</guid>
		<description><![CDATA[As some folks on Hacker News noticed, -&gt;&gt; is there to reduce errors. Please note in the #7 example that you erroneously use &quot;a&quot; instead of &quot;b&quot; in your computation of &quot;c&quot;.

The threading ops make this kind of error impossible, while maintaining code clarity. Not using them is a big mistake. They exist to reduce errors, reduce excess typing, and signal to code readers that a transformation is taking place. Not using them due to dogma is a mistake.]]></description>
		<content:encoded><![CDATA[<p>As some folks on Hacker News noticed, -&gt;&gt; is there to reduce errors. Please note in the #7 example that you erroneously use &#8220;a&#8221; instead of &#8220;b&#8221; in your computation of &#8220;c&#8221;.</p>
<p>The threading ops make this kind of error impossible, while maintaining code clarity. Not using them is a big mistake. They exist to reduce errors, reduce excess typing, and signal to code readers that a transformation is taking place. Not using them due to dogma is a mistake.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
