<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The next 10,000 hours</title>
	<atom:link href="http://www.trouble.net.au/blog/korny/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.trouble.net.au/blog/korny</link>
	<description>Korny&#039;s tech blog</description>
	<lastBuildDate>Sat, 04 Jun 2011 01:07:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>10 Clojure one liners&#8230;</title>
		<link>http://www.trouble.net.au/blog/korny/2011/06/03/10-clojure-one-liners/</link>
		<comments>http://www.trouble.net.au/blog/korny/2011/06/03/10-clojure-one-liners/#comments</comments>
		<pubDate>Fri, 03 Jun 2011 05:16:28 +0000</pubDate>
		<dc:creator>korny</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.trouble.net.au/blog/korny/?p=224</guid>
		<description><![CDATA[After the original 10 Scala one liners to impress your friends, and 10 CofeeScript one liners and 10 Ruby one liners, I thought I&#8217;d do the same in clojure &#8211; mostly as I&#8217;m playing with clojure at the moment and thought it&#8217;d be fun &#8211; I&#8217;m sure someone else has probably already done this! Note [...]]]></description>
			<content:encoded><![CDATA[<p>After the original <a href="http://solog.co/47/10-scala-one-liners-to-impress-your-friends/">10 Scala one liners to impress your friends</a>, and <a href="http://ricardo.cc/2011/06/02/10-CoffeeScript-One-Liners-to-Impress-Your-Friends.html">10 CofeeScript one liners</a> and <a href="http://programmingzen.com/2011/06/02/10-ruby-one-liners-to-impress-your-friends/">10 Ruby one liners</a>, I thought I&#8217;d do the same in <a href="http://clojure.org">clojure</a> &#8211; mostly as I&#8217;m playing with clojure at the moment and thought it&#8217;d be fun &#8211; I&#8217;m sure someone else has probably already done this!<br />
<span id="more-224"></span><br />
<i>Note</i> some of these are a bit unusual, as I&#8217;ve attempted to copy the original Scala solutions &#8211; so for example you might use <code>(range 10)</code> rather than <code>(range 1 10)</code> &#8211; but that&#8217;d give you [0,1,2,3,4,5,6,7,8,9] not [1,2,3,4,5,6,7,8,9,10] &#8211; so I&#8217;ve stuck with the original code.</p>
<h3>1. Multiply each item in a list by 2</h3>
<p><div id="gist-1005855" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="p">(</span><span class="nf">map</span><span class="w"> </span><span class="o">#</span><span class="p">(</span><span class="nf">*</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="nv">%</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nf">range</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="mi">10</span><span class="p">))</span><span class="w"></span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1005855/19fdae106801e8c74d61c48b4a61030a6d37af9a/one.clj" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1005855#file_one.clj" style="float:right;margin-right:10px;color:#666">one.clj</a>
            <a href="https://gist.github.com/1005855">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
<br />
This just maps an anonymous function &#8220;#(* 2 %)&#8221; &#8211; basically the &#8220;times two&#8221; function &#8211; across the list.</p>
<h3>2. Sum a list of numbers</h3>
<p><div id="gist-1005855" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="p">(</span><span class="nf">reduce</span><span class="w"> </span><span class="nv">+</span><span class="w"> </span><span class="p">(</span><span class="nf">range</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="mi">1000</span><span class="p">))</span><span class="w"></span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1005855/ea33fbca9e2ef7b4442269d074082b92ea450c4f/two.clj" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1005855#file_two.clj" style="float:right;margin-right:10px;color:#666">two.clj</a>
            <a href="https://gist.github.com/1005855">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
<br />
This is very simple &#8211; &#8220;reduce&#8221; takes the function &#8220;+&#8221; (yes, &#8220;+&#8221; is a function in clojure) and repeatedly applies it to the list, accumulating the result as it goes.</p>
<h3>3. Verify if exists in a string</h3>
<p><div id="gist-1005855" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="p">(</span><span class="nf">def</span><span class="w"> </span><span class="nv">words</span><span class="w"> </span><span class="p">[</span><span class="s">&quot;clojure&quot;</span><span class="w">, </span><span class="s">&quot;stm&quot;</span><span class="w">, </span><span class="s">&quot;compojure&quot;</span><span class="w">, </span><span class="s">&quot;leiningen&quot;</span><span class="w">, </span><span class="s">&quot;clojure.core&quot;</span><span class="p">])</span><span class="w"></span></div><div class='line' id='LC2'><span class="p">(</span><span class="nf">def</span><span class="w"> </span><span class="nv">tweet</span><span class="w"> </span><span class="s">&quot;This is an example tweet talking about clojure and leiningen.&quot;</span><span class="p">)</span><span class="w"></span></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'><span class="c1">; 3a</span><span class="w"></span></div><div class='line' id='LC5'><span class="p">(</span><span class="nf">reduce</span><span class="w"> </span><span class="o">#</span><span class="p">(</span><span class="nf">or</span><span class="w"> </span><span class="nv">%1</span><span class="w"> </span><span class="p">(</span><span class="nf">.contains</span><span class="w"> </span><span class="nv">tweet</span><span class="w"> </span><span class="nv">%2</span><span class="p">))</span><span class="w"> </span><span class="nv">false</span><span class="w"> </span><span class="nv">words</span><span class="p">)</span><span class="w"></span></div><div class='line' id='LC6'><br/></div><div class='line' id='LC7'><span class="c1">; 3b</span><span class="w"></span></div><div class='line' id='LC8'><span class="p">(</span><span class="nf">some</span><span class="w"> </span><span class="o">#</span><span class="p">(</span><span class="nf">.contains</span><span class="w"> </span><span class="nv">tweet</span><span class="w"> </span><span class="nv">%</span><span class="p">)</span><span class="w"> </span><span class="nv">words</span><span class="p">)</span><span class="w"></span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1005855/172d245c9f8a2ef46f863a9c1876d367cbcd6382/three.clj" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1005855#file_three.clj" style="float:right;margin-right:10px;color:#666">three.clj</a>
            <a href="https://gist.github.com/1005855">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
<br />
Note that example 3a mimics the original ugly scala &#8211; you can do this better using &#8216;some&#8217; as in example 3b.  &#8220;some&#8221; is like &#8220;any?&#8221; in ruby or &#8220;exists&#8221; in scala &#8211; it tests the &#8220;contains&#8221; function against every word in &#8220;words&#8221;, and returns as soon as any of them returns true.</p>
<p>This is still ugly in that it uses String.contains whereas it really should split the string into word tokens &#8211; I&#8217;ll leave that as an exercise for the reader.</p>
<h3>4. Read in a file</h3>
<p><div id="gist-1005855" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="p">(</span><span class="nf">ns</span><span class="w"> </span><span class="nv">ten</span><span class="w"></span></div><div class='line' id='LC2'><span class="w">  </span><span class="p">(</span><span class="no">:require</span><span class="w"></span></div><div class='line' id='LC3'><span class="w">    </span><span class="p">[</span><span class="nv">clojure.java.io</span><span class="w"> </span><span class="no">:as</span><span class="w"> </span><span class="nv">io</span><span class="p">]))</span><span class="w"></span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'><span class="c1">; 4a</span><span class="w"></span></div><div class='line' id='LC6'><span class="p">(</span><span class="nf">slurp</span><span class="w"> </span><span class="s">&quot;data.txt&quot;</span><span class="p">)</span><span class="w"></span></div><div class='line' id='LC7'><br/></div><div class='line' id='LC8'><span class="c1">; 4b</span><span class="w"></span></div><div class='line' id='LC9'><span class="p">(</span><span class="nf">take</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="p">(</span><span class="nf">line-seq</span><span class="w"> </span><span class="p">(</span><span class="nf">io/reader</span><span class="w"> </span><span class="s">&quot;data.txt&quot;</span><span class="p">)))</span><span class="w"></span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'><span class="c1">; 4c</span><span class="w"></span></div><div class='line' id='LC12'><span class="p">(</span><span class="nf">with-open</span><span class="w"> </span><span class="p">[</span><span class="nv">rdr</span><span class="w"> </span><span class="p">(</span><span class="nf">io/reader</span><span class="w"> </span><span class="s">&quot;http://oldweb.cecm.sfu.ca/projects/ISC/dataB/isc/C/pi10000.txt&quot;</span><span class="p">)]</span><span class="w"> </span><span class="p">(</span><span class="nf">take</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="p">(</span><span class="nf">line-seq</span><span class="w"> </span><span class="nv">rdr</span><span class="p">)))</span><span class="w"></span></div><div class='line' id='LC13'><br/></div><div class='line' id='LC14'><span class="c1">; 4d</span><span class="w"></span></div><div class='line' id='LC15'><span class="p">(</span><span class="nf">with-open</span><span class="w"> </span><span class="p">[</span><span class="nv">rdr</span><span class="w"> </span><span class="p">(</span><span class="nf">io/reader</span><span class="w"> </span><span class="s">&quot;http://oldweb.cecm.sfu.ca/projects/ISC/dataB/isc/C/pi10000.txt&quot;</span><span class="p">)]</span><span class="w"> </span><span class="p">(</span><span class="nf">doall</span><span class="w"> </span><span class="p">(</span><span class="nf">take</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="p">(</span><span class="nf">line-seq</span><span class="w"> </span><span class="nv">rdr</span><span class="p">))))</span><span class="w"></span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1005855/0d596268d6625cc2dbc405d76951aa81d884da30/four.clj" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1005855#file_four.clj" style="float:right;margin-right:10px;color:#666">four.clj</a>
            <a href="https://gist.github.com/1005855">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
<br />
The first example is simple &#8211; it just reads a whole file using the &#8216;slurp&#8217; function.  This will do for 99% of applications.</p>
<p>However for a bigger file, it&#8217;s good to use clojure&#8217;s innate laziness &#8211; 4b reads *only* the first 3 lines of the file, if you don&#8217;t need the rest, it doesn&#8217;t read it.</p>
<p>Unfortunately, we never close the file handle in 4b, which is a bad thing to do.  4c uses &#8216;with-open&#8217; to read a large file, and then close it once we&#8217;re done &#8211; much safer, but sadly this throws an IOException &#8211; because of clojure&#8217;s laziness.  The &#8216;(take 3 (line-seq rdr))&#8217; function is evaluated lazily, when the &#8220;println&#8221; function is called &#8211; by which time, the file handle is closed!</p>
<p>So 4d calls &#8216;doall&#8217; which forces the sequence to be evaluated immediately.  This is getting a bit long for a one-liner &#8211; but it&#8217;s very flexible; it only reads as many lines as are needed, which for large files or other streams, is extremely useful.</p>
<h3>5. Happy birthday!</h3>
<p><div id="gist-1005855" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="c1">; 5a</span><span class="w"></span></div><div class='line' id='LC2'><span class="p">(</span><span class="nf">map</span><span class="w"> </span><span class="o">#</span><span class="p">(</span><span class="nf">str</span><span class="w"> </span><span class="s">&quot;Happy Birthday &quot;</span><span class="w"> </span><span class="p">(</span><span class="nf">if</span><span class="w"> </span><span class="p">(</span><span class="nf">=</span><span class="w"> </span><span class="nv">%</span><span class="w"> </span><span class="mi">3</span><span class="p">)</span><span class="w"> </span><span class="s">&quot;dear NAME&quot;</span><span class="w"> </span><span class="s">&quot;to You&quot;</span><span class="p">))</span><span class="w"> </span><span class="p">(</span><span class="nf">range</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="mi">4</span><span class="p">))</span><span class="w"></span></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'><span class="c1">; 5b</span><span class="w"></span></div><div class='line' id='LC5'><span class="p">(</span><span class="nf">for</span><span class="w"> </span><span class="p">[</span><span class="nv">x</span><span class="w"> </span><span class="p">(</span><span class="nf">range</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="mi">5</span><span class="p">)]</span><span class="w"> </span><span class="p">(</span><span class="nf">println</span><span class="w"> </span><span class="p">(</span><span class="nf">str</span><span class="w"> </span><span class="s">&quot;Happy Birthday &quot;</span><span class="w"> </span><span class="p">(</span><span class="nf">if</span><span class="w"> </span><span class="p">(</span><span class="nf">=</span><span class="w"> </span><span class="nv">x</span><span class="w"> </span><span class="mi">3</span><span class="p">)</span><span class="w"> </span><span class="s">&quot;dear NAME&quot;</span><span class="w"> </span><span class="s">&quot;to You&quot;</span><span class="p">))))</span><span class="w"></span></div><div class='line' id='LC6'><br/></div><div class='line' id='LC7'><span class="c1">; 5c</span><span class="w"></span></div><div class='line' id='LC8'><span class="p">(</span><span class="nf">doseq</span><span class="w"> </span><span class="p">[</span><span class="nv">x</span><span class="w"> </span><span class="p">(</span><span class="nf">range</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="mi">5</span><span class="p">)]</span><span class="w"> </span><span class="p">(</span><span class="nf">println</span><span class="w"> </span><span class="p">(</span><span class="nf">str</span><span class="w"> </span><span class="s">&quot;Happy Birthday &quot;</span><span class="w"> </span><span class="p">(</span><span class="nf">if</span><span class="w"> </span><span class="p">(</span><span class="nf">=</span><span class="w"> </span><span class="nv">x</span><span class="w"> </span><span class="mi">3</span><span class="p">)</span><span class="w"> </span><span class="s">&quot;dear NAME&quot;</span><span class="w"> </span><span class="s">&quot;to You&quot;</span><span class="p">))))</span><span class="w"></span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1005855/5601efcd1dc7a3daadf3345869dec5d1b1575d1f/five.clj" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1005855#file_five.clj" style="float:right;margin-right:10px;color:#666">five.clj</a>
            <a href="https://gist.github.com/1005855">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
<br />
5a mimics the scala code &#8211; it uses &#8216;map&#8217;, which is a bit ugly when looping over  a range.</p>
<p>5b uses &#8216;for&#8217;, which is much clearer for most folks.  The only trouble in this example is that &#8216;for&#8217; actually returns a list of values, so calling 5b results in the output:</p>
<pre>
5b: (Happy Birthday to You
Happy Birthday to You
Happy Birthday dear NAME
Happy Birthday to You
nil nil nil nil)</pre>
<p>5c uses &#8216;doseq&#8217; which has a syntax just like &#8216;for&#8217; but just calls the side effects of the loop (i.e. the &#8220;println&#8221; functions) and ignores the result. So the output is:</p>
<pre>Happy Birthday to You
Happy Birthday to You
Happy Birthday dear NAME
Happy Birthday to You
5c: nil</pre>
<h3>6. Filter list of numbers</h3>
<p><div id="gist-1005855" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="p">(</span><span class="nf">group-by</span><span class="w"> </span><span class="o">#</span><span class="p">(</span><span class="nf">if</span><span class="w"> </span><span class="p">(</span><span class="nf">&gt;</span><span class="w"> </span><span class="nv">%</span><span class="w"> </span><span class="mi">60</span><span class="p">)</span><span class="w"> </span><span class="no">:passed</span><span class="w"> </span><span class="no">:failed</span><span class="p">)</span><span class="w"> </span><span class="p">[</span><span class="mi">49</span><span class="w">, </span><span class="mi">58</span><span class="w">, </span><span class="mi">76</span><span class="w">, </span><span class="mi">82</span><span class="w">, </span><span class="mi">88</span><span class="w">, </span><span class="mi">90</span><span class="p">])</span><span class="w"></span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1005855/59697e2cbdaea96c2dd1736c22f9d5ce206d3144/six.clj" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1005855#file_six.clj" style="float:right;margin-right:10px;color:#666">six.clj</a>
            <a href="https://gist.github.com/1005855">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
<br />
This is pretty simple.  It calls &#8220;group-by&#8221; on the list, grouping it by the anonymous function that turns each score into :passed or :failed. The output is:</p>
<pre>6: {:failed [49 58], :passed [76 82 88 90]}</pre>
<p>Note that clojure has a &#8216;partition-by&#8217; function similar to scala&#8217;s &#8216;partition&#8217;, but with a subtly different behaviour &#8211; it will start a new list every time a function changes, so <code>(partition-by #(&gt; % 60) [49, 58, 76, 82, 88, 90, 33])</code> gets messed up by the final number, resulting in &#8220;((49 58) (76 82 88 90) (33))&#8221;.  Group-by matches the original requirements better.</p>
<h3>7. Fetch and parse an xml feed</h3>
<p><div id="gist-1005855" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="p">(</span><span class="nf">ns</span><span class="w"> </span><span class="nv">ten</span><span class="w"></span></div><div class='line' id='LC2'><span class="w">  </span><span class="p">(</span><span class="no">:require</span><span class="w"></span></div><div class='line' id='LC3'><span class="w">    </span><span class="p">[</span><span class="nv">clojure.xml</span><span class="p">]))</span><span class="w"></span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'><span class="p">(</span><span class="nf">clojure.xml/parse</span><span class="w"> </span><span class="s">&quot;http://search.twitter.com/search.atom?&amp;q=clojure&quot;</span><span class="p">)</span><span class="w"></span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1005855/77423ac61aded426ba258d4f2881afcb52d206e8/seven.clj" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1005855#file_seven.clj" style="float:right;margin-right:10px;color:#666">seven.clj</a>
            <a href="https://gist.github.com/1005855">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
<br />
results in a big structure, starting &#8220;{:tag :feed, :attrs {:xmlns:google http://base.google.com/ns/1.0&#8230;&#8221; &#8211; from there on, it&#8217;s pretty easy to use clojure commands like xml-seq to lazily parse the xml feed.</p>
<h3>8. Find minimum in a list</h3>
<p><div id="gist-1005855" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="c1">; 8a</span><span class="w"></span></div><div class='line' id='LC2'><span class="p">(</span><span class="nf">reduce</span><span class="w"> </span><span class="nv">min</span><span class="w"> </span><span class="p">[</span><span class="mi">14</span><span class="w">, </span><span class="mi">35</span><span class="w">, </span><span class="mi">-7</span><span class="w">, </span><span class="mi">46</span><span class="w">, </span><span class="mi">98</span><span class="p">])</span><span class="w"></span></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'><span class="c1">; 8b</span><span class="w"></span></div><div class='line' id='LC5'><span class="p">(</span><span class="nf">min</span><span class="w"> </span><span class="mi">14</span><span class="w"> </span><span class="mi">35</span><span class="w"> </span><span class="mi">-7</span><span class="w"> </span><span class="mi">46</span><span class="w"> </span><span class="mi">98</span><span class="p">)</span><span class="w"></span></div><div class='line' id='LC6'><br/></div><div class='line' id='LC7'><span class="c1">; 8c</span><span class="w"></span></div><div class='line' id='LC8'><span class="p">(</span><span class="nf">apply</span><span class="w"> </span><span class="nv">min</span><span class="w"> </span><span class="p">[</span><span class="mi">14</span><span class="w">, </span><span class="mi">35</span><span class="w">, </span><span class="mi">-7</span><span class="w">, </span><span class="mi">46</span><span class="w">, </span><span class="mi">98</span><span class="p">])</span><span class="w"></span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1005855/9ecc037c98dca5b01afb482e2c1d13dd948c7cfd/eight.clj" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1005855#file_eight.clj" style="float:right;margin-right:10px;color:#666">eight.clj</a>
            <a href="https://gist.github.com/1005855">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
<br />
8a follows the original Scala code.  It&#8217;s a bit wasteful &#8211; it uses &#8216;reduce&#8217; to run &#8216;min&#8217; repeatedly over every pair of numbers in the list.</p>
<p>8b is better &#8211; the &#8220;min&#8221; function can take multiple arguments, and finds the minimum of all of them.</p>
<p>If you have an array already, you can use &#8216;apply&#8217; to pass the array as parameters to &#8216;min&#8217;, as in 8c.</p>
<h3>9. Parallel processing</h3>
<p><div id="gist-1005855" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="p">(</span><span class="nf">ns</span><span class="w"> </span><span class="nv">ten</span><span class="w"></span></div><div class='line' id='LC2'><span class="w">  </span><span class="p">(</span><span class="no">:require</span><span class="w"></span></div><div class='line' id='LC3'><span class="w">    </span><span class="p">[</span><span class="nv">clojure.java.io</span><span class="w"> </span><span class="no">:as</span><span class="w"> </span><span class="nv">io</span><span class="p">]))</span><span class="w"></span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'><span class="p">(</span><span class="nf">pmap</span><span class="w"> </span><span class="o">#</span><span class="p">(</span><span class="nf">count</span><span class="w"> </span><span class="nv">%</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nf">line-seq</span><span class="w"> </span><span class="p">(</span><span class="nf">io/reader</span><span class="w"> </span><span class="s">&quot;http://oldweb.cecm.sfu.ca/projects/ISC/dataB/isc/C/pi10000.txt&quot;</span><span class="p">)))</span><span class="w"></span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1005855/71ebee11402943565976f9609616bcdf24140831/nine.clj" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1005855#file_nine.clj" style="float:right;margin-right:10px;color:#666">nine.clj</a>
            <a href="https://gist.github.com/1005855">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
<br />
This is where clojure really shines.  &#8216;pmap&#8217; will map a function across a sequence, semi-lazily, and in parallel.  It actually only launches one thread per CPU on your system, so it&#8217;s designed for CPU intensive functions &#8211; if you want to do other kinds of multi-threaded operation, there&#8217;s <a href="http://clojure.org/concurrent_programming">no shortage of ways</a> to do this in clojure.</p>
<h3>10. Sieve of Eratosthenes</h3>
<p>Clojure is very big on laziness&#8230; and I&#8217;m feeling to lazy to re-implement the Sieve in a one-liner.  I&#8217;m sure it could be done!  In the meantime, I&#8217;ll point you to cgrand&#8217;s <a href="http://clj-me.cgrand.net/2009/07/30/everybody-loves-the-sieve-of-eratosthenes/">great article about the Sieve of Eratosthenes in clojure</a>.</p>
<p>Phew &#8211; it was far more work blogging about these than it was solving the problem.</p>
<p>If you want more clojure, I recently wrote <a href="https://github.com/kornysietsma/twitter-example">a simple Twitter web app in clojure (and coffeescript)</a> &#8211; I might blog about that in more detail at some stage, but in the meantime there&#8217;s a lot of info <a href="https://github.com/kornysietsma/twitter-example#readme">in the readme</a>.</p>
<p><i>Update</i> &#8211; removed redundant printf statements. sorry!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.trouble.net.au/blog/korny/2011/06/03/10-clojure-one-liners/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>New Job</title>
		<link>http://www.trouble.net.au/blog/korny/2011/06/03/new-job/</link>
		<comments>http://www.trouble.net.au/blog/korny/2011/06/03/new-job/#comments</comments>
		<pubDate>Fri, 03 Jun 2011 03:42:20 +0000</pubDate>
		<dc:creator>korny</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.trouble.net.au/blog/korny/?p=222</guid>
		<description><![CDATA[After five years at my previous workplace (as a consultant, then as a permanent) I finally made the jump to a new job &#8211; I&#8217;m now working for ThoughtWorks! I have a long post all about the career change process that&#8217;s in the &#8220;to be finished&#8221; blog backlog, hopefully some time soon I&#8217;ll get it [...]]]></description>
			<content:encoded><![CDATA[<p>After five years at my previous workplace (as a consultant, then as a permanent) I finally made the jump to a new job &#8211; I&#8217;m now working for <a href="http://thoughtworks.com">ThoughtWorks</a>!<br />
I have a long post all about the career change process that&#8217;s in the &#8220;to be finished&#8221; blog backlog, hopefully some time soon I&#8217;ll get it cleaned up and posted.  But for now, I&#8217;m looking forward to awesome times with the ThoughtWorks crew.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.trouble.net.au/blog/korny/2011/06/03/new-job/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mocking functional code in Scala</title>
		<link>http://www.trouble.net.au/blog/korny/2011/03/27/mocking-functional-code-in-scala/</link>
		<comments>http://www.trouble.net.au/blog/korny/2011/03/27/mocking-functional-code-in-scala/#comments</comments>
		<pubDate>Sat, 26 Mar 2011 23:30:50 +0000</pubDate>
		<dc:creator>korny</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.trouble.net.au/blog/korny/?p=186</guid>
		<description><![CDATA[I&#8217;m having a love-hate relationship with Scala &#8211; it&#8217;s a nifty language with a huge pile of power, and a huge pile of complexity. One of my main problems is that static typing sometimes makes it hard to test without jumping through a lot of hoops. Consider this code: It&#8217;s nice concise code, relatively readable [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m having a love-hate relationship with Scala &#8211; it&#8217;s a nifty language with a huge pile of power, and a huge pile of complexity.</p>
<p>One of my main problems is that static typing sometimes makes it hard to test without jumping through a lot of hoops. Consider this code:</p>
<div id="gist-886660" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'>&nbsp;&nbsp;<span class="k">def</span> <span class="n">ingestAllFromDatabase</span><span class="o">()</span> <span class="o">{</span></div><div class='line' id='LC2'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">solrIngester</span><span class="o">.</span><span class="n">clear</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">personRepository</span><span class="o">.</span><span class="n">foreach</span><span class="o">(</span><span class="n">solrIngester</span><span class="o">.</span><span class="n">addDocument</span><span class="o">(</span><span class="n">_</span><span class="o">))</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">solrIngester</span><span class="o">.</span><span class="n">commit</span><span class="o">()</span></div><div class='line' id='LC5'>&nbsp;&nbsp;<span class="o">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/886660/ce15993f46f650a601342d72eed4c86e975f6929/code.scala" style="float:right;">view raw</a>
            <a href="https://gist.github.com/886660#file_code.scala" style="float:right;margin-right:10px;color:#666">code.scala</a>
            <a href="https://gist.github.com/886660">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>It&#8217;s nice concise code, relatively readable &#8211; this method sets up an ingestor, traverses a database, and for every record in the database it ingests it.  Should be relatively straightforward to unit test, right?<span id="more-186"></span></p>
<p>The trouble is, to properly test it, I&#8217;d like the personRepository and the solrIngester to both be mocked out.  They aren&#8217;t part of the code under test &#8211; they&#8217;re separate classes, and I want to test how the function under test interacts with them.  Specifically, I&#8217;d like to test that the inline function &#8220;solrIngester.addDocument(_)&#8221; is passed to the function &#8220;personRepository.foreach()&#8221;.</p>
<p>(an aside &#8211; yes, this could be structured better. But if you wait to structure your code perfectly before you write any unit tests, it&#8217;s awfully hard to TDD anything&#8230;)</p>
<p>Well, I found a solution:  (Note, we&#8217;re using the Specs test library, with Mockito matchers &#8211; other tools can probably do something similar, somehow, I hope&#8230;)</p>
<div id="gist-886660" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'>&nbsp;&nbsp;<span class="k">def</span> <span class="n">stubForEach</span><span class="o">[</span><span class="kt">T</span><span class="o">](</span><span class="n">list</span><span class="k">:</span> <span class="kt">List</span><span class="o">[</span><span class="kt">T</span><span class="o">])</span><span class="k">:</span> <span class="o">(</span><span class="kt">Any</span><span class="o">)</span> <span class="o">=&gt;</span> <span class="nc">Unit</span> <span class="k">=</span> <span class="o">{</span></div><div class='line' id='LC2'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">providedFunction</span> <span class="k">=&gt;</span> <span class="o">{</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">val</span> <span class="n">function</span> <span class="k">=</span> <span class="n">providedFunction</span><span class="o">.</span><span class="n">asInstanceOf</span><span class="o">[(</span><span class="kt">T</span><span class="o">)</span> <span class="k">=&gt;</span> <span class="kt">Unit</span><span class="o">]</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">list</span><span class="o">.</span><span class="n">foreach</span> <span class="o">{</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">value</span> <span class="k">=&gt;</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">function</span><span class="o">.</span><span class="n">apply</span><span class="o">(</span><span class="n">value</span><span class="o">)</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="o">}</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="o">}</span></div><div class='line' id='LC9'>&nbsp;&nbsp;<span class="o">}</span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'>&nbsp;&nbsp;<span class="s">&quot;Ingestion Manager should&quot;</span> <span class="o">{</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="s">&quot;ingest all people from the database&quot;</span> <span class="n">in</span> <span class="o">{</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">val</span> <span class="n">solrIngester</span> <span class="k">=</span> <span class="n">mock</span><span class="o">[</span><span class="kt">SolrIngester</span><span class="o">]</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">val</span> <span class="n">personRepository</span> <span class="k">=</span> <span class="n">mock</span><span class="o">[</span><span class="kt">PersonRepository</span><span class="o">]</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">val</span> <span class="n">ingestionManager</span> <span class="k">=</span> <span class="k">new</span> <span class="nc">IngestionManager</span><span class="o">(</span><span class="n">ldifLoader</span><span class="o">,</span> <span class="n">solrIngester</span><span class="o">,</span> <span class="n">personRepository</span><span class="o">)</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">val</span> <span class="n">person1</span> <span class="k">=</span> <span class="n">mock</span><span class="o">[</span><span class="kt">Person</span><span class="o">]</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">val</span> <span class="n">person2</span> <span class="k">=</span> <span class="n">mock</span><span class="o">[</span><span class="kt">Person</span><span class="o">]</span></div><div class='line' id='LC18'><br/></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">personRepository</span><span class="o">.</span><span class="n">foreach</span><span class="o">(</span><span class="n">any</span><span class="o">)</span> <span class="n">answers</span> <span class="o">{</span> <span class="n">stubForEach</span><span class="o">(</span><span class="nc">List</span><span class="o">(</span><span class="n">person1</span><span class="o">,</span><span class="n">person2</span><span class="o">))</span> <span class="o">}</span></div><div class='line' id='LC20'><br/></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">ingestionManager</span><span class="o">.</span><span class="n">ingestAllFromDatabase</span></div><div class='line' id='LC22'><br/></div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">there</span> <span class="n">was</span> <span class="n">one</span><span class="o">(</span><span class="n">solrIngester</span><span class="o">).</span><span class="n">clear</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">there</span> <span class="n">was</span> <span class="n">one</span><span class="o">(</span><span class="n">solrIngester</span><span class="o">).</span><span class="n">addDocument</span><span class="o">(</span><span class="n">person1</span><span class="o">)</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">there</span> <span class="n">was</span> <span class="n">one</span><span class="o">(</span><span class="n">solrIngester</span><span class="o">).</span><span class="n">addDocument</span><span class="o">(</span><span class="n">person2</span><span class="o">)</span></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">there</span> <span class="n">was</span> <span class="n">one</span><span class="o">(</span><span class="n">solrIngester</span><span class="o">).</span><span class="n">commit</span></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="o">}</span></div><div class='line' id='LC28'>&nbsp;&nbsp;<span class="o">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/886660/291caef72035f8131b55b12d0889e7bb89ed8158/spec.scala" style="float:right;">view raw</a>
            <a href="https://gist.github.com/886660#file_spec.scala" style="float:right;margin-right:10px;color:#666">spec.scala</a>
            <a href="https://gist.github.com/886660">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>It doesn&#8217;t actually use a matcher for the passed function &#8211; I couldn&#8217;t work out a way to manage that. Instead, it builds a stub function object that behaves like foreach(), but uses a hardcoded list of person objects &#8211; and then gets the mock personRepository object to use the stub function object instead of the real foreach function</p>
<p>This illustrates the good and bad things about Scala.  You couldn&#8217;t do this in Java.  You <em>can</em> do it in Scala.  But it took a while to figure it out &#8211; and even longer to explain it to the rest of the team.  And the test code is longer and (worse) harder to understand than the code under test</p>
<p>After using ruby and rspec for a long time, this just feels like waste.  I&#8217;ve heard static typing fans talking about how it gives you for free, a whole lot of testing you&#8217;d have to do manually in a dynamic language.  But the rest of your testing can be very painful indeed.</p>
<p><strong>Update</strong> &#8211; the ruby/rspec equivalent of the above:<br />
<div id="gist-892082" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="n">describe</span> <span class="no">IngestionManager</span> <span class="k">do</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="n">it</span> <span class="s2">&quot;should ingest all the people from the database&quot;</span> <span class="k">do</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">ingester</span> <span class="o">=</span> <span class="n">mock</span><span class="p">(</span><span class="s1">&#39;ingester&#39;</span><span class="p">)</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">repository</span> <span class="o">=</span> <span class="n">mock</span><span class="p">(</span><span class="s1">&#39;repository&#39;</span><span class="p">)</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">manager</span> <span class="o">=</span> <span class="no">IngestionManager</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">ingester</span><span class="p">,</span> <span class="n">repository</span><span class="p">)</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">person1</span> <span class="o">=</span> <span class="n">mock</span><span class="p">(</span><span class="s1">&#39;person1&#39;</span><span class="p">)</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">person2</span> <span class="o">=</span> <span class="n">mock</span><span class="p">(</span><span class="s1">&#39;person2&#39;</span><span class="p">)</span></div><div class='line' id='LC8'><br/></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">ingester</span><span class="o">.</span><span class="n">should_receive</span> <span class="ss">:clear</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">repository</span><span class="o">.</span><span class="n">should_receive</span><span class="p">(</span><span class="ss">:each</span><span class="p">)</span><span class="o">.</span><span class="n">and_yield</span><span class="p">(</span><span class="n">person1</span><span class="p">)</span><span class="o">.</span><span class="n">and_yield</span><span class="p">(</span><span class="n">person2</span><span class="p">)</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">ingester</span><span class="o">.</span><span class="n">should_receive</span><span class="p">(</span><span class="ss">:addDocument</span><span class="p">)</span><span class="o">.</span><span class="n">with</span><span class="p">(</span><span class="n">person1</span><span class="p">)</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">ingester</span><span class="o">.</span><span class="n">should_receive</span><span class="p">(</span><span class="ss">:addDocument</span><span class="p">)</span><span class="o">.</span><span class="n">with</span><span class="p">(</span><span class="n">person2</span><span class="p">)</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">ingester</span><span class="o">.</span><span class="n">should_receive</span> <span class="ss">:commit</span></div><div class='line' id='LC14'><br/></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">manager</span><span class="o">.</span><span class="n">ingestAllFromDatabase</span></div><div class='line' id='LC16'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC17'><span class="k">end</span></div><div class='line' id='LC18'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/892082/d8ceecc537c9d748119fe9f4d08137407c951842/spec.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/892082#file_spec.rb" style="float:right;margin-right:10px;color:#666">spec.rb</a>
            <a href="https://gist.github.com/892082">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
<br />
see comments below for more.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.trouble.net.au/blog/korny/2011/03/27/mocking-functional-code-in-scala/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>This year</title>
		<link>http://www.trouble.net.au/blog/korny/2011/03/26/this-year/</link>
		<comments>http://www.trouble.net.au/blog/korny/2011/03/26/this-year/#comments</comments>
		<pubDate>Fri, 25 Mar 2011 21:14:40 +0000</pubDate>
		<dc:creator>korny</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.trouble.net.au/blog/korny/?p=189</guid>
		<description><![CDATA[Well, it&#8217;s been almost a year since I&#8217;ve blogged.  It&#8217;s not that nothing bloggable has happened &#8211; it&#8217;s just that too much that is bloggable has happened, and I keep getting caught up with grand ideas of big subjects. I&#8217;ll try a new tack &#8211; post whatever comes up, briefly, and then if I find [...]]]></description>
			<content:encoded><![CDATA[<p>Well, it&#8217;s been almost a year since I&#8217;ve blogged.  It&#8217;s not that nothing bloggable has happened &#8211; it&#8217;s just that <strong>too much</strong> that is bloggable has happened, and I keep getting caught up with grand ideas of big subjects.</p>
<p>I&#8217;ll try a new tack &#8211; post whatever comes up, briefly, and then if I find the time, post a more detailed follow-up.  Maybe that will get the juices flowing again.</p>
<p>A brief summary of the last year:</p>
<ul>
<li>I ran an awesome R&amp;D team &#8211; and we did lots of awesome stuff(tm) &#8211; the source of most of the geekery below, though a fair bit was done in my own time as well</li>
<li>I did a lot of Ruby / Sinatra / Javascript UI building &#8211; it&#8217;s a great way to rapidly develop web apps, though the javascript is growing and the ruby is shrinking these days.  Must find time to do some Node.js</li>
<li>I played a chunk with html5 and css3 &#8211; wonderful changes in the web UI world, that are making pretty sites achievable, without the horror of old-school html</li>
<li>I used a bunch of NoSQL databases, mostly MongoDB &#8211; it&#8217;s a little dodgy in parts, but it&#8217;s an awesomely simple and powerful beast.  And it makes simple app development a dream.</li>
<li>I did some big-data mangling on Amazon EC2 &#8211; EC2 is a wonderful magical kingdom for processing data.  It&#8217;s a pity that corporate masters tend to completely screw it up.</li>
<li>I did a bunch of reading about <a href="http://www.poppendieck.com/">Lean</a>, Agile, <a href="http://agilemanagement.net/index.php/kanbanbook/">Kanban</a>, <a href="http://www.danpink.com/drive">Motivation</a>, <a href="http://www.cs.unca.edu/~manns/intropatterns.html">Change</a>, and just to branch out a bit, Design and Typography.</li>
<li>Most recently, I&#8217;m in a new team that is using Scala.  I&#8217;m growing a complex love-hate relationship with Scala &#8211; I&#8217;ll have to write up my thoughts about it soon.</li>
<li>And I put up a few bits and pieces on <a href="https://github.com/kornysietsma">github</a></li>
</ul>
<p>Phew.  Lots of scope for more posts.  Lets see if I can keep it up!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.trouble.net.au/blog/korny/2011/03/26/this-year/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Face the Face</title>
		<link>http://www.trouble.net.au/blog/korny/2010/04/10/face-the-face/</link>
		<comments>http://www.trouble.net.au/blog/korny/2010/04/10/face-the-face/#comments</comments>
		<pubDate>Fri, 09 Apr 2010 23:02:17 +0000</pubDate>
		<dc:creator>korny</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.trouble.net.au/blog/korny/?p=172</guid>
		<description><![CDATA[I&#8217;ve been playing with new features in html5 recently &#8211; there are lots of things getting a bit of media coverage, but the wider support of embedded fonts really caught my eye. By including an @font-face entry in your css file, and the appropriate font files on a server somewhere, you can get really nice [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been playing with new features in html5 recently &#8211; there are lots of things getting a bit of media coverage, but the wider support of embedded fonts really caught my eye.  By including an @font-face entry in your css file, and the appropriate font files on a server somewhere, you can get really nice typography, without needing to use flash-based hacks like <a href="http://en.wikipedia.org/wiki/Scalable_Inman_Flash_Replacement">sifr</a>,  or newer javascript hacks like <a href="http://cufon.shoqolate.com/">cufon</a></p>
<p><a href="http://cufon.shoqolate.com/"></a><a href="http://www.trouble.net.au/blog/korny/files/2010/04/beautiful_es.png"><img class="aligncenter size-full wp-image-178" title="beautiful_es" src="http://www.trouble.net.au/blog/korny/files/2010/04/beautiful_es.png" alt="" width="291" height="80" /></a> <span id="more-172"></span></p>
<p>(Note, on the usual question of browser support &#8211; check out the <a href="http://webfonts.info/wiki/index.php?title=@font-face_browser_support">webfonts wiki</a> page, or the nifty &#8220;<a href="http://a.deveria.com/caniuse/">When can I use</a>&#8221; page.  The short answer is, @font-face is supported in *all* desktop browsers, as long as you can get a font in the right format.)</p>
<p>Anyway, the point of this post is not to describe how @font-face works &#8211; you can find that information <a href="http://webfonts.info/wiki/index.php?title=What_are_webfonts%3F">all</a> <a href="http://paulirish.com/2009/bulletproof-font-face-implementation-syntax/">over</a> <a href="http://nicewebtype.com/notes/2009/10/30/how-to-use-css-font-face/">the</a> web, and there are <a href="http://www.fontsquirrel.com/">many</a> <a href="http://www.theleagueofmoveabletype.com/">good</a> <a href="http://webfonts.info/wiki/index.php?title=Fonts_available_for_@font-face_embedding">free</a> (and <a href="http://typekit.com/">non-free</a>) fonts out there.</p>
<p><a href="http://www.trouble.net.au/blog/korny/files/2010/04/sniglet.png"><img class="aligncenter size-full wp-image-179" title="sniglet" src="http://www.trouble.net.au/blog/korny/files/2010/04/sniglet.png" alt="" width="557" height="110" /></a></p>
<p>But I did want to point folks to Tim Brown&#8217;s <a href="http://webfontspecimen.com/">Web Font Specimen</a>, a nifty way to look at web fonts.  I found this when trying to wade through a pile of free fonts, looking for nice ones.  The only problem was, it needed editing by hand to change the font specimen &#8211; too much work.<br />
&#8220;That&#8217;d be easy to automate with Sinatra&#8221; I thought, so I went looking on github to see if anyone had done it, and found the <a href="http://github.com/robertjwhitney/web-font-specimen">web font specimen</a> Sinatra mini-app, by Robert J Whitney.  Which was neat, but still involved editing a sass file to specify the font you want to view.<br />
This wasn&#8217;t quite what I wanted &#8211; (a) I&#8217;m not a big fan of Sass, I prefer something closer to CSS like Less, and (b) it only showed a single font, and needed configuration to change fonts, while I wanted to browse several.</p>
<p>So I forked it &#8211; see <a href="http://github.com/kornysietsma/web-font-specimen">my shiny new Sinatra app on github</a>.<br />
It actually ended up being more of a reboot than a fork &#8211; I undid a pile of other people&#8217;s hard work, and reverted the sass and haml files back to their original css and html, then added some logic to scan font directories dynamically &#8211; all the details are in the code and the <a href="http://github.com/kornysietsma/web-font-specimen#readme">readme</a>.<br />
But this is how it looks, once you install some fonts and load up the main index page:</p>
<p><a href="http://www.trouble.net.au/blog/korny/files/2010/04/index.png"><img class="alignnone size-medium wp-image-176" title="index page" src="http://www.trouble.net.au/blog/korny/files/2010/04/index-300x208.png" alt="some pretty font samples" width="300" height="208" /></a></p>
<p>Click on a font, and it takes you to a the Specimen page &#8211; this is basically Tim Brown&#8217;s original page, unmodified (except for a &#8216;back&#8217; link):</p>
<p><a href="http://www.trouble.net.au/blog/korny/files/2010/04/goudy.png"><img class="alignnone size-medium wp-image-177" title="OFL-Sorts-Mill-Goudy Font Sample" src="http://www.trouble.net.au/blog/korny/files/2010/04/goudy-300x205.png" alt="pretty font sample page" width="300" height="205" /></a></p>
<p>&#8230; And that&#8217;s about it.  I&#8217;m probably not going much further with this &#8211; it&#8217;s pretty handy as-is, for browsing your local font files and seeing what looks nice on different browsers.  If anyone wants any changes, feel free to hassle me &#8211; or fork the project yourself!</p>
<p><a href="http://www.trouble.net.au/blog/korny/files/2010/04/aquiline_two.png"><img class="aligncenter size-full wp-image-180" title="aquiline_two" src="http://www.trouble.net.au/blog/korny/files/2010/04/aquiline_two.png" alt="" width="527" height="293" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.trouble.net.au/blog/korny/2010/04/10/face-the-face/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android shortcut for sending mail</title>
		<link>http://www.trouble.net.au/blog/korny/2010/03/26/android-shortcut-for-sending-mail/</link>
		<comments>http://www.trouble.net.au/blog/korny/2010/03/26/android-shortcut-for-sending-mail/#comments</comments>
		<pubDate>Fri, 26 Mar 2010 00:24:12 +0000</pubDate>
		<dc:creator>korny</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.trouble.net.au/blog/korny/?p=168</guid>
		<description><![CDATA[I&#8217;m blogging about this because the second time I needed to make a mail shortcut, I couldn&#8217;t remember how &#8211; so if I blog it, I can always come here when I need to do it again! I&#8217;m using a couple of different applications that allow you to update them by e-mail &#8211; mostly, task [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m blogging about this because the second time I needed to make a mail shortcut, I couldn&#8217;t remember how &#8211; so if I blog it, I can always come here when I need to do it again!</p>
<p>I&#8217;m using a couple of different applications that allow you to update them by e-mail &#8211; mostly, task management apps.  I&#8217;m teetering between using <a href="http://www.rememberthemilk.com">Remember the Milk</a> and <a href="http://runwayapp.com/">Runway</a> to manage my to-do tasks.  Both of them have nice web interfaces, but adding a new idea/task via a web interface is a hassle &#8211; you have to be online, and you need to use a Browser UI &#8211; and even though both have nice mobile UIs, they are overkill for just adding a new &#8220;to be categorised&#8221; item.</p>
<p>Thankfully, both have magic e-mail addresses that can receive tasks as mail.  And on an Android phone, it&#8217;s very simple indeed to fire off a new mail &#8211; you can compose an e-mail and hit &#8220;send&#8221; or &#8220;save as draft&#8221;, and when the phone next syncs mail, it&#8217;ll be sent or put into your &#8216;drafts&#8217; folder on gmail.  Sure, you can do the same with a standalone app such as <a href="http://weloveastrid.com/">Astrid</a>, or the RTM-specific Android app (which I&#8217;ve never tried), but again, for basic &#8220;I need to remember this&#8221; tasks, a full app is overkill; and while Astrid will auto-sync, I trust the Gmail auto-sync rather more!</p>
<p>Anyway, to the shortcut business.  Rather than loading up the whole gmail client every time, you can simply make a desktop shortcut which loads the &#8220;Compose Mail&#8221; interface.  (Note, I have a HTC Hero, which has HTC&#8217;s custom Sense UI, so some of this may not apply to non-Sense phones).  The steps are as follows:</p>
<ol>
<li>Add the mail address to your gmail contacts, however you like (I use a desktop web browser generally, why bother doing this on the phone? Just add the contact in gmail, and wait for it to sync to the phone&#8217;s contacts list)</li>
<li>On the phone, press the &#8220;+&#8221; button on the bottom-right of the screen, or however you add icons in your Android OS</li>
<li>Select &#8220;Shortcut&#8221; (not &#8220;widget&#8221;, strangely)</li>
<li>Select &#8220;Person&#8221;</li>
<li>Choose the newly added contact</li>
<li>Select &#8220;send mail&#8221; &#8211; and a &#8220;send mail to XXX&#8221; icon will be put on your desktop</li>
</ol>
<p>If you find you have a lot of shortcuts, it&#8217;s well worth putting them in folders &#8211; I have a folder called &#8220;Planning&#8221; that has my &#8220;send to RTM&#8221; shortcut, plus bookmarks for the web interface, links to google calendar, etc.</p>
<p>Note this is also how you make a shortcut to send a SMS or to call a person.  Very handy for quick contacts for loved ones!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.trouble.net.au/blog/korny/2010/03/26/android-shortcut-for-sending-mail/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Conclusions on CoffeeScript</title>
		<link>http://www.trouble.net.au/blog/korny/2010/03/02/conclusions-with-coffeescript/</link>
		<comments>http://www.trouble.net.au/blog/korny/2010/03/02/conclusions-with-coffeescript/#comments</comments>
		<pubDate>Mon, 01 Mar 2010 23:57:41 +0000</pubDate>
		<dc:creator>korny</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.trouble.net.au/blog/korny/?p=165</guid>
		<description><![CDATA[Well, having played with CoffeeScript for a few days, I think it&#8217;s a wonderful thing &#8211; but for the moment, at least, I&#8217;m going back to JavaScript, with some regret. It&#8217;s a fabulous, clean, simple language &#8211; I love the terseness of the code: class TagPanel constructor: (width, height, paper) -&#38;gt; @width: width @height: height [...]]]></description>
			<content:encoded><![CDATA[<p>Well, having played with <a href="http://jashkenas.github.com/coffee-script/">CoffeeScript</a> for a few days, I think it&#8217;s a wonderful thing &#8211; but for the moment, at least, I&#8217;m going back to JavaScript, with some regret.<br />
<span id="more-165"></span><br />
It&#8217;s a fabulous, clean, simple language &#8211; I love the terseness of the code:</p>
<pre class="brush: php">
class TagPanel
  constructor: (width, height, paper) -&amp;gt;
    @width: width
    @height: height
    @paper: paper
    @boxes: []

  add_box: (box) -&amp;gt;
    box.display(@paper)
    @boxes.push box

  animate: (count) -&amp;gt;
    for i in [1...count]
      for box in @boxes
        box.step()

this.TagPanel: TagPanel # make global
</pre>
<p>compared with the JavaScript output:</p>
<pre class="brush: javascript">
(function(){
  var TagPanel;
  TagPanel = function TagPanel(width, height, paper) {
    this.width = width;
    this.height = height;
    this.paper = paper;
    this.boxes = [];
    return this;
  };
  TagPanel.prototype.add_box = function add_box(box) {
    box.display(this.paper);
    return this.boxes.push(box);
  };
  TagPanel.prototype.animate = function animate(count) {
    var _a, _b, _c, _d, _e, _f, _g, _h, _i, box, i;
    _a = []; _d = 1; _e = count;
    for (_c = 0, i = _d; (_d &lt;= _e ? i  _e); (_d &lt;= _e ? i += 1 : i -= 1), _c++) {
      _a.push((function() {
        _f = []; _g = this.boxes;
        for (_h = 0, _i = _g.length; _h &lt;; _i; _h++) {
          box = _g[_h];
          _f.push(box.step());
        }
        return _f;
      }).call(this));
    }
    return _a;
  };
  this.TagPanel = TagPanel;
  // make global
})();
</pre>
<p>However, I think it fails (for me) for a few reasons; some of these may be resolved over time, some may not.<br />
I think the main problem is that it&#039;s too different to Javascript.  This is the same reason I&#039;m not a fan of <a href="http://haml-lang.com/">HAML</a> or <a href="http://sass-lang.com/">SASS</a>, but quite like <a href="http://lesscss.org/">LessCSS</a> &#8211; if you are too different to the core language, a number of things no longer work:</p>
<ul>
<li>Syntax highlighting and IDE support are minimal</li>
<li>You aren&#8217;t learning enough about the core language</li>
<li>You can&#8217;t easily use existing code snippets or examples, with mentally de-compiling them back to CoffeeScript</li>
</ul>
<p><a href="http://lesscss.org/">LessCSS</a>, or in-language templating tools like <a href="http://github.com/defunkt/mustache">Mustache</a> or even good ol&#8217; <a href="http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/">ERB</a>, let you mix the old and the new; sometimes you IDE still gets screwed up by the differences from the core language, but you can generally work it out.</p>
<p>I have a few other minor issues with CofeeScript &#8211; I&#8217;m not such a big fan of Python-style indentation-as-code; I used to be more of a fan, and I could learn to love it again, but without IDE support it&#8217;s a bit of a pain.  Also there are a few other things I&#8217;d quibble about; but they are just that, quibbles, most of it is just fine as a language.</p>
<p>But a key thing for me is that I&#8217;m still learning to do Javascript properly &#8211; after years of using it badly as a make-my-browser-clicks-work tool, I went to a talk by <a href="http://javascript.crockford.com/">Doug Crockford</a>, and realised I need to learn this language properly.  And that means becoming familiar with the language itself, learning the right way and the wrong way to do things; using CoffeeScript encourages a few particular idioms, which work well, but I&#8217;m not learning beyond those idioms.</p>
<p>So I&#8217;ll take my code spiked in CoffeeScript and try to do it properly in JavaScript, probably working on TDDing it with <a href="http://visionmedia.github.com/jspec/">JSpec</a> or other such tools.  Maybe when I&#8217;m completely confident in JavaScript I&#8217;ll come back to the sweet smell of the Coffee&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.trouble.net.au/blog/korny/2010/03/02/conclusions-with-coffeescript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Playing with CoffeeScript</title>
		<link>http://www.trouble.net.au/blog/korny/2010/02/25/playing-with-coffeescript/</link>
		<comments>http://www.trouble.net.au/blog/korny/2010/02/25/playing-with-coffeescript/#comments</comments>
		<pubDate>Thu, 25 Feb 2010 03:03:35 +0000</pubDate>
		<dc:creator>korny</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[javascript coffeescript]]></category>

		<guid isPermaLink="false">http://www.trouble.net.au/blog/korny/?p=148</guid>
		<description><![CDATA[I&#8217;ve been fiddling with Coffeescript, a nifty language for writing Javascript &#8211; well, really it&#8217;s more like a pre-compiler than a language; it compiles directly to readable javascript (including comments!) and generally one Coffeescript statement produces one javascript statement. So why would you use it? Because it bypasses some of the horribleness of Javascript syntax, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been fiddling with <a href="http://jashkenas.github.com/coffee-script">Coffeescript</a>, a nifty language for writing Javascript &#8211; well, really it&#8217;s more like a pre-compiler than a language; it compiles directly to readable javascript (including comments!) and generally one Coffeescript statement produces one javascript statement.</p>
<p>So why would you use it?  Because it bypasses some of the horribleness of Javascript syntax, and implements a few handy patterns, like anonymous function creation, in much clearer code.<br />
<span id="more-148"></span><br />
For example, the following Coffeescript:</p>
<pre class="brush: text">
square: (x) -&gt;
alert &#039;squaring: &#039; + x
x * x
</pre>
<p>converts to the following javascript:</p>
<pre class="brush: javascript">
square: function square(x) {
  alert(&#039;squaring:&#039; + x);
  return x * x;
}
</pre>
<p>There are many more examples at the <a href="http://jashkenas.github.com/coffee-script">Coffeescript</a> home page.</p>
<p>I&#8217;m not 100% sold on this, as I&#8217;m still learning (proper) Javascript, and this amplifies some of my ignorance.  For example, I really struggle with &#8216;this&#8217; and functions/objects &#8211; and while Coffeescript automatically enforces some good Javascript behaviour, when I do something wrong it&#8217;s a bigger than usual struggle to work out why.<br />
A longer example: I&#8217;ve been playing with <a href="http://raphaeljs.com/">Raphael</a> (and JQuery) and decided to do some fiddling in Coffeescript:</p>
<pre class="brush: text">
app: {
  init: -&gt;
    app.paper: Raphael(&#039;playspace&#039;,320,200)
    app.draw_circle()
    app.draw_square()

  # simple circle with event-based on-click event
  draw_circle: -&gt;
    circle: app.paper.circle(50,40,30)
    circle.attr(&quot;fill&quot;,&quot;#f00&quot;)
    circle.attr(&quot;stroke&quot;,&quot;#fff&quot;)
    $(circle.node).click((e) -&gt; app.kick(e))

  # square with object-based on-click event
  draw_square: -&gt;
    square: app.paper.rect(150,40,50,30)
    square.attr(&quot;fill&quot;,&quot;#0f0&quot;)
    square.attr(&quot;stroke&quot;,&quot;#fff&quot;)
    $(square.node).click((e) -&gt; app.punt(square,e))

  kick: (e) -&gt;
    app.paper.text(e.pageX + 10, e.pageY + 10, &quot;Raphaël\nkicks\nbutt!&quot;)

  punt: (obj,e) -&gt;
    obj.translate(10,10)
}

# make it globally visible - not really needed, handy for debugging
if window?
  window.APP: app

$(app.init)
</pre>
<p>The javascript version is:</p>
<pre class="brush: javascript">
(function(){
  var app;
  app = {
    init: function init() {
      app.paper = Raphael(&#039;playspace&#039;, 320, 200);
      app.draw_circle();
      return app.draw_square();
    },
    // simple circle with event-based on-click event
    draw_circle: function draw_circle() {
      var circle;
      circle = app.paper.circle(50, 40, 30);
      circle.attr(&quot;fill&quot;, &quot;#f00&quot;);
      circle.attr(&quot;stroke&quot;, &quot;#fff&quot;);
      return $(circle.node).click(function(e) {
        return app.kick(e);
      });
    },
    // square with object-based on-click event
    draw_square: function draw_square() {
      var square;
      square = app.paper.rect(150, 40, 50, 30);
      square.attr(&quot;fill&quot;, &quot;#0f0&quot;);
      square.attr(&quot;stroke&quot;, &quot;#fff&quot;);
      return $(square.node).click(function(e) {
        return app.punt(square, e);
      });
    },
    kick: function kick(e) {
      return app.paper.text(e.pageX + 10, e.pageY + 10, &quot;Raphaël\nkicks\nbutt!&quot;);
    },
    punt: function punt(obj, e) {
      return obj.translate(10, 10);
    }
  };
  // make it globally visible - not really needed, handy for debugging
  (typeof window !== &quot;undefined&quot; &amp;&amp; window !== null) ? (window.APP = app) : null;
  $(app.init);
})();
</pre>
<p>Now, this works, it&#8217;s a lot more readable than the Javascript version, and it&#8217;s nifty how Coffeescript wrapped everything in an anonymous function so as to not pollute the global namespace (except where I did so deliberately).</p>
<p>But this was about my 8th try.  I had endless problems getting the &#8216;click&#8217; handlers to hook into the &#8216;kick&#8217; and &#8216;punt&#8217; methods.  I tried (initially) using &#8216;this.kick&#8217; but it failed as when the click handler is called, this is bound elsewhere.  I tried storing &#8216;this&#8217; in a variable, but had pain with the fact that somewhere in the mess of anonymous function wrappers, &#8216;this&#8217; never seemed to mean the right thing.</p>
<p>In the end, I hit on storing the whole thing as an object &#8216;app&#8217; &#8211; I was already going to make it part of &#8216;window.APP&#8217; but didn&#8217;t want to prefix all calls with &#8216;APP&#8217;&#8230; but in the end, that&#8217;s kind-of what I did, only the global APP variable isn&#8217;t actually needed, just the local &#8216;app&#8217; variable.</p>
<p>Anyway, I&#8217;m sure there is a better way to do this &#8211; but I haven&#8217;t found it, and this one works.  Now I have to decide if I want to keep playing with Coffeescript, having worked all this out, or go back to ugly old Javascript, where at least there are hundreds of net resources to help me when I get stuck!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.trouble.net.au/blog/korny/2010/02/25/playing-with-coffeescript/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Simple ruby wrapper for Delcom build lights on Linux</title>
		<link>http://www.trouble.net.au/blog/korny/2010/02/12/simple-ruby-wrapper-for-delcom-build-lights-on-linux/</link>
		<comments>http://www.trouble.net.au/blog/korny/2010/02/12/simple-ruby-wrapper-for-delcom-build-lights-on-linux/#comments</comments>
		<pubDate>Fri, 12 Feb 2010 05:53:24 +0000</pubDate>
		<dc:creator>korny</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.trouble.net.au/blog/korny/?p=138</guid>
		<description><![CDATA[This isn&#8217;t particularly new &#8211; I wrote this code a while ago, but it never got &#8220;finished&#8221; so I never wrote it up&#8230; Many agile dev teams use Delcom USB build lights: http://delcomproducts.com/productdetails.asp?productnum=804005 Coding for these is apparently quite complex&#8230; unless you are on a recent-ish Linux machine, in which case it&#8217;s amazingly trivial. When [...]]]></description>
			<content:encoded><![CDATA[<p>This isn&#8217;t particularly new &#8211; I wrote this code a while ago, but it never got &#8220;finished&#8221; so I never wrote it up&#8230;</p>
<p>Many agile dev teams use Delcom USB build lights:<br />
<a href="http://delcomproducts.com/productdetails.asp?productnum=804005">http://delcomproducts.com/productdetails.asp?productnum=804005</a></p>
<p>Coding for these is apparently quite complex&#8230; unless you are on a recent-ish Linux machine, in which case it&#8217;s amazingly trivial.<br />
<span id="more-138"></span><br />
When you plug the light in, if you have the right modules loaded, you&#8217;ll get a set of magic files in a directory somewhere under:<br />
<code>/sys/bus/usb/drivers/usbled</code> &#8211; on my PC with my light they show up under <code>/sys/bus/usb/drivers/usbled/7-2:1.0</code>, and you only need to care about 3 little virtual files:</p>
<pre class="brush: bash">
-rw-rw-rw- 1 root root 4096 2010-02-12 16:26 blue
-rw-rw-rw- 1 root root 4096 2010-02-12 16:26 green
-rw-rw-rw- 1 root root 4096 2010-02-12 16:26 red
</pre>
<p>Those 3 files control the 3 components of the light.  You can set or get the colour trivially from the shell, once you know the name:</p>
<pre class="brush: bash">
$ cat /sys/bus/usb/drivers/usbled/7-2:1.0/blue
0
$ echo &quot;1&quot; &gt; /sys/bus/usb/drivers/usbled/7-2:1.0/blue
# Blam!  The light goes blue!
$ cat /sys/bus/usb/drivers/usbled/7-2:1.0/blue
1
$ echo &quot;1&quot; &gt; /sys/bus/usb/drivers/usbled/7-2:1.0/red
# and now the light goes purple - red + blue!
</pre>
<p>That&#8217;s really all you need to know &#8211; you can read, and write, the red/green/blue elements of the light.  A little ruby wrapper I wrote makes for nicer colour names, and automatically works out the path to the light (ok, it just finds the first directory that looks right in the usbled path&#8230;):</p>
<pre class="brush: ruby">
#!/usr/bin/env ruby
class UsbLight
  COLOURNAMES = {
      :black =&gt; [0,0,0],
      :red =&gt; [1,0,0],
      :green =&gt; [0,1,0],
      :blue =&gt; [0,0,1],
      :cyan =&gt; [0,1,1],
      :magenta =&gt; [1,0,1],
      :yellow =&gt; [1,1,0],
      :white =&gt; [1,1,1]
    }

  def initialize
    @usbledpath = &#039;/sys/bus/usb/drivers/usbled&#039;
    @usbleddev = Dir.new(@usbledpath).find { |f| f =~ /^\d-\d.*/ }
    raise &quot;Can&#039;t find device in #{@usbledpath}&quot; unless @usbleddev
    @usbled = File.join(@usbledpath,@usbleddev)
    @lights = {}
    %w(red green blue).each do |light|
      @lights[light] = File.join(@usbled,light)
      raise &quot;can&#039;t read #{light} light&quot; unless File.readable?(@lights[light])
      raise &quot;can&#039;t write #{light} light&quot; unless File.writable?(@lights[light])
    end
  end
  def colour
    lights = [read_light(&quot;red&quot;),read_light(&quot;green&quot;),read_light(&quot;blue&quot;)]
    colour_pattern = COLOURNAMES.detect { |colour, pattern| pattern == lights }
    raise &quot;bad colour combo: #{lights.inspect}&quot; if colour_pattern.nil?
    colour_pattern[0]
  end
  def colour=(name)
    lights = COLOURNAMES[name.to_sym]
    raise &quot;unknown lamp colour: #{name}&quot; unless lights
    write_light(&quot;red&quot;,lights[0])
    write_light(&quot;green&quot;,lights[1])
    write_light(&quot;blue&quot;,lights[2])
  end
  def off
    self.colour = :black
  end

  private
  def read_light(name)
    File.new(@lights[name]).read.to_i
  end
  def write_light(name,value)
    open(@lights[name],&quot;w&quot;) do |f|
      f.puts(value.to_s)
    end
  end
end
</pre>
<p>I have a Hudson watcher that uses this to set the light colour &#8211; but that&#8217;s a subject for another post!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.trouble.net.au/blog/korny/2010/02/12/simple-ruby-wrapper-for-delcom-build-lights-on-linux/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Behaviour Driven Development with Cucumber and Selenium</title>
		<link>http://www.trouble.net.au/blog/korny/2009/11/03/behaviour-driven-development-with-cucumber-and-selenium/</link>
		<comments>http://www.trouble.net.au/blog/korny/2009/11/03/behaviour-driven-development-with-cucumber-and-selenium/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 10:22:08 +0000</pubDate>
		<dc:creator>korny</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[bdd]]></category>
		<category><![CDATA[cucumber]]></category>
		<category><![CDATA[selenium]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.trouble.net.au/blog/korny/?p=102</guid>
		<description><![CDATA[[Please note - if you are familiar with BDD, Cucumber, or Selenium, parts of this may be a tad basic - but I thought it was worth writing a from-scratch guide for those to whom this is unfamiliar territory...] What is Behaviour Driven Development? BDD is a new-ish term used as a contrast to Test [...]]]></description>
			<content:encoded><![CDATA[<p>[Please note - if you are familiar with BDD, Cucumber, or Selenium, parts of this may be a tad basic - but I thought it was worth writing a from-scratch guide for those to whom this is unfamiliar territory...]</p>
<h3>What is Behaviour Driven Development?</h3>
<p>BDD is a new-ish term used as a contrast to Test Driven Development &#8211; it was coined by Dan North in 2006, as described in his article at <a href="http://dannorth.net/introducing-bdd" target="_blank">http://dannorth.net/introducing-bdd</a> &#8211; there&#8217;s also a good introduction in <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development" target="_blank">wikipedia</a>.</p>
<p>In a nutshell, BDD is all about describing the behaviour of an application, in a plain-text language that can be understood by end users, testers, and developers &#8211; and then hopefully automating acceptance testing, so you can prove that at any time, the application meets the BDD description.<br />
<span id="more-102"></span></p>
<h3>How about Cucumber? and Selenium?</h3>
<p><a href="http://cukes.info/" target="_blank">Cucumber</a>, which grew out of the Ruby <a href="http://rspec.info/">Rspec</a> framework, is a tool to enable the writing of acceptance criteria in a controlled plain-text format, and then running those criteria via some ruby back-end code.</p>
<p><a href="http://seleniumhq.org/" target="_blank">Selenium</a> is a set of tools for automating tests in web browsers.  There are actually two main flavours of Selenium, Selenium IDE that runs in a browser-based gui, and Selenium RC, a client/server version with a java server and clients in a number of languages. We&#8217;ll use Selenium RC, with the Ruby front end (as it makes integrating with Cucumber very easy).  You can also use alternative tools such as <a href="http://watir.com/" target="_blank">Watir</a> or <a href="http://celerity.rubyforge.org/" target="_blank">Celerity</a> to do similar things in different ways; each has it&#8217;s merits and limitations.</p>
<h3>Ok, give me an example</h3>
<p>I&#8217;ve used the Twitter home page as an example, as it has a bunch of asynchronous ajax behaviour, which is very hard to test without automating a web browser.</p>
<p>The scenarios for a related set of Twitter features are defined in a feature file, such as <code><strong>trending_topics.feature</strong></code> :</p>
<pre>Feature: Twitter trending topics
In order to tap into the zeitgeist
as a web surfer
I should be able to see what's being discussed on twitter

Scenario: view popular topics
When I visit the Twitter home page
Then I should be able to see popular topics right now

Scenario: search for most popular topics
Given I am on the Twitter home page
And I see the most popular topic
When I search for the most popular topic
Then I should see results containing the most popular topic
And I should see a message indicating more results exist within 40 seconds</pre>
<p>The first few lines are a preamble &#8211; they define the background of the feature.</p>
<p>The actual scenarios are runnable definitions of how the feature actually behaves.</p>
<h3>Making the features runnable</h3>
<p>There are several layers of code to make these features actually runnable.</p>
<p>First, we have step definitions &#8211; these are code that matches each &#8220;Given&#8221;, &#8220;When&#8221; or &#8220;Then&#8221; step with a regular expression or a plain text string, that identifies the matching ruby logic, and possibly extracts user parameters.  For example, the step &#8220;And I should see a message indicating more results exist within 40 seconds&#8221; is matched by ruby code like:</p>
<pre class="brush: ruby">
Then /^I should see a message indicating more results exist within (\d+) seconds$/ do |timeout|
</pre>
<p>- the regular expression matches the step, and pulls out the timeout parameter into a variable.</p>
<p>The full code of the steps file is as follows:</p>
<p><code><strong>twitter_steps.rb</strong></code></p>
<pre class="brush: ruby">
Given &quot;I am on the Twitter home page&quot; do
  @home_page.visit
end

Given &quot;I see the most popular topic&quot; do
  @most_popular = @home_page.most_popular_topic
  puts &quot;Most popular topic: &#039;#{@most_popular}&#039;&quot;
end

When &quot;I visit the Twitter home page&quot; do
  Given &quot;I am on the Twitter home page&quot;
end

When &quot;I search for the most popular topic&quot; do
  @home_page.search(@most_popular)
end

Then &quot;I should be able to see popular topics right now&quot; do
  @home_page.should have_popular_topics
end

Then &quot;I should see results containing the most popular topic&quot; do
  @results_page.tweets.each do |result|
     result[:tweet].downcase.should include @most_popular.downcase
  end
end

Then /^I should see a message indicating more results exist within (\d+) seconds$/ do |timeout|
  @results_page.wait_for_more_results(timeout.to_i)
end
</pre>
<p>As you can see, the step implementations are very simple &#8211; all the heavy lifting is done by page model objects &#8211; @home_page and @results page wrap all the logic related to two different web pages.  The twitter_steps.rb file just handles matching the steps, and tracking some state, such as the @most_popular variable.</p>
<p><code><strong>twitter_home_page.rb</strong></code> defines the home page model:</p>
<pre class="brush: ruby">
class TwitterHomePage
  PAGE_URL = &quot;http://www.twitter.com&quot;
  def initialize(world)
    @world = world
    @browser = $selenium_helper.browser
  end

  def visit
    @browser.open PAGE_URL
    @browser.wait_for_page_to_load
    @browser.title.should == &quot;Twitter&quot;
  end

  def has_popular_topics?
    @browser.element? POP_TOPICS_LOCATOR
  end

  def most_popular_topic
    @browser.text FIRST_POP_TOPIC_LOCATOR
  end

  def search(topic)
    @browser.type SEARCH_BOX_LOCATOR, topic
    @browser.click SEARCH_BUTTON_LOCATOR
    @browser.wait_for_element RESULTS_HEADING_LOCATOR
  end

  private

  POP_TOPICS_LOCATOR = %Q{//div[@id = &quot;trends&quot;]//div[@class = &quot;current&quot;]}
  FIRST_POP_TOPIC_LOCATOR = &quot;#{POP_TOPICS_LOCATOR}/ul/li[1]/a&quot;
  SEARCH_BOX_LOCATOR = %Q{//input[@id=&quot;home_search_q&quot;]}
  SEARCH_BUTTON_LOCATOR = %Q{//a[@id=&quot;home_search_submit&quot;]}
  RESULTS_HEADING_LOCATOR = %Q{//div[@id=&quot;content&quot;]/h2[@id=&quot;timeline_heading&quot;]}
end
</pre>
<p><code><strong>twitter_results_page.rb</strong></code> is for handling search results:</p>
<pre class="brush: ruby">
class TwitterResultsPage
  def initialize(world)
    @world = world
    @browser = $selenium_helper.browser
  end

  def tweets
    # ajax results, give them a chance to load
    @browser.wait_for_element(TIMELINE_LOCATOR)
    result_count = @browser.get_xpath_count(TIMELINE_LOCATOR).to_i

    (1..result_count).collect do |count|
      {
        :author =&gt; @browser.get_text(tweet_author_locator(count)),
        :tweet =&gt; @browser.get_text(tweet_text_locator(count))
      }
    end
  end

  def wait_for_more_results(timeout_secs)
    @browser.wait_for_element(MORE_RESULTS_LOCATOR,{:timeout_in_secs =&gt; timeout_secs})
  end

  private

  def tweet_author_locator(count)
    %Q{#{tweet_locator(count)}//a[contains(@class, &quot;screen-name&quot;)]}
  end

  def tweet_text_locator(count)
    %Q{#{tweet_locator(count)}//span[contains(@class, &quot;msgtxt&quot;)]}
  end

  def tweet_locator(count)
    %Q{#{TIMELINE_LOCATOR}[#{count}]}
  end

  TIMELINE_LOCATOR = %Q{//ol[@id=&quot;timeline&quot;]/li}
  MORE_RESULTS_LOCATOR = %Q{//div[@id=&quot;new_results_notification&quot;]/a[@id=&quot;results_update&quot; and not(contains(@style, &quot;display: none&quot;))]}
end
</pre>
<p>The page models use a lot of xpath locators to find items in web pages; they work well on most modern browsers but might be inconsistent on IE6 &#8211; if you want to test on IE6 you might have to look into other ways to locate elements, such as finding them by ID.</p>
<p>There are some utility classes that set up the environment, user configuration, and the Selenium interface:</p>
<p><code><strong>env.rb</strong></code> is the main entry point for Cucumber &#8211; it is loaded first, before any other ruby files, and it sets up globals and startup/shutdown code:</p>
<pre class="brush: ruby">
BASEDIR = File.join(File.dirname(__FILE__),&quot;..&quot;) unless defined? BASEDIR
PRJDIR = File.join(File.dirname(__FILE__),&quot;..&quot;,&quot;..&quot;,&quot;..&quot;) unless defined? PRJDIR
require &#039;spec/expectations&#039; # rspec extras
require File.join(BASEDIR,&#039;support/selenium_helper.rb&#039;)
require File.join(BASEDIR,&#039;support/user_config.rb&#039;)

# globals - keep these to a minimum!
$user_config = UserConfig.new
$selenium_helper = SeleniumHelper.new($user_config)  # better a global than a singleton - still need something global as it&#039;s used in monkey-patching bits below

at_exit do
  $stderr.puts &quot;global exit block - closing browser&quot;
  $selenium_helper.shutdown
end

module MyWorld
  # add methods here you want accessible from all cucumber steps
end

World(MyWorld)

Before do
  @home_page = TwitterHomePage.new(self)
  @results_page = TwitterResultsPage.new(self)
end
</pre>
<p>The &#8216;MyWorld&#8217; module is there as a starting point for your own extensions &#8211; generally I have often-needed functions in this module; see <a href="http://wiki.github.com/aslakhellesoy/cucumber/a-whole-new-world">the cucumber documentation</a> for more.</p>
<p>The &#8216;Before&#8217; block is called before every scenario &#8211; here it just sets up the page objects, but other per-scenario stuff can also be added here.</p>
<p>Other than that, the main things included are a user config class, that loads user configuration from a file named for the user&#8217;s host name (so on &#8220;my_pc&#8221; it will load a config file called &#8220;config/my_pc.config&#8221;); see <a href="http://gist.github.com/224106">http://gist.github.com/224106</a> for code and a typical example.</p>
<p>&#8230; and the real work of loading Selenium is in the <strong><code>selenium_helper.rb</code></strong> file:</p>
<pre class="brush: ruby">
require &#039;selenium/client&#039;
require &#039;selenium/rspec/spec_helper&#039;
require File.join(BASEDIR,&#039;support/user_config.rb&#039;)

if defined? JRUBY_VERSION
  # jruby has it&#039;s own process-handling code, as &#039;fork&#039; is unreliable in java
  require &#039;java&#039;
end

class SeleniumHelper
  attr_accessor :max_timeout, :browser
  def initialize(user_config)
    @user_config = user_config
    @max_timeout = 45  # maximum allowed timeout
    @selenium_port = user_config[&#039;selenium.port&#039;]
    @selenium_browser = @user_config[&#039;selenium.browser.name&#039;]
    @selenium_process = nil
    @browser = nil
    start_selenium
    start_browser
  end

  def shutdown
    stop_selenium
  end

  private

  def start_selenium
    selenium_jar_path = File.expand_path(File.join(PRJDIR,&quot;lib&quot;,&quot;selenium&quot;,&quot;selenium-server.jar&quot;))
    raise &quot;Can&#039;t find #{selenium_jar_path}&quot; unless File.exists?(selenium_jar_path)
    cmd = &quot;java -jar #{selenium_jar_path} -timeout #{@max_timeout} -port #{@selenium_port}&quot;

    if defined? JRUBY_VERSION # java magic to run a process
      @selenium_process = java.lang.ProcessBuilder.new(cmd.split(&quot; &quot;)).redirectErrorStream(true).start
      # spawn a thread to redirect background process to log file
      $stderr.puts &quot;selenium process started in background&quot;
      output_stream_to_log(@selenium_process.getInputStream, &quot;selenium.log&quot;)
    else # not java - use fork
      @selenium_process = Process.fork do
          # Note: you need to redirect stdout this way
          # - if you try using &quot;cmd &gt; selenium.log&quot; ruby spawns a subprocess, which you can&#039;t kill
         $stdout.reopen(File.new(&quot;selenium.log&quot;, &quot;w&quot;))
         exec cmd
      end
      $stderr.puts &quot;selenium process started with pid #{@selenium_process}&quot;
    end
    sleep 2  # give it a chance to start
    $stderr.puts &quot;Selenium output sent to selenium.log&quot;
  end

  def start_browser
    begin
      base_url = &quot;http://localhost&quot;
      @browser = Selenium::Client::Driver.new(&quot;localhost&quot;, @selenium_port, @selenium_browser, base_url, @max_timeout)
      @browser.start_new_browser_session
    rescue Exception
      stop_selenium
      raise
    end
  end

  def stop_selenium
    $stderr.puts &quot;killing background selenium task&quot;
    # could open http://localhost:selenium_port/selenium-server/driver/?cmd=shutDown - but this is more reliable!
    if defined? JRUBY_VERSION
      @selenium_process.destroy
      $stderr.puts &quot;and waiting...&quot;
      @selenium_process.waitFor
    else
      Process.kill(&quot;HUP&quot;, @selenium_process)
      $stderr.puts &quot;and waiting...&quot;
      Process.wait
    end
    $stderr.puts &quot;dead.&quot;
  end

  def output_stream_to_log(inputStream, logfilename)
    Thread.new do
      File.open(logfilename,&quot;w&quot;) do |f|
        output = java.io.BufferedReader.new(java.io.InputStreamReader.new(inputStream))
        while (line = output.readLine) != nil
          f.puts line
        end
        output.close
      end
    end

  end
end
</pre>
<p>Note you <b>can</b> just load selenium.jar from a command line, and save yourself much of the effort here &#8211; but this will load and unload it for you, which can keep things simpler.  There&#8217;s some complexity involved in getting it to work both in JRuby (which has to use Java&#8217;s ProcessBuilder class) and in vanilla Ruby.</p>
<h3>Building and running this example</h3>
<p>To get this example up and running, you need:</p>
<ul>
<li><a href="http://www.ruby-lang.org">Ruby</a>, or <a href="http://jruby.org">JRuby</a> &#8211; native Ruby is faster, but if you are in the Java world, JRuby can be handy as it&#8217;s 100% java</li>
<li><a href="http://www.rubygems.org">Ruby-gems</a>, the ruby packaging system (included in JRuby)</li>
<li> The ruby gems:
<ul>
<li>rspec (tested with version 1.2.6) &#8211; not essential, but adds many nice matchers and features to cucumber</li>
<li>cucumber (tested with version 0.3.9)</li>
<li>Selenium (tested with version 1.1.14)</li>
<li>selenium-client (tested with version 1.2.15)</li>
</ul>
</li>
<li>Java 1.5 or later (needed for the selenium server)</li>
<li> The selenium-rc server (version 1.0.1 or later)
<ul>
<li>you really only need the selenium-server jar file, everything else is included in the ruby gems above</li>
<li>download selenium-rc from <a href="http://seleniumhq.org/download/">http://seleniumhq.org/download/</a> , unzip selenium-remote-control-???.zip, and extract the file &#8216;selenium-server.jar&#8217;</li>
</ul>
</li>
</ul>
<p>The file structure is as follows:</p>
<ul>
<li> Root folder &#8211; optionally contains a cucumber.yml file (see cucumber docs for more)
<ul>
<li> test/features &#8211; base directory for all feature files
<ul>
<li>/trending_topics.feature</li>
<li> /step_definitions
<ul>
<li>twitter_steps.rb</li>
</ul>
</li>
<li> /support
<ul>
<li>env.rb</li>
<li>selenium_helper.rb</li>
<li>user_config.rb</li>
<li> /pages
<ul>
<li>twitter_home_page.rb</li>
<li>twitter_results_page.rb</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>lib/selenium/selenium-server.jar &#8211; the selenium server itself</li>
</ul>
</li>
</ul>
<p>The complete set of sample files (except the selenium jar file!) is available at <a href='http://sietsma.com/korny/cuke_sample.zip'>http://sietsma.com/korny/cuke_sample.zip</a>.</p>
<h3>Running it!</h3>
<p>To run all the scenarios in the feature file, assuming all the software is installed and in the path as required, run:</p>
<pre>$ cucumber test/features/trending_topics.feature</pre>
<p>The output should be similar to:</p>
<pre>
selenium process started with pid 25298
Selenium output sent to selenium.log
Feature: Twitter trending topics
  In order to tap into the zeitgeist
  as a web surfer
  I should be able to see what's being discussed on twitter

  Scenario: view popular topics                           # test/features/trending_topics.feature:6
    <i>When I visit the Twitter home page</i>                    # test/features/step_definitions/twitter_steps.rb:10
    <i>Then I should be able to see popular topics right now</i> # test/features/step_definitions/twitter_steps.rb:18

  Scenario: search for most popular topics                                     # test/features/trending_topics.feature:10
    <i>Given I am on the Twitter home page</i>                                        # test/features/step_definitions/twitter_steps.rb:1
Most popular topic: '#unseenprequels'
    <i>And I see the most popular topic</i>                                           # test/features/step_definitions/twitter_steps.rb:5
    <i>When I search for the most popular topic</i>                                   # test/features/step_definitions/twitter_steps.rb:14
    <i>Then I should see results containing the most popular topic</i>                # test/features/step_definitions/twitter_steps.rb:22
    <i>And I should see a message indicating more results exist within 40 seconds</i> # test/features/step_definitions/twitter_steps.rb:26

2 scenarios (2 passed)
7 steps (7 passed)
0m33.328s
global exit block - closing browser
killing background selenium task
and waiting...
dead.
</pre>
<p>Note sections in <i>italics</i> are actually green on a terminal, to indicate success.  You can also format output as html, for prettier display, or for embedding in a Continuous Integration report.<br />
&#8212;</p>
<p>There is far more that could be said on this topic &#8211; this is just the tip of the iceberg.  Hopefully this is a useful starting point however!</p>
<p>As mentioned earlier, you can download all the code in this article from <a href='http://sietsma.com/korny/cuke_sample.zip'>http://sietsma.com/korny/cuke_sample.zip</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.trouble.net.au/blog/korny/2009/11/03/behaviour-driven-development-with-cucumber-and-selenium/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

