<?xml version="1.0" encoding="utf-8"?>
<feed xml:base="http://pepijndevos.nl/" xmlns="http://www.w3.org/2005/Atom">
 
	<title>Wishful Coding</title>
	<subtitle>Didn't you ever wish your computer understood you?</subtitle>
	<link href="http://pepijndevos.nl/atom.xml" rel="self"/>
	<link href="http://pepijndevos.nl/"/>
	<updated>2012-04-23T08:00:54-07:00</updated>
	<id>http://pepijndevos.nl/</id>
	<author>
		<name>Pepijn de Vos</name>
		<email>pepijndevos+atom@gmail.com</email>
	</author>

	
	<entry>
		<title>Fast PyCAM on Mac using Homebrew</title>
		<link href="http://pepijndevos.nl/2012/04/23/fast-pycam-on-mac-using-homebrew.html"/>
		<updated>2012-04-23T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2012/04/23/fast-pycam-on-mac-using-homebrew</id>
		<content type="html">&lt;p&gt;Ever since I started working on my CNC mill, I have been looking for decent software to generate G-code for it.&lt;/p&gt;

&lt;p&gt;I &lt;a href='https://github.com/pepijndevos/Home-made-CNC'&gt;wrote a G-code interpreter&lt;/a&gt; for my machine, after I found out LinuxCNC doesn&amp;#8217;t support my type of LPT stepper driver, but finding good software to turn a 3D model into G-code turned out to be hard.&lt;/p&gt;

&lt;p&gt;I went down &lt;a href='http://replicat.org/generators'&gt;this list&lt;/a&gt;, but most of them where hard to install or impossible to configure. In 2D I had some luck with the Inkscape plugin, but I was lost for 3D.&lt;/p&gt;

&lt;p&gt;With the mill in a working state, and nothing to mill, I decided to push forward with PyCAM. I skipped PyCAM previously, because of its &lt;a href='https://sourceforge.net/apps/mediawiki/pycam/index.php?title=Requirements'&gt;dependencies&lt;/a&gt;, which weren&amp;#8217;t all available in Homebrew.&lt;/p&gt;

&lt;p&gt;Some experimentation revealed a few important things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It runs okay on my Ubuntu netbook.&lt;/li&gt;

&lt;li&gt;Toolpath calculations take a looong time.&lt;/li&gt;

&lt;li&gt;Its CLI runs without OpenGL and GTK+&lt;/li&gt;

&lt;li&gt;It supports multiple and distributed processors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After I cancelled the Ubuntu calculations, I ran it headless on my Mac. While somewhat faster, it still took a long time to generate G-code.&lt;/p&gt;

&lt;p&gt;The real speedup came later, when I found PyCAM supports Psyco. But rather than messing with Psyco, I followed the advice on the Psyco homepage, and found the headless PyCAM runs great, and very fast, on PyPy.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Psyco is unmaintained and dead. Please look at PyPy for the state-of-the-art in JIT compilers for Python.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After successfully running PyCAM headless, I finally put my teeth in the dependencies. Installation steps using Homebrew follow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href='http://pycam.sourceforge.net/download.html'&gt;Download PyCAM&lt;/a&gt;.&lt;/li&gt;

&lt;li&gt;Apply &lt;a href='https://sourceforge.net/tracker/?func=detail&amp;amp;aid=3520280&amp;amp;group_id=237831&amp;amp;atid=1104176#filebar'&gt;my patch&lt;/a&gt; to make sure it finds pygtk.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;brew install pygtk&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;&lt;code&gt;sudo easy_install PyOpenGL&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;Wait for my &lt;a href='https://github.com/mxcl/homebrew/pull/11801'&gt;pygtkglext Formula&lt;/a&gt; to be merged, or get it from my branch.&lt;/li&gt;

&lt;li&gt;&lt;code&gt;brew install pygtkglext&lt;/code&gt; or &lt;code&gt;brew install https://raw.github.com/pepijndevos/homebrew/master/Library/Formula/pygtkglext.rb&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now you should be able to just run &lt;code&gt;./pycam&lt;/code&gt; to see the GUI pop up. However, I use the following 2 commands to run a server on PyPy, for extra speed.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;pypy pycam --start-server-only --server-auth-key=fietspomp --number-of-processes=4

python pycam --enable-server --remote-server=localhost --server-auth-key=fietspomp --number-of-processes=0&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&amp;#8217;ll blog about the mill itself later. This morning I tried to mill a small sample project, but the mill is very inaccurate and jammed after a few layers.&lt;/p&gt;</content>
		
		<category term="python" />
		
		<category term="mill" />
		
		<category term="gcode" />
		
		<category term="mac" />
		
	</entry>
	
	<entry>
		<title>Crazy Seq</title>
		<link href="http://pepijndevos.nl/2012/04/17/crazy-seq.html"/>
		<updated>2012-04-17T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2012/04/17/crazy-seq</id>
		<content type="html">&lt;p&gt;crazy-seq, the solution to all your head-holding induced memory problems.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='clojure'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;crazy-seq&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;head&lt;/span&gt; &lt;span class='nv'&gt;f&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;reify&lt;/span&gt;
    &lt;span class='nv'&gt;clojure&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;lang&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;ISeq&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;first &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;_&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='nv'&gt;head&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;more&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;_&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;crazy-seq&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;f&lt;/span&gt; &lt;span class='nv'&gt;head&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nv'&gt;f&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;next &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;this&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;rest &lt;/span&gt;&lt;span class='nv'&gt;this&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;seq &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;this&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='nv'&gt;this&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;equiv&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;_&lt;/span&gt; &lt;span class='nv'&gt;_&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='nv'&gt;false&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;def &lt;/span&gt;&lt;span class='nv'&gt;s&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;crazy-seq&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='nv'&gt;inc&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='c1'&gt;; hold head&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;dorun &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;take &lt;/span&gt;&lt;span class='mi'&gt;100000000&lt;/span&gt; &lt;span class='nv'&gt;s&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='c1'&gt;; low fat&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;nth &lt;/span&gt;&lt;span class='nv'&gt;s&lt;/span&gt; &lt;span class='mi'&gt;10&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='c1'&gt;; recomputes&lt;/span&gt;
&lt;span class='c1'&gt;;=&amp;gt; 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;A normal lazy seq is made up of a car and a function that returns the cdr, which is then cached.&lt;/p&gt;

&lt;p&gt;This means that if you store the first item and walk to the millionth, it will keep all these million items in memory.&lt;/p&gt;

&lt;p&gt;What crazy-seq does, is that it simply does not cache the value. So you can walk to the millionth item, and it will only store the first and the current, the others are GC&amp;#8217;d.&lt;/p&gt;

&lt;p&gt;This means that walking twice will cost more CPU cycles, and it means that you get in trouble if the fn is not side-effect free.&lt;/p&gt;

&lt;p&gt;Have fun.&lt;/p&gt;</content>
		
		<category term="clojure" />
		
	</entry>
	
	<entry>
		<title>Sciento CS-113</title>
		<link href="http://pepijndevos.nl/2012/04/09/sciento-cs-113.html"/>
		<updated>2012-04-09T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2012/04/09/sciento-cs-113</id>
		<content type="html">&lt;iframe src='http://www.youtube.com/embed/2R5WW9qNwEg' allowfullscreen='allowfullscreen' frameborder='0' height='315' width='560'&gt; &lt;/iframe&gt;
&lt;p&gt;After my success with the Cyber arm, I had to try my luck at the Sciento one.&lt;/p&gt;

&lt;p&gt;This time I was out of luck with Dutch or English documentation, but my brother found a &lt;a href='http://translate.google.com/translate?sl=auto&amp;amp;tl=en&amp;amp;js=n&amp;amp;prev=_t&amp;amp;hl=en&amp;amp;ie=UTF-8&amp;amp;layout=2&amp;amp;eotf=1&amp;amp;u=http%3A%2F%2Frobotica.udl.cat%2Fbrazo_robot%2Flabview%2Frobotcs113.pdf&amp;amp;act=url'&gt;Spanish PDF, from which I was able to get the needed information using Google Translate.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unlike the Cyber, the Sciento is controlled by sending actual ASCII commands, rather than stepping the motors directly.&lt;/p&gt;

&lt;p&gt;It is a lot smarter than the other arm, as it can remember its position. A list of commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&amp;#8221;Z&amp;#8221; Sets the reference point&lt;/li&gt;

&lt;li&gt;&amp;#8221;N&amp;#8221; Go to the reference position&lt;/li&gt;

&lt;li&gt;&amp;#8221;C&amp;#8221;/&amp;#8221;O&amp;#8221; Close/open the claw&lt;/li&gt;

&lt;li&gt;&amp;#8220;M100,0,-250,0,0,0&amp;#8221; Move the motors for the specified steps.&lt;/li&gt;

&lt;li&gt;&amp;#8220;H7&amp;#8221; Save the current position in the specified register(1-100)&lt;/li&gt;

&lt;li&gt;&amp;#8220;P5,500,200,-5,0,0,0&amp;#8221; Save the specified position in the specified register(first number, 1-100)&lt;/li&gt;

&lt;li&gt;&amp;#8220;G1&amp;#8221; Move to the location in the specified register&lt;/li&gt;

&lt;li&gt;&amp;#8220;S5&amp;#8221; Set the motor speed(1-5)&lt;/li&gt;

&lt;li&gt;&amp;#8220;D1&amp;#8221; Wait for x seconds. Useless?&lt;/li&gt;

&lt;li&gt;&amp;#8220;L1&amp;#8221; Check the limits of the motors. Recommended for testing, off by default.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that numbers are represented as ASCII text and that commands are upper-case. All commands are terminated by a carriage return.&lt;/p&gt;

&lt;p&gt;A downside to this arm is that in comparison to the one-byte commands for the Cyber, it takes ages to send an ASCII command across, making this arm unsuitable for smooth control with a gamepad.&lt;/p&gt;

&lt;p&gt;I programmed a coarse and ugly controller, with buttons for storing positions and moving to them. In the video I&amp;#8217;m just stepping through the motions I stored earlier.&lt;/p&gt;

&lt;p&gt;The controller is a real mess, based on the Cyber code, and not very interesting.&lt;/p&gt;

&lt;p&gt;The code for the arm itself is nice though. Note the use of the actual strobe line, as opposed to the strobe bit in the Cyber code.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='python'&gt;&lt;span class='kn'&gt;import&lt;/span&gt; &lt;span class='nn'&gt;parallel&lt;/span&gt;
&lt;span class='kn'&gt;from&lt;/span&gt; &lt;span class='nn'&gt;time&lt;/span&gt; &lt;span class='kn'&gt;import&lt;/span&gt; &lt;span class='n'&gt;sleep&lt;/span&gt;

&lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;parallel&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Parallel&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;write&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='n'&gt;bs&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;ord&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='n'&gt;bs&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;append&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;13&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='n'&gt;bs&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
        &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;setData&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;setDataStrobe&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;setDataStrobe&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='n'&gt;sleep&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mf'&gt;0.001&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;command&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;cmd&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='n'&gt;write&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;cmd&lt;/span&gt;&lt;span class='o'&gt;+&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;,&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;join&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;str&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;move&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;m1&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m2&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m3&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m4&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m5&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m6&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='s'&gt;&amp;quot;Move a number of steps&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;command&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;M&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m3&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m4&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m5&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m6&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;here&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='s'&gt;&amp;quot;Save current position in slot n 1-100&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;command&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;H&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;position&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m3&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m4&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m5&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m6&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='s'&gt;&amp;quot;Save the specified position in slot n 1-100&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;command&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;P&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m2&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m3&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m4&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m5&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;m6&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;zero&lt;/span&gt;&lt;span class='p'&gt;():&lt;/span&gt;
    &lt;span class='s'&gt;&amp;quot;Set the reference point&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;command&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;Z&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;goto&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='s'&gt;&amp;quot;Go to position in slot n 1-100&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;command&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;G&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;home&lt;/span&gt;&lt;span class='p'&gt;():&lt;/span&gt;
    &lt;span class='s'&gt;&amp;quot;Return to the reference&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;command&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;N&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;open&lt;/span&gt;&lt;span class='p'&gt;():&lt;/span&gt;
    &lt;span class='s'&gt;&amp;quot;open the claw&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;command&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;O&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;close&lt;/span&gt;&lt;span class='p'&gt;():&lt;/span&gt;
    &lt;span class='s'&gt;&amp;quot;Close the claw&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;command&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;speed&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='s'&gt;&amp;quot;Set the speed 1-5&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;command&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;S&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;delay&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='s'&gt;&amp;quot;Wait for n seconds&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;command&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;D&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;limit&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='s'&gt;&amp;quot;enable/disable limits&amp;quot;&lt;/span&gt;
    &lt;span class='n'&gt;commands&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;L&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</content>
		
		<category term="roboticarm" />
		
		<category term="python" />
		
		<category term="pygame" />
		
		<category term="pyparallel" />
		
	</entry>
	
	<entry>
		<title>Cyber 310</title>
		<link href="http://pepijndevos.nl/2012/04/07/cyber-310.html"/>
		<updated>2012-04-07T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2012/04/07/cyber-310</id>
		<content type="html">&lt;iframe src='http://www.youtube.com/embed/mZr161tNlqI' allowfullscreen='allowfullscreen' frameborder='0' height='315' width='560'&gt; &lt;/iframe&gt;
&lt;p&gt;We got 2 robotic arms from a school lab that did them away. After we got them, they had been accumulating dust for ages in our shed, with one failed attempt at making them work in between.&lt;/p&gt;

&lt;p&gt;This was my second attempt. As you can imagine, there aren&amp;#8217;t nearly as many people writing about robotic arms as there are writing about Clojure or Node.js, so documentation is sparse.&lt;/p&gt;

&lt;p&gt;The most useful (English!) resource I found was &lt;a href='http://www.anf.nildram.co.uk/beebcontrol/arms/cyber/documents.html'&gt;this collection&lt;/a&gt;, which has original manual pages he got from a museum(!). I contacted him for a couple more pages, which where very helpful.&lt;/p&gt;

&lt;p&gt;I can only say it was very hard to find out how easy it was to control this arm.&lt;/p&gt;

&lt;p&gt;Basically, you have one pin for every motor, and 2 control pins. To send a command you just set the motor pins, and then turn the corresponding toggle pin on and off.&lt;/p&gt;

&lt;p&gt;To reverse motor 2:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;01000000
01000001
01000000&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To turn motor 3 one step:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;00100000
00100010
00100000&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once I figured that out, I probably spent most of my time installing stuff on Windows, then installing Ubuntu and installing there.&lt;/p&gt;

&lt;p&gt;To make PyParallel work, I had to &lt;code&gt;rmmod lp&lt;/code&gt; and to run as root.&lt;/p&gt;

&lt;p&gt;The code, might you have a dusty Cyber 310 in your shed:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='python'&gt;&lt;span class='kn'&gt;import&lt;/span&gt; &lt;span class='nn'&gt;parallel&lt;/span&gt;
&lt;span class='kn'&gt;from&lt;/span&gt; &lt;span class='nn'&gt;time&lt;/span&gt; &lt;span class='kn'&gt;import&lt;/span&gt; &lt;span class='n'&gt;sleep&lt;/span&gt;

&lt;span class='n'&gt;base&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;
&lt;span class='n'&gt;shoulder&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;
&lt;span class='n'&gt;elbow&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt;
&lt;span class='n'&gt;leftwrist&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;8&lt;/span&gt;
&lt;span class='n'&gt;rightwrist&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;16&lt;/span&gt;
&lt;span class='n'&gt;grip&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;32&lt;/span&gt;
&lt;span class='n'&gt;prf&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;64&lt;/span&gt;
&lt;span class='n'&gt;strobe&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;128&lt;/span&gt;

&lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;parallel&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Parallel&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;direction&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;setData&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;setData&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='o'&gt;+&lt;/span&gt;&lt;span class='n'&gt;strobe&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;setData&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;step&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;setData&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;setData&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='o'&gt;+&lt;/span&gt;&lt;span class='n'&gt;prf&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;move&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;steps&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;motors&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='n'&gt;dir_pattern&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;abs&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;sum&lt;/span&gt;&lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt; &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;m&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='n'&gt;motors&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;m&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;]))&lt;/span&gt;
    &lt;span class='n'&gt;step_pattern&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;sum&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;abs&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;motors&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
    
    &lt;span class='n'&gt;direction&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;dir_pattern&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='nb'&gt;range&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;steps&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
        &lt;span class='n'&gt;step&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;step_pattern&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='n'&gt;sleep&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mf'&gt;0.01&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='python'&gt;&lt;span class='kn'&gt;import&lt;/span&gt; &lt;span class='nn'&gt;os&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nn'&gt;pygame&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nn'&gt;cyber&lt;/span&gt;
&lt;span class='kn'&gt;from&lt;/span&gt; &lt;span class='nn'&gt;time&lt;/span&gt; &lt;span class='kn'&gt;import&lt;/span&gt; &lt;span class='n'&gt;sleep&lt;/span&gt;

&lt;span class='n'&gt;os&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;environ&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;SDL_VIDEODRIVER&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;dummy&amp;quot;&lt;/span&gt;
&lt;span class='n'&gt;pygame&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;display&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;init&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
&lt;span class='n'&gt;pygame&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;init&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
&lt;span class='n'&gt;j&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;pygame&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;joystick&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Joystick&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;init&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;

&lt;span class='c'&gt;#axes = {cyber.base:0, cyber.shoulder:1, cyber.elbow:2, cyber.leftwrist:3, cyber.rightwrist:4, cyber.grip:5}&lt;/span&gt;
&lt;span class='n'&gt;axes&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='n'&gt;cyber&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;base&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='n'&gt;cyber&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;shoulder&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='n'&gt;cyber&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;elbow&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='mi'&gt;4&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;dead_int&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;real&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;deadzone&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='mf'&gt;0.5&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;real&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;deadzone&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;
    &lt;span class='k'&gt;elif&lt;/span&gt; &lt;span class='n'&gt;real&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='n'&gt;deadzone&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;
    &lt;span class='k'&gt;else&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;

&lt;span class='k'&gt;print&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;Initialized Joystick : &lt;/span&gt;&lt;span class='si'&gt;%s&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;&lt;/span&gt; &lt;span class='o'&gt;%&lt;/span&gt; &lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get_name&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
&lt;span class='k'&gt;try&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
    &lt;span class='k'&gt;while&lt;/span&gt; &lt;span class='bp'&gt;True&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
        &lt;span class='n'&gt;pygame&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;event&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;pump&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
        &lt;span class='c'&gt;#sleep(0.01)&lt;/span&gt;
        &lt;span class='n'&gt;movements&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;dead_int&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get_axis&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;v&lt;/span&gt; &lt;span class='ow'&gt;in&lt;/span&gt; &lt;span class='n'&gt;axes&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;iteritems&lt;/span&gt;&lt;span class='p'&gt;()]&lt;/span&gt;

	&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;y&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get_hat&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
	&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='ow'&gt;and&lt;/span&gt; &lt;span class='n'&gt;y&lt;/span&gt; &lt;span class='o'&gt;!=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
		&lt;span class='n'&gt;wr&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;cyber&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;leftwrist&lt;/span&gt;&lt;span class='o'&gt;+&lt;/span&gt;&lt;span class='n'&gt;cyber&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;rightwrist&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='n'&gt;y&lt;/span&gt;
		&lt;span class='n'&gt;movements&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;append&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;wr&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
	&lt;span class='k'&gt;elif&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;!=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='ow'&gt;and&lt;/span&gt; &lt;span class='n'&gt;y&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
		&lt;span class='n'&gt;movements&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;append&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;cyber&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;leftwrist&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
		&lt;span class='n'&gt;movements&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;append&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;cyber&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;rightwrist&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

	&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get_button&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
		&lt;span class='n'&gt;movements&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;append&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;cyber&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;grip&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
	&lt;span class='k'&gt;elif&lt;/span&gt; &lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get_button&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
		&lt;span class='n'&gt;movements&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;append&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='n'&gt;cyber&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;grip&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;	

        &lt;span class='n'&gt;cyber&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;move&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;movements&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        
&lt;span class='k'&gt;except&lt;/span&gt; &lt;span class='ne'&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
    &lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;quit&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</content>
		
		<category term="roboticarm" />
		
		<category term="python" />
		
		<category term="pygame" />
		
		<category term="pyparallel" />
		
	</entry>
	
	<entry>
		<title>Lat/Lon to Meter</title>
		<link href="http://pepijndevos.nl/2012/03/26/latlon-to-meter.html"/>
		<updated>2012-03-26T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2012/03/26/latlon-to-meter</id>
		<content type="html">&lt;p&gt;Easy, 1 Latitude is the circumference of the earth divided by 360: 111 km&lt;/p&gt;

&lt;p&gt;1 Longitude depends on your Latitude, so… copy-paste&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;math.radians(6378137.0 * math.cos(math.radians(lat)))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, I know this all breaks down horribly when you consider large distances or require high precision(it also upsets mathematicians), but I don&amp;#8217;t care(much).&lt;/p&gt;

&lt;p&gt;All I&lt;sup id='fnref:1'&gt;&lt;a href='#fn:1' rel='footnote'&gt;1&lt;/a&gt;&lt;/sup&gt; am interested in is, if I stand at 42° Latitude and I walk North 10 meter, about what is my new Latitude?&lt;/p&gt;
&lt;div class='footnotes'&gt;&lt;hr /&gt;&lt;ol&gt;&lt;li id='fn:1'&gt;
&lt;p&gt;And probably half the googlers and questioners on Stack Overflow.&lt;/p&gt;
&lt;a href='#fnref:1' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content>
		
		<category term="math" />
		
	</entry>
	
	<entry>
		<title>Thoughts about generating stripboard layouts</title>
		<link href="http://pepijndevos.nl/2012/03/13/thoughts-about-generating-stripboard-layouts.html"/>
		<updated>2012-03-13T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2012/03/13/thoughts-about-generating-stripboard-layouts</id>
		<content type="html">&lt;p&gt;I am at the moment working on a servo controller for the &lt;a href='http://mindstorms.lego.com/'&gt;LEGO NXT&lt;/a&gt; based on the &lt;a href='http://www.picaxe.com/'&gt;PICAXE 20X2&lt;/a&gt;&lt;sup id='fnref:1'&gt;&lt;a href='#fn:1' rel='footnote'&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;When you design a circuit, you usually use schematics like these:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/picaxe_project_board.png' alt='schematic' /&gt;&lt;/p&gt;

&lt;p&gt;However, when you actually want to solder the circuit, you either get a &lt;abbr title='Printed Circuit Board'&gt;PCB&lt;/abbr&gt;, or you use stripboard, which looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/588px-Stripboard.jpg' alt='stripboard' /&gt;&lt;/p&gt;

&lt;p&gt;It is basically a board full of holes, with horizontal copper lanes connecting rows of holes.&lt;/p&gt;

&lt;p&gt;All you have to do is insert the pieces so that things that should connect are on the same lane. To make things even easier, you can break lanes, or join lanes with a wire link.&lt;/p&gt;

&lt;p&gt;Wait a moment… If we lay out the components like on the schematic, nothing will connect correctly!&lt;/p&gt;

&lt;p&gt;Right, this brings me to the meat of this post. How can we automate this, to get an optimal and flawless translation from what is basically a graph, to a set of lanes?&lt;/p&gt;

&lt;p&gt;I think the best tool for this job is constraint logic programming, of which &lt;a href='http://www.schemeworkshop.org/2011/papers/Alvis2011.pdf'&gt;cKanren&lt;/a&gt; is a neat implementation on top of MiniKanren.&lt;/p&gt;

&lt;p&gt;Our program is somewhat related to the N-Queens problem, for which a solution is implemented in &lt;a href='http://www.schemeworkshop.org/2011/papers/Alvis2011.pdf'&gt;section 4.2 in the cKanren paper&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In he N-Queens problem, N queens must be arranged on an NxN board, so that no queen attacks another queen. This is implemented using all-difffd&lt;sup id='fnref:2'&gt;&lt;a href='#fn:2' rel='footnote'&gt;2&lt;/a&gt;&lt;/sup&gt;, which forces the queens to all be on different rows, columns and diagonals.&lt;/p&gt;

&lt;p&gt;Likewise, we can require our components to be all-difffd when it comes to lanes, but our situation is a little more complicated.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Components have multiple points which have constraints of themselves&lt;sup id='fnref:3'&gt;&lt;a href='#fn:3' rel='footnote'&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;

&lt;li&gt;Lanes need to be broken under &lt;abbr title='Micro Controller'&gt;uC&lt;/abbr&gt;&amp;#8217;s and might be broken for compactness.&lt;/li&gt;

&lt;li&gt;Lanes might need to be joined with a wire link.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let me state right away that I have not solved all of these complications, but I&amp;#8217;ll let you in on my thought process.&lt;/p&gt;

&lt;p&gt;For starters, lets define lanes as a finite domain of numbers. This allows us to use all-difffd, but gets us in trouble when we need to express broken lines.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scheme'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;fresh&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;lane&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;infd&lt;/span&gt; &lt;span class='nv'&gt;lane&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;range&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='mi'&gt;50&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In this simplified version, I also just defined components as a list of points they are connected to. Components that are connected, use the same fresh variable. This also gets us into trouble when we insert wire links.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scheme'&gt;&lt;span class='nv'&gt;&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;run&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;q&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;fresh&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;l1&lt;/span&gt; &lt;span class='nv'&gt;l2&lt;/span&gt; &lt;span class='nv'&gt;l3&lt;/span&gt; &lt;span class='nv'&gt;l4&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;infd&lt;/span&gt; &lt;span class='nv'&gt;l1&lt;/span&gt; &lt;span class='nv'&gt;l2&lt;/span&gt; &lt;span class='nv'&gt;l3&lt;/span&gt; &lt;span class='nv'&gt;l4&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;range&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='mi'&gt;10&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;==&lt;/span&gt; &lt;span class='nv'&gt;q&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list &lt;/span&gt;&lt;span class='ss'&gt;&amp;#39;r1&lt;/span&gt; &lt;span class='nv'&gt;l1&lt;/span&gt; &lt;span class='nv'&gt;l2&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list &lt;/span&gt;&lt;span class='ss'&gt;&amp;#39;r2&lt;/span&gt; &lt;span class='nv'&gt;l3&lt;/span&gt; &lt;span class='nv'&gt;l4&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list &lt;/span&gt;&lt;span class='ss'&gt;&amp;#39;fet&lt;/span&gt; &lt;span class='nv'&gt;l1&lt;/span&gt; &lt;span class='nv'&gt;l3&lt;/span&gt; &lt;span class='nv'&gt;l2&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;distinctfd&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list &lt;/span&gt;&lt;span class='nv'&gt;l1&lt;/span&gt; &lt;span class='nv'&gt;l2&lt;/span&gt; &lt;span class='nv'&gt;l3&lt;/span&gt; &lt;span class='nv'&gt;l4&lt;/span&gt;&lt;span class='p'&gt;))))&lt;/span&gt;
&lt;span class='p'&gt;(((&lt;/span&gt;&lt;span class='nf'&gt;r1&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;r2&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;fet&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The result is rather boring, as it just echoes back what is connected to what. It does get a little more interesting when we add constraints.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scheme'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;define &lt;/span&gt;&lt;span class='nv'&gt;lanes&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;range&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='mi'&gt;50&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;define &lt;/span&gt;&lt;span class='nv'&gt;lane&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;lambda &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;l&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;infd&lt;/span&gt; &lt;span class='nv'&gt;l&lt;/span&gt; &lt;span class='nv'&gt;lanes&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;define &lt;/span&gt;&lt;span class='nv'&gt;resistor&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;lambda &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;l1&lt;/span&gt; &lt;span class='nv'&gt;l2&lt;/span&gt; &lt;span class='nv'&gt;r&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;fresh&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;l2+&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;lane&lt;/span&gt; &lt;span class='nv'&gt;l1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;lane&lt;/span&gt; &lt;span class='nv'&gt;l2&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;lane&lt;/span&gt; &lt;span class='nv'&gt;l2+&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;plusfd&lt;/span&gt; &lt;span class='nv'&gt;l2&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='nv'&gt;l2+&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;&amp;lt;fd&lt;/span&gt; &lt;span class='nv'&gt;l2+&lt;/span&gt; &lt;span class='nv'&gt;l1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;==&lt;/span&gt; &lt;span class='nv'&gt;r&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list &lt;/span&gt;&lt;span class='ss'&gt;&amp;#39;r&lt;/span&gt; &lt;span class='nv'&gt;l1&lt;/span&gt; &lt;span class='nv'&gt;l2&lt;/span&gt;&lt;span class='p'&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now we can get some valid resistor positions, and incorporate their constraints into the full application.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scheme'&gt;&lt;span class='nv'&gt;&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;run&lt;/span&gt; &lt;span class='mi'&gt;5&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;q&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;fresh&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;l1&lt;/span&gt; &lt;span class='nv'&gt;l2&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;resistor&lt;/span&gt; &lt;span class='nv'&gt;l1&lt;/span&gt; &lt;span class='nv'&gt;l2&lt;/span&gt; &lt;span class='nv'&gt;q&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nf'&gt;r&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;r&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;r&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;r&lt;/span&gt; &lt;span class='mi'&gt;5&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;r&lt;/span&gt; &lt;span class='mi'&gt;5&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='nv'&gt;&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;run&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;q&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;fresh&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;l1&lt;/span&gt; &lt;span class='nv'&gt;l2&lt;/span&gt; &lt;span class='nv'&gt;l3&lt;/span&gt; &lt;span class='nv'&gt;l4&lt;/span&gt; &lt;span class='nv'&gt;r1&lt;/span&gt; &lt;span class='nv'&gt;r2&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;infd&lt;/span&gt; &lt;span class='nv'&gt;l1&lt;/span&gt; &lt;span class='nv'&gt;l2&lt;/span&gt; &lt;span class='nv'&gt;l3&lt;/span&gt; &lt;span class='nv'&gt;l4&lt;/span&gt; &lt;span class='nv'&gt;lanes&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;resistor&lt;/span&gt; &lt;span class='nv'&gt;l1&lt;/span&gt; &lt;span class='nv'&gt;l2&lt;/span&gt; &lt;span class='nv'&gt;r1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;resistor&lt;/span&gt; &lt;span class='nv'&gt;l3&lt;/span&gt; &lt;span class='nv'&gt;l4&lt;/span&gt; &lt;span class='nv'&gt;r2&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;==&lt;/span&gt; &lt;span class='nv'&gt;q&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list &lt;/span&gt;&lt;span class='nv'&gt;r1&lt;/span&gt; &lt;span class='nv'&gt;r2&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list &lt;/span&gt;&lt;span class='ss'&gt;&amp;#39;fet&lt;/span&gt; &lt;span class='nv'&gt;l1&lt;/span&gt; &lt;span class='nv'&gt;l3&lt;/span&gt; &lt;span class='nv'&gt;l2&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;distinctfd&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list &lt;/span&gt;&lt;span class='nv'&gt;l1&lt;/span&gt; &lt;span class='nv'&gt;l2&lt;/span&gt; &lt;span class='nv'&gt;l3&lt;/span&gt; &lt;span class='nv'&gt;l4&lt;/span&gt;&lt;span class='p'&gt;))))&lt;/span&gt;
&lt;span class='p'&gt;(((&lt;/span&gt;&lt;span class='nf'&gt;r&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;r&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;fet&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;How to proceed from here? I don&amp;#8217;t know. I think we need to find a different representation for lanes, to support breaking and joining them.&lt;/p&gt;

&lt;p&gt;I started writing a goal called connectedo, to consider 2 lanes with a wire link between them as connected, but this is unfinished.&lt;/p&gt;
&lt;div class='footnotes'&gt;&lt;hr /&gt;&lt;ol&gt;&lt;li id='fn:1'&gt;
&lt;p&gt;COMPANY &amp;LT;3 CAPS&lt;/p&gt;
&lt;a href='#fnref:1' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;li id='fn:2'&gt;
&lt;p&gt;Called distinctfd in the code on Github.&lt;/p&gt;
&lt;a href='#fnref:2' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;li id='fn:3'&gt;
&lt;p&gt;Such as &amp;#8220;a resistor must span at least 4 holes&amp;#8221; and &amp;#8220;a &lt;abbr title='Micro Controller'&gt;uC&lt;/abbr&gt; has 2 continuous columns of pins with 2 columns between them&amp;#8221;&lt;/p&gt;
&lt;a href='#fnref:3' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content>
		
		<category term="clojure" />
		
		<category term="scheme" />
		
		<category term="minikanren" />
		
		<category term="ckanren" />
		
	</entry>
	
	<entry>
		<title>Hidden Pages in Wordpress</title>
		<link href="http://pepijndevos.nl/2012/01/02/hidden-pages-in-wordpress.html"/>
		<updated>2012-01-02T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/2012/01/02/hidden-pages-in-wordpress</id>
		<content type="html">&lt;p&gt;More often that not, I need to hide pages from the menu and search pages, when setting up a Wordpress blog.&lt;/p&gt;

&lt;p&gt;Usually for download and thank-you pages, or other stuff that is only accessible via a direct link.&lt;/p&gt;

&lt;p&gt;By default, Wordpress includes a visibility settings, which has 3 values.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Public &amp;#8211; anyone can see it.&lt;/li&gt;

&lt;li&gt;Protected &amp;#8211; Anyone with the password can see it.&lt;/li&gt;

&lt;li&gt;Private &amp;#8211; Only you can see it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of them is useful for my goals, however, some digging revealed that a small change would allow you to link directly to password protected pages.&lt;/p&gt;

&lt;p&gt;Copy wp-pass.php to unlock.php, and make the changes below.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='diff'&gt;&lt;span class='gd'&gt;--- wp-pass.php	2011-09-19 05:17:26.000000000 +0200&lt;/span&gt;
&lt;span class='gi'&gt;+++ unlock.php	2012-01-02 17:38:47.000000000 +0100&lt;/span&gt;
&lt;span class='gu'&gt;@@ -10,8 +10,8 @@&lt;/span&gt;
 require( dirname(__FILE__) . &amp;#39;/wp-load.php&amp;#39;);
 
 // 10 days
&lt;span class='gd'&gt;-setcookie(&amp;#39;wp-postpass_&amp;#39; . COOKIEHASH, stripslashes( $_POST[&amp;#39;post_password&amp;#39;] ), time() + 864000, COOKIEPATH);&lt;/span&gt;
&lt;span class='gi'&gt;+setcookie(&amp;#39;wp-postpass_&amp;#39; . COOKIEHASH, stripslashes( $_GET[&amp;#39;post_password&amp;#39;] ), time() + 864000, COOKIEPATH);&lt;/span&gt;
 
&lt;span class='gd'&gt;-wp_safe_redirect(wp_get_referer());&lt;/span&gt;
&lt;span class='gi'&gt;+wp_safe_redirect($_GET[&amp;#39;return&amp;#39;]);&lt;/span&gt;
 exit;
 ?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now you can simply link to &lt;a href='http://example.com/unlock.php?post_password=foobar&amp;amp;return=/thank-you/'&gt;http://example.com/unlock.php?post_password=foobar&amp;amp;return=/thank-you/&lt;/a&gt;&lt;/p&gt;</content>
		
		<category term="wordpress" />
		
	</entry>
	
	<entry>
		<title>Lego NXT With a Gamepad</title>
		<link href="http://pepijndevos.nl/2011/11/26/lego-nxt-with-a-gamepad.html"/>
		<updated>2011-11-26T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/11/26/lego-nxt-with-a-gamepad</id>
		<content type="html">&lt;iframe src='http://www.youtube.com/embed/IECaiDxiMYQ' allowfullscreen='allowfullscreen' frameborder='0' height='315' width='420'&gt; &lt;/iframe&gt;
&lt;p&gt;I built this robot a while back, but I can&amp;#8217;t stand the software that comes with the NXT, my own compiler isn&amp;#8217;t ready yet, and any other remote controls I found didn&amp;#8217;t work particularly well, if at all.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you want it done right, you have to do it yourself &amp;#8211; Bernd Paysan&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I threw together PyGame and nxt-python, and wrote my own little application to control the NXT. Notice that it looks very similar to &lt;a href='http://pepijndevos.nl/2010/04/control-the-mouse-with-a-joystick/index.html'&gt;this PyMouse code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have no building plans for the robot, it&amp;#8217;s the standard wheel base with my own pincer. I do have the code:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='python'&gt;&lt;span class='kn'&gt;import&lt;/span&gt; &lt;span class='nn'&gt;pygame&lt;/span&gt;
&lt;span class='kn'&gt;from&lt;/span&gt; &lt;span class='nn'&gt;nxt&lt;/span&gt; &lt;span class='kn'&gt;import&lt;/span&gt; &lt;span class='n'&gt;locator&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;motor&lt;/span&gt;
&lt;span class='kn'&gt;from&lt;/span&gt; &lt;span class='nn'&gt;time&lt;/span&gt; &lt;span class='kn'&gt;import&lt;/span&gt; &lt;span class='n'&gt;sleep&lt;/span&gt;

&lt;span class='c'&gt;# edit this to reflect your joystick axis and buttons&lt;/span&gt;
&lt;span class='n'&gt;axis&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;y&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;x*&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;y*&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='mi'&gt;5&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt;

&lt;span class='n'&gt;b&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;locator&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find_one_brick&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;

&lt;span class='n'&gt;left&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;motor&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Motor&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;motor&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;PORT_B&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='n'&gt;right&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;motor&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Motor&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;motor&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;PORT_A&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='n'&gt;action&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;motor&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Motor&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;motor&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;PORT_C&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='n'&gt;closed&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='bp'&gt;False&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;limit&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;nr&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;nr&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='mi'&gt;50&lt;/span&gt; &lt;span class='ow'&gt;or&lt;/span&gt; &lt;span class='n'&gt;nr&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;50&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nb'&gt;min&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;127&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nb'&gt;max&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;128&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;nr&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
    &lt;span class='k'&gt;else&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;move&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fwd&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;turn&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='n'&gt;lp&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;int&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='n'&gt;fwd&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='n'&gt;turn&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;100&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='n'&gt;rp&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;int&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='n'&gt;fwd&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='n'&gt;turn&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;100&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='n'&gt;left&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;limit&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;lp&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
    &lt;span class='n'&gt;right&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;limit&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;rp&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;pincer&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;button&lt;/span&gt;&lt;span class='p'&gt;):&lt;/span&gt;
    &lt;span class='k'&gt;global&lt;/span&gt; &lt;span class='n'&gt;closed&lt;/span&gt;
    &lt;span class='k'&gt;try&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;button&lt;/span&gt; &lt;span class='ow'&gt;and&lt;/span&gt; &lt;span class='ow'&gt;not&lt;/span&gt; &lt;span class='n'&gt;closed&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
            &lt;span class='n'&gt;closed&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='bp'&gt;True&lt;/span&gt;
            &lt;span class='n'&gt;action&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;turn&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='mi'&gt;40&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;70&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;emulate&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='bp'&gt;False&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='k'&gt;elif&lt;/span&gt; &lt;span class='ow'&gt;not&lt;/span&gt; &lt;span class='n'&gt;button&lt;/span&gt; &lt;span class='ow'&gt;and&lt;/span&gt; &lt;span class='n'&gt;closed&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
            &lt;span class='n'&gt;closed&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='bp'&gt;False&lt;/span&gt;
            &lt;span class='n'&gt;action&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;turn&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;30&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;70&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;emulate&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='bp'&gt;False&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;brake&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt;&lt;span class='bp'&gt;False&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='k'&gt;except&lt;/span&gt; &lt;span class='n'&gt;motor&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;BlockedException&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
        &lt;span class='k'&gt;print&lt;/span&gt; &lt;span class='n'&gt;action&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get_tacho&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;

&lt;span class='n'&gt;pygame&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;init&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
&lt;span class='n'&gt;j&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;pygame&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;joystick&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Joystick&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='c'&gt;# first joystick&lt;/span&gt;
&lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;init&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
&lt;span class='k'&gt;print&lt;/span&gt; &lt;span class='s'&gt;&amp;#39;Initialized Joystick : &lt;/span&gt;&lt;span class='si'&gt;%s&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;&lt;/span&gt; &lt;span class='o'&gt;%&lt;/span&gt; &lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get_name&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
&lt;span class='k'&gt;try&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
    &lt;span class='k'&gt;while&lt;/span&gt; &lt;span class='bp'&gt;True&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
        &lt;span class='n'&gt;pygame&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;event&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;pump&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
        &lt;span class='n'&gt;sleep&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mf'&gt;0.1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        
        &lt;span class='c'&gt;# get_axis returns a value between -1 and 1&lt;/span&gt;
        &lt;span class='n'&gt;move&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get_axis&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;axis&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;y&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;]),&lt;/span&gt; &lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get_axis&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;axis&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;]))&lt;/span&gt;
        &lt;span class='n'&gt;pincer&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get_button&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
        
&lt;span class='k'&gt;except&lt;/span&gt; &lt;span class='ne'&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;
    &lt;span class='n'&gt;j&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;quit&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</content>
		
		<category term="lego" />
		
		<category term="pygame" />
		
		<category term="nxt" />
		
		<category term="joystick" />
		
	</entry>
	
	<entry>
		<title>Twisted on Dotcloud</title>
		<link href="http://pepijndevos.nl/2011/11/22/twisted-on-dotcloud.html"/>
		<updated>2011-11-22T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/11/22/twisted-on-dotcloud</id>
		<content type="html">&lt;p&gt;A while back, I wrote a &lt;a href='http://pepijndevos.nl/Twemail/'&gt;Twisted email server&lt;/a&gt; that would sit between you and Twitter and let you reed and send tweets via email.&lt;/p&gt;

&lt;p&gt;With the advent of free cloud hosting, I thought it&amp;#8217;d be fun to put it online. I&amp;#8217;ll share with you how it&amp;#8217;s done, for those of you who are looking for a place to put your Twisted app.&lt;/p&gt;

&lt;p&gt;The major problem with these easy hosts is that they assume a simple WSGI app or a background worker, but then the background worker is not accessible from the outside.&lt;/p&gt;

&lt;p&gt;First I tried Heroku, then Dotcloud, and finally a couple of others, and just when I had given up, @solomonstre came in:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;＠pepijndevos dotcloud has beta support for arbitrary tcp/udp ports. Want to try? :)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After some fruitless tries, he shared &lt;a href='https://github.com/jpetazzo/python-worker-on-dotcloud'&gt;this repo&lt;/a&gt;, which contains scaffolding for a web-accessible Python worker.&lt;/p&gt;

&lt;p&gt;The core parts of this thing are dotcloud.yml, where you define a setup script, the ports you want, and the command to run your app.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;worker:
  type: custom
  buildscript: builder
  ports:
    smpt: tcp
    pop3: tcp
  process: ~/run
  approot: twemail
  environment:
    PYTHON_VERSION: 2.7&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;builder&lt;/code&gt; contains a whole lot of pip/virtualenv code, while &lt;code&gt;run&lt;/code&gt; contains something like &lt;code&gt;twistd -ny yourapp.tac&lt;/code&gt;.&lt;/p&gt;</content>
		
		<category term="twisted" />
		
		<category term="dotcloud" />
		
		<category term="python" />
		
		<category term="twitter" />
		
	</entry>
	
	<entry>
		<title>Study Group</title>
		<link href="http://pepijndevos.nl/2011/11/10/study-group.html"/>
		<updated>2011-11-10T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/11/10/study-group</id>
		<content type="html">&lt;p&gt;I&amp;#8217;m starting a study group in Loenen (Gelderland), and you are invited. The primary focus of the group will be on programming and computer science.&lt;/p&gt;

&lt;p&gt;After having been to several learning institutions, I found out it&amp;#8217;s not something that works for me. I like to study at my own pace, whatever it is that I want to study.&lt;/p&gt;

&lt;p&gt;However, I found that collaborating and peer learning make things a lot more fun. Therefore I want to organize a study group, to learn and create together.&lt;/p&gt;

&lt;p&gt;Do you want to join? To work out the details, and to facilitate further discussion, I have created a &lt;a href='http://wishfulcoding.nl/studygroup/'&gt;wiki&lt;/a&gt; and a &lt;a href='http://groups.google.com/group/studygroupveluwe'&gt;mailing list&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I sketched out a few things that&amp;#8217;d work for me, but if you feel like &amp;#8220;I want to join, but…&amp;#8221;, speak up, nothing is set in stone.&lt;/p&gt;</content>
		
		<category term="programming" />
		
		<category term="learning" />
		
	</entry>
	
	<entry>
		<title>Vacuum Balloon</title>
		<link href="http://pepijndevos.nl/2011/11/09/vacuum-balloon.html"/>
		<updated>2011-11-09T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/11/09/vacuum-balloon</id>
		<content type="html">&lt;p&gt;You know these helium balloons? They float because helium is lighter, less dense then air. You know what is even lighter than air? No air at all!&lt;/p&gt;

&lt;p&gt;I came across the idea on &lt;a href='http://keithwiley.com/mindWanderings/vacuumBalloon.shtml'&gt;this website&lt;/a&gt;, where he notes&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I haven&amp;#8217;t done any math, but I assume this isn&amp;#8217;t feasible at the present time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I &lt;em&gt;have&lt;/em&gt; done some math, or rather, asked Wolfram Alpha.&lt;/p&gt;

&lt;p&gt;So, first of all, how heavy is a cubic meter of air anyaway?&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/wolframalpha-20111109043749224.gif' alt='weight of 1 cubic meter air' /&gt;&lt;/p&gt;

&lt;p&gt;Ok, so our balloon can weigh just over a kilo and still float. But what is the surface area of a balloon of that size?&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/wolframalpha-20111109044344634.gif' alt='surface area of a sphere of 1 cubic meter volume' /&gt;&lt;/p&gt;

&lt;p&gt;Almost five square meter. So with one kilo of matter, we need to make a balloon of nearly 5 square meter surface area.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/wolframalpha-20111109043833019.gif' alt='volume of 1280 g Al / 4.836 square meter' /&gt;&lt;/p&gt;

&lt;p&gt;Aww, not looking good. If we use aluminum&lt;sup id='fnref:1'&gt;&lt;a href='#fn:1' rel='footnote'&gt;1&lt;/a&gt;&lt;/sup&gt;, we can make a shell of a tenth of a millimeter thick. This shell will have to resist 1 bar, which equals 10 newton per square centimeter.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/wolframalpha-20111109055834761.gif' alt='pressure vessel formula' /&gt;&lt;/p&gt;

&lt;p&gt;I just &lt;a href='http://en.wikipedia.org/wiki/Pressure_vessel#Stress_in_thin-walled_pressure_vessels'&gt;picked this up from Wikipedia&lt;/a&gt;, but presumably this means the stress on the shell will be 3162 newton per square millimeter.&lt;/p&gt;

&lt;p&gt;Now, remember that this is a vacuum, so while a pressurized balloon retains it shape &lt;em&gt;because of&lt;/em&gt; the pressure, the biggest problem with our vacuum balloon is the buckling force.&lt;/p&gt;

&lt;p&gt;The smallest dent, a gust of wind, or even gravity itself, will cause the balloon to implode. I asked my dad&lt;sup id='fnref:2'&gt;&lt;a href='#fn:2' rel='footnote'&gt;2&lt;/a&gt;&lt;/sup&gt;, and he asked his engineer, how to calculate this force. Third order magic.&lt;/p&gt;
&lt;div class='footnotes'&gt;&lt;hr /&gt;&lt;ol&gt;&lt;li id='fn:1'&gt;
&lt;p&gt;We should be using carbon or some composite probably, but it doesn&amp;#8217;t really get much beyond 1mm anyway.&lt;/p&gt;
&lt;a href='#fnref:1' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;li id='fn:2'&gt;
&lt;p&gt;He&amp;#8217;s an architect.&lt;/p&gt;
&lt;a href='#fnref:2' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content>
		
		<category term="physics" />
		
		<category term="vacuum" />
		
	</entry>
	
	<entry>
		<title>Google Reader on Kindle</title>
		<link href="http://pepijndevos.nl/2011/11/04/google-reader-on-kindle.html"/>
		<updated>2011-11-04T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/11/04/google-reader-on-kindle</id>
		<content type="html">&lt;p&gt;I recently bought a &lt;a href='http://www.amazon.com/dp/B0051QYGXA?tag=wishcodi-20'&gt;Kindle&lt;/a&gt;, and I love it! It takes some effort to &lt;a href='http://willus.com/k2pdfopt/'&gt;convert scanned PDF books&lt;/a&gt;, but other than that, you just email stuff to Amazon, and it gets delivered.&lt;/p&gt;

&lt;p&gt;For long articles, I found that &lt;a href='http://www.instapaper.com'&gt;Instapaper&lt;/a&gt; has a &amp;#8216;Read Later&amp;#8217; bookmarklet, that can be configured to send a digest to my Kindle.&lt;/p&gt;

&lt;p&gt;The only hard part was Google Reader, so I thought I&amp;#8217;d share that with you. Reader has a &amp;#8216;Send To&amp;#8217; feature that can send articles to Kindle, but you have to go trough all the articles manually.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;ll have to involve an extra step, called &lt;a href='http://www.instascriber.com/'&gt;Instascriber&lt;/a&gt;. Instascriber lets you automatically send up to three feeds to Instapaper. Not enough for all my feeds, but luckily Reader has an RSS feed hidden deep down.&lt;/p&gt;

&lt;p&gt;The broad approach is to collect your feeds in a &lt;em&gt;public&lt;/em&gt; place in Google reader, so you can put the RSS feed in Instascriber, which submits them to Instapaper, which in turn emails them to Amazon, which then finally delivers the issue on my Kindle.&lt;/p&gt;

&lt;p&gt;Finding a public RSS feed in Reader is a bit tricky. Information I found about public folders and tags seemed outdated, with the new interface. What you need to do is, go to &amp;#8216;Browse for stuff&amp;#8217;, and create a bundle there.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/googlereader.png' alt='image of google reader' /&gt;&lt;/p&gt;

&lt;p&gt;When you&amp;#8217;re done, you need to figure out how to get the feed. I did this by clicking &amp;#8216;Add a link&amp;#8217;, to get to the public page. Depending on your browser, you might already see the RSS icon there. For FireFox, it can be found by pressing CMD+I and going to the &amp;#8216;Feeds&amp;#8217; tab.&lt;/p&gt;

&lt;p&gt;For reference, this is what my feed looks like &lt;a href='http://www.google.com/reader/public/atom/user%2F09723460687514136094%2Fbundle%2Fkindle'&gt;http://www.google.com/reader/public/atom/user%2F09723460687514136094%2Fbundle%2Fkindle&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From here on, it&amp;#8217;s standard form-filling and do-as-you-are-told business.&lt;/p&gt;

&lt;p&gt;First register at Instapaper, and set up Kindle delivery &lt;a href='http://www.instapaper.com/user/kindle'&gt;according to their instructions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, register at Instascriber, enter the Reader feed, and enjoy reading!&lt;/p&gt;</content>
		
		<category term="kindle" />
		
		<category term="googlereader" />
		
		<category term="rss" />
		
	</entry>
	
	<entry>
		<title>Clojure Wiki Gitorial</title>
		<link href="http://pepijndevos.nl/2011/10/23/clojure-wiki-gitorial.html"/>
		<updated>2011-10-23T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/10/23/clojure-wiki-gitorial</id>
		<content type="html">&lt;p&gt;At the last &lt;a href='http://groups.google.com/group/amsterdam-clojurians'&gt;Amsterdam Clojurians&lt;/a&gt; meetup, I gave a presentation with &lt;a href='https://twitter.com/neotyk'&gt;Hubert Iwaniuk&lt;/a&gt;, in which I wrote a wiki in 15 minutes, and Hubert explained what I was doing.&lt;/p&gt;

&lt;p&gt;Unfortunately no video is available, but I made a Gitorial out of it to show you what I did. Typos included.&lt;/p&gt;

&lt;p&gt;commit &lt;a href='https://github.com/pepijndevos/Clojure-Micro-Wiki/commit/9d2f91089dadbe795a16da9d84cb0da33cea9a37'&gt;9d2f91089dadbe795a16da9d84cb0da33cea9a37&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Welcome to this gitorial. I just created an empty Leiningen project with &lt;code&gt;lein new wiki&lt;/code&gt; and initiated git with &lt;code&gt;git init&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;commit &lt;a href='https://github.com/pepijndevos/Clojure-Micro-Wiki/commit/e2156be6cbfc421e384ebb016699497501395131'&gt;e2156be6cbfc421e384ebb016699497501395131&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I&amp;#8217;m using Ring for serving my application, and Moustache for routing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;commit &lt;a href='https://github.com/pepijndevos/Clojure-Micro-Wiki/commit/1898d45e54d1ae6045742f8e5db3b8fbc1fb7141'&gt;1898d45e54d1ae6045742f8e5db3b8fbc1fb7141&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I defined a router that will at this point match an empty address and return &amp;#8220;hello world&amp;#8221;. The -main function can be run with &lt;code&gt;lein run -m
wiki.core&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Browsing to &lt;a href='http://localhost:8080/'&gt;http://localhost:8080/&lt;/a&gt; now should display &amp;#8220;hello world&amp;#8221;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;commit &lt;a href='https://github.com/pepijndevos/Clojure-Micro-Wiki/commit/5e68a78f30586ad5313072201df25e5b1eea76ac'&gt;5e68a78f30586ad5313072201df25e5b1eea76ac&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A lot is going on here, form top to bottom:&lt;/p&gt;

&lt;p&gt;I imported some Ring middleware. These modify the request and response on the fly. Note that wrap-reload and wrap-stacktrace are for debuging only.&lt;/p&gt;

&lt;p&gt;I added the middleware to the Moustache app.&lt;/p&gt;

&lt;p&gt;I added routes. The first route matches and WikiLink and binds it to title. The second one redirects all other links to the MainPage.&lt;/p&gt;

&lt;p&gt;The #&amp;#8217; syntax is for getting the var instead of the value, to make reloading work.&lt;/p&gt;

&lt;p&gt;At this point, visiting the same url should redirect to /MainPage and display &amp;#8220;hello tester&amp;#8221;&lt;/p&gt;

&lt;p&gt;Changing this text does not require a server restart, so we can keep it running from now on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;commit &lt;a href='https://github.com/pepijndevos/Clojure-Micro-Wiki/commit/ae78c9d640420d0154b22c66df581fa684b8aa48'&gt;ae78c9d640420d0154b22c66df581fa684b8aa48&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I lied, to add a new dependency, you need to restart the server.&lt;/p&gt;

&lt;p&gt;Hiccup is a DSL for generating HTML.&lt;/p&gt;

&lt;p&gt;I defined a HTML template and a function for showing it that takes a request and a title.&lt;/p&gt;

&lt;p&gt;Note that I used the underscore to denote we&amp;#8217;re not using the request.&lt;/p&gt;

&lt;p&gt;Delegate is a HOF that returns a function with the title alreadu supplied. Moustache supplies the request.&lt;/p&gt;

&lt;p&gt;Try visiting /FooBar now.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;commit &lt;a href='https://github.com/pepijndevos/Clojure-Micro-Wiki/commit/cd24f552f7eefb470ac7b4357d01486e0fc9c888'&gt;cd24f552f7eefb470ac7b4357d01486e0fc9c888&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I added Clutch as a dependency. Clutch is a library for CouchDB.&lt;/p&gt;

&lt;p&gt;Install CouchDB and use Futon to create a wiki database and insert a &amp;#8220;MainPage&amp;#8221; document with a &amp;#8220;content&amp;#8221; key.&lt;/p&gt;

&lt;p&gt;I defined my own Ring middleware that takes a handler and returns another function that calls the old handler in the context of our database.&lt;/p&gt;

&lt;p&gt;The show function now gets a document from the database and passes its content to page.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;commit &lt;a href='https://github.com/pepijndevos/Clojure-Micro-Wiki/commit/f0c831708f397137b9aadf397376de2202f5cd60'&gt;f0c831708f397137b9aadf397376de2202f5cd60&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can now edit and create pages.&lt;/p&gt;

&lt;p&gt;Page now takes a revision, which is used in the web form to update.&lt;/p&gt;

&lt;p&gt;The update function does use the request object, and uses destructuring to extracts form data as parsed by wrap-params.&lt;/p&gt;

&lt;p&gt;Depending if a revision was supplied, a new document is created or an existing one updated. Then, the page is shown.&lt;/p&gt;

&lt;p&gt;Note how Moustache now delegates POST requests to update and GET requests to show.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;commit &lt;a href='https://github.com/pepijndevos/Clojure-Micro-Wiki/commit/11588b8f1e591ea6415515ffa21e70ed630eef91'&gt;11588b8f1e591ea6415515ffa21e70ed630eef91&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I added a Java library for Markdown parsing.&lt;/p&gt;

&lt;p&gt;The markup function also replaces WikiLinks with an HTML link.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;commit &lt;a href='https://github.com/pepijndevos/Clojure-Micro-Wiki/commit/235c551d57786f79c1867452de37b079a59606bd'&gt;235c551d57786f79c1867452de37b079a59606bd&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Getting ready for deployment.&lt;/p&gt;

&lt;p&gt;I removed the debugging wrappers and the var syntax(#&amp;#8217;wiki).&lt;/p&gt;

&lt;p&gt;Jetty now gets the port number from the environment/Foreman. This means it now runs at port 5000.&lt;/p&gt;

&lt;p&gt;Install Foreman with &lt;code&gt;gem install foreman&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I added a Procfile according to &lt;a href='http://devcenter.heroku.com/articles/clojure'&gt;http://devcenter.heroku.com/articles/clojure&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</content>
		
		<category term="clojure" />
		
		<category term="tutorial" />
		
	</entry>
	
	<entry>
		<title>The Origin of Language</title>
		<link href="http://pepijndevos.nl/2011/10/22/the-origin-of-language.html"/>
		<updated>2011-10-22T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/10/22/the-origin-of-language</id>
		<content type="html">&lt;p&gt;Dutch is an interesting language. It seems we&amp;#8217;re at a crossroad of German, French and English influences.&lt;/p&gt;

&lt;p&gt;During the Roman empire, the river Rijn was the border of the Germanic and Roman empire, of which German and Italian are direct descendants&lt;sup id='fnref:1'&gt;&lt;a href='#fn:1' rel='footnote'&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Dutch is very close to German, but it was and is influenced by the &amp;#8216;world languages&amp;#8217; of the time. (The world was a lot smaller at that time) And so it happened that during 1800-1900 or so, French was spoken by the elite, and we where part of the French empire at times.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/map-europe.png' alt='Map of French and Roman empire' /&gt;&lt;/p&gt;

&lt;p&gt;If you look at a Dutch dictionary today, you can divide most words in 3 categories, Words that are a lot like German, Archaic and chic words from France and modern words from English.&lt;/p&gt;

&lt;p&gt;Dutch is a lot like Common Lisp or Scala&lt;sup id='fnref:2'&gt;&lt;a href='#fn:2' rel='footnote'&gt;2&lt;/a&gt;&lt;/sup&gt;. If we&amp;#8217;d make a cheesy map of Europe with languages and paradigms overlaid, you&amp;#8217;d see that natural languages are complected and &lt;em&gt;very&lt;/em&gt; multi-paradigm.&lt;/p&gt;

&lt;p&gt;Programming languages are much more designed, and mostly unambiguous, like Esperanto or Lojban. Computers don&amp;#8217;t like ambiguity. Some languages, like Scheme, are still designed for growth though.&lt;/p&gt;
&lt;embed src='http://video.google.com/googleplayer.swf?docid=-8860158196198824415&amp;hl=en&amp;fs=true' allowFullScreen='true' allowScriptAccess='always' id='VideoPlayback' type='application/x-shockwave-flash' style='width:400px;height:326px'&gt; &lt;/embed&gt;
&lt;p&gt;Near the end Guy Steele argues that programming languages need to be more like natural ones, and the other way around.&lt;/p&gt;

&lt;p&gt;As we have seen earlier, natural languages grow, and grow a lot. But I know from experience that adding words to your language that are not native, feels forced at times, does not go well with grammar, and leads to extra complexity.&lt;/p&gt;

&lt;p&gt;On the other hand, natural languages should be simpler. But I argue that this has nothing to do with syllables, but with choosing simple words with but one meaning, concerning one thing.&lt;/p&gt;

&lt;p&gt;But do our programming languages have this property? &lt;a href='http://www.infoq.com/presentations/Simple-Made-Easy'&gt;Rich Hickey argues this is often not the case, and explains the word &amp;#8216;simple&amp;#8217; in more detail.&lt;/a&gt;&lt;sup id='fnref:3'&gt;&lt;a href='#fn:3' rel='footnote'&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;I can only wonder what future languages will look like. Since our applications will be limited by our understanding, programming will be an art of omission and simplicity.&lt;/p&gt;

&lt;p&gt;Last video, I promise. &amp;#8216;Uncle Bob&amp;#8217; Martin shows us what progress we have made in software development. Not much, compared to &lt;a href='http://en.wikipedia.org/wiki/Moore&amp;apos;s_law'&gt;Moore&amp;#8217;s law&lt;/a&gt;. We&amp;#8217;re still programming Lisp, and doing assignment, branching and iteration.&lt;/p&gt;
&lt;iframe src='http://www.youtube.com/embed/mslMLp5bQD0' allowfullscreen='allowfullscreen' frameborder='0' height='315' width='560'&gt; &lt;/iframe&gt;
&lt;p&gt;What we did with structured programming, with object orientated programming and with functional programming, is taking stuff away. We converted conventions to rules.&lt;/p&gt;

&lt;p&gt;Maybe future languages will have rules about simplicity?&lt;/p&gt;
&lt;div class='footnotes'&gt;&lt;hr /&gt;&lt;ol&gt;&lt;li id='fn:1'&gt;
&lt;p&gt;I&amp;#8217;m not a historian, I never followed a single history lesson. Take with a spoon of salt.&lt;/p&gt;
&lt;a href='#fnref:1' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;li id='fn:2'&gt;
&lt;p&gt;More salt please; At least we&amp;#8217;re back at programming.&lt;/p&gt;
&lt;a href='#fnref:2' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;li id='fn:3'&gt;
&lt;p&gt;I can&amp;#8217;t seem to embed an InfoQ video.&lt;/p&gt;
&lt;a href='#fnref:3' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content>
		
		<category term="history" />
		
		<category term="language" />
		
		<category term="dutch" />
		
		<category term="clojure" />
		
	</entry>
	
	<entry>
		<title>My Bookshelf 5/5: Making Ideas Happen</title>
		<link href="http://pepijndevos.nl/2011/10/10/my-bookshelf-55-making-ideas-happen.html"/>
		<updated>2011-10-10T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/10/10/my-bookshelf-55-making-ideas-happen</id>
		<content type="html">&lt;p&gt;Great book, read it. And if you don&amp;#8217;t, scan &lt;a href='http://www.amazon.com/gp/reader/159184312X/ref=sib_dp_kd#reader-link'&gt;the index&lt;/a&gt;, it reads like a list of do&amp;#8217;s and don&amp;#8217;ts.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://www.amazon.com/gp/product/159184312X/ref=as_li_tf_tl?ie=UTF8&amp;amp;tag=wishcodi-20&amp;amp;linkCode=as2&amp;amp;camp=217145&amp;amp;creative=399381&amp;amp;creativeASIN=159184312X'&gt;&lt;img src='/images/mih.png' alt='Making Ideas Happen' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The book describes the Action Method, which resolves around persisting, following up, managing action steps(todo&amp;#8217;s that start with a verb) and relentless execution. It&amp;#8217;s not easy, but it makes sense.&lt;/p&gt;

&lt;p&gt;I actually read this book during summer holiday. I&amp;#8217;ve been, uh&amp;#8230; practicing since then. On thing that stuck with me in particular is that connectivity is inverse productivity.&lt;/p&gt;

&lt;p&gt;I found it much easier to focus on the action step at hand without all the distractions from email, IM, Twitter, etc. But when you are offline, you need to prepare yourself with all the docs and libs you need, put the whole internet on a floppy if you can&lt;sup id='fnref:1'&gt;&lt;a href='#fn:1' rel='footnote'&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src='http://www.wherestheanykey.co.uk/ComicImages/217.jpg' alt='Internet on a Floppy' /&gt;&lt;/p&gt;

&lt;p&gt;Behance &lt;a href='http://www.actionmethod.com/'&gt;developed a web application&lt;/a&gt; specifically for following the Action Method, but as you can imagine, having your task manager &amp;#8216;in the cloud&amp;#8217; while working offline, is not ideal.&lt;/p&gt;

&lt;p&gt;I need something that syncs between my laptop and my desktop, but works great offline. CouchDB seemed to fit the bill perfectly. After I started a homebrew solution and one based on the Backbone MVC framework, I found this.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Those who don&amp;#8217;t understand UNIX are condemned to reinvent it, poorly. &amp;#8211; Henry Spencer&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Why not use mighty tools such as text files and rsync(or Dropbox)? Googling for todo.txt shows I&amp;#8217;m not the first to have that idea. There is a more or less &lt;a href='https://github.com/ginatrapani/todo.txt-cli/wiki/The-Todo.txt-Format'&gt;agreed upon format&lt;/a&gt;, and even &lt;a href='http://elentok.blogspot.com/2011/06/qtodotxt-cross-platform-todotxt-gui.html'&gt;a GUI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Good luck with that, I&amp;#8217;m going back to my task list, which features cleaning the kitchen.&lt;/p&gt;
&lt;div class='footnotes'&gt;&lt;hr /&gt;&lt;ol&gt;&lt;li id='fn:1'&gt;
&lt;p&gt;Half of my action steps at the time consisted of &amp;#8220;Download X&amp;#8221;&lt;/p&gt;
&lt;a href='#fnref:1' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content>
		
		<category term="bookshelf" />
		
		<category term="review" />
		
	</entry>
	
	<entry>
		<title>Understand SQL, learn NoSQL</title>
		<link href="http://pepijndevos.nl/2011/10/04/understand-sql-learn-nosql.html"/>
		<updated>2011-10-04T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/10/04/understand-sql-learn-nosql</id>
		<content type="html">&lt;p&gt;I learned SQL when I started PHP. I found a website named &lt;a href='http://www.tizag.com/mysqlTutorial/'&gt;Tizag&lt;/a&gt;, where they had SQL tutorials. I installed PhpMyAdmin, created tables, ran queries like &lt;code&gt;SELECT * FROM pages WHERE foo IS bar LEFT JOIN ON comments&lt;/code&gt; or whatever. It was magic.&lt;/p&gt;

&lt;p&gt;No one ever explained to me how it stored the information, or how it was so fast (or slow). They did say that indexes made stuff faster, sometimes.&lt;/p&gt;

&lt;p&gt;On the other hand, when you read the CouchDB guide, they do not primarily teach you their query language, but also a lot about how stuff works. A lot of this also applies to SQL databases.&lt;/p&gt;

&lt;h3 id='storage'&gt;Storage&lt;/h3&gt;

&lt;p&gt;CouchDB uses a &lt;a href='http://en.wikipedia.org/wiki/B-tree'&gt;B-tree&lt;/a&gt; to store documents. This provides O(log n) lookup, update, etc. rather than O(n) scanning of all documents. It seems most SQL databases use a B-tree as well, but not always.&lt;/p&gt;

&lt;h3 id='indexes'&gt;Indexes&lt;/h3&gt;

&lt;p&gt;When you add a &lt;code&gt;WHERE&lt;/code&gt; clause to your query, the database has to look at all documents for a match.&lt;/p&gt;

&lt;p&gt;If you add an index to the field, you get a sorted representation of that field. This way you can get single items or ranges(&lt;code&gt;time &amp;gt; 123456&lt;/code&gt;) in logarithmic time, using binary search.&lt;/p&gt;

&lt;p&gt;CouchDB gives you a &amp;#8216;view&amp;#8217; of the &lt;code&gt;_id&lt;/code&gt; of a document, but other views will have to be created to create the equivalent of a &lt;code&gt;WHERE&lt;/code&gt; clause. (What &lt;code&gt;_id&lt;/code&gt; is in CouchDB, is your primary key in SQL)&lt;/p&gt;

&lt;h3 id='locking__transactions'&gt;Locking &amp;amp; Transactions&lt;/h3&gt;

&lt;p&gt;NoSQL databases are infamous for their lack of locking and transactions. Why? For the sake of scalability.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s ignore for a moment that 90% of all apps can run on a single server. The idea is that creating a transaction synchronously on a whole cluster is nearly impossible, let alone fast. So you you just don&amp;#8217;t to it at all, in NoSQL land.&lt;/p&gt;

&lt;p&gt;The flip side is that not locking at all allows reads to be faster. More on that in the next section.&lt;/p&gt;

&lt;p&gt;Interesting to note is that both CouchDB and PostgreSQL use &lt;a href='http://en.wikipedia.org/wiki/Multiversion_concurrency_control'&gt;MVCC&lt;/a&gt;, allowing for reads without locking. So this is not unique to NoSQL databases.&lt;/p&gt;

&lt;h3 id='history__recovery'&gt;History &amp;amp; Recovery&lt;/h3&gt;

&lt;p&gt;CouchDB stores its data in &lt;a href='http://www.bzero.se/ldapd/btree.html'&gt;append-only B-trees&lt;/a&gt;, meaning that data is never changed.&lt;/p&gt;

&lt;p&gt;Because old data is still there and immutable, readers can access it without waiting for a write to complete. It is even possible to read old revisions of the data.&lt;/p&gt;

&lt;p&gt;What is maybe even more interesting is that, if the server crashes in the middle of an update, the old data is still there.&lt;/p&gt;

&lt;p&gt;InnoDB also applies a similar technique, unlike Mysam, which needs to scan and repair the whole database.&lt;/p&gt;

&lt;h3 id='joins'&gt;Joins&lt;/h3&gt;

&lt;p&gt;Basically the same thing as transactions, you don&amp;#8217;t want to scavenge your whole cluster looking for all comments referencing a blogpost.&lt;/p&gt;

&lt;p&gt;The high-performance way to do joins is to not do joins, instead unlearn everything your learned about normalization, and &lt;a href='http://en.wikipedia.org/wiki/Denormalization'&gt;denormalize&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The other way to do it teaches us more about SQL joins though. Basically you create an index or view on the &amp;#8216;foreign key&amp;#8217;, and run a separate query to get the correct documents. Here is an &lt;a href='http://www.cmlenz.net/archives/2007/10/couchdb-joins'&gt;elaborate example&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id='conlusion'&gt;Conlusion&lt;/h3&gt;

&lt;p&gt;Neither SQL or NoSQL databases are magic, and they are even pretty similar in most ways. Don&amp;#8217;t follow the hype, choose wisely.&lt;/p&gt;</content>
		
		<category term="sql" />
		
		<category term="nosql" />
		
		<category term="couchdb" />
		
	</entry>
	
	<entry>
		<title>Minecraft 1.8 (P)review</title>
		<link href="http://pepijndevos.nl/2011/09/12/minecraft-18-review.html"/>
		<updated>2011-09-12T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/09/12/minecraft-18-review</id>
		<content type="html">&lt;p&gt;Like most Minecraft addicts&lt;sup id='fnref:1'&gt;&lt;a href='#fn:1' rel='footnote'&gt;1&lt;/a&gt;&lt;/sup&gt;, I downloaded the prerelease this weekend and played it all day. There are some really cool things in there, but also a few crapy ones, and of course a few bugs and glitches.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/2011-09-12_11.17.34.png' alt='My new home' /&gt;&lt;/p&gt;

&lt;p&gt;I rally love the new biomes. I spawned in a desert biome, and if it wasn&amp;#8217;t for the NPC village, I would have died for sure. Rivers are also great for exploring by boat.&lt;/p&gt;

&lt;p&gt;I really like all the stuff that is specific to certain biomes. Without compasses and maps, it&amp;#8217;s quite an adventure to get wood, animals and later vines and mushrooms from other biomes.&lt;/p&gt;

&lt;p&gt;There are quite a few odd new items, like Ender pearls, rotten meat, and huge mushrooms, but they win on atmosphere, so I built my home in a shroom. Beat that, treehouse!&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/2011-09-12_11.18.45.png' alt='Mineshaft' /&gt;&lt;/p&gt;

&lt;p&gt;The new map features all look really neat, but I found the abandoned mineshafts impossible to navigate. They cross right through strongholds, other caves and themselves.&lt;/p&gt;

&lt;p&gt;The only thing I rally don&amp;#8217;t like about the Adventure Update is the food and fighting mechanics. It&amp;#8217;s like playing Quake 3 on peaceful&lt;sup id='fnref:2'&gt;&lt;a href='#fn:2' rel='footnote'&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m not going to say anything about experience points, because I don&amp;#8217;t know what they will be used for, but let me say that I don&amp;#8217;t think Minecraft is a classic RPG.&lt;/p&gt;

&lt;p&gt;The idea of food healing you indirectly is really nice, but having it replenish my life slowly makes me play as reckless as if I&amp;#8217;m playing on peaceful. Maybe it could heal you while sleeping?&lt;/p&gt;

&lt;p&gt;When you run, you are able to jump 4 blocks. Though, mid-air, you go faster than running, so the fastest way to move is to jump running. I pray that running diagonally isn&amp;#8217;t even faster.&lt;/p&gt;

&lt;p&gt;There is a new fighting mechanic that lets you deal critical hits by jumping down on a mob while hitting. This means the best way to fight is to jump up and down.&lt;/p&gt;

&lt;p&gt;The last thing that adds to the Quake experience is hammering the mouse button. Previously, it was possible to place blocks and hit mobs by just holding the button, now you need to hammer the mouse like a real FPS. &lt;em&gt;dislike&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, overall, I really enjoy 1.8, but can I say it&amp;#8217;s having a bit of an identity crisis?&lt;/p&gt;
&lt;div class='footnotes'&gt;&lt;hr /&gt;&lt;ol&gt;&lt;li id='fn:1'&gt;
&lt;p&gt;Well, I played all Sunday, but except for that I don&amp;#8217;t play much.&lt;/p&gt;
&lt;a href='#fnref:1' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;li id='fn:2'&gt;
&lt;p&gt;I Play on hard.&lt;/p&gt;
&lt;a href='#fnref:2' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content>
		
		<category term="minecraft" />
		
		<category term="review" />
		
	</entry>
	
	<entry>
		<title>CSS tips and tricks</title>
		<link href="http://pepijndevos.nl/2011/08/17/css-tips-and-tricks.html"/>
		<updated>2011-08-17T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/08/17/css-tips-and-tricks</id>
		<content type="html">&lt;p&gt;While working on &lt;a href='https://github.com/pepijndevos/Sombrero'&gt;Sombrero&lt;/a&gt;, I encountered a lot of things I did not know how to do properly. I hope they help someone.&lt;/p&gt;

&lt;h2 id='width_cling'&gt;width: cling;&lt;/h2&gt;

&lt;p&gt;Block elements normally fill up all the available width, except when you apply &lt;code&gt;position&lt;/code&gt; or &lt;code&gt;float&lt;/code&gt; to them. I needed some element to take up the &lt;em&gt;minimal&lt;/em&gt; width, without the side effects of floating or positioning. &lt;code&gt;display: table;&lt;/code&gt; is the solution I was looking for.&lt;/p&gt;

&lt;h2 id='fullwidth_form_fields'&gt;Full-width form fields&lt;/h2&gt;

&lt;p&gt;Another problem in my magic alignment layout where full-width form fields. Input elements do not take space like normal block elements, no matter the &lt;code&gt;display&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;width: 100%;&lt;/code&gt; works, but only as long as you have absolutely no borders, margin, or padding. To get around that, CSS 3 has a property to use the IE 5 box model, which includes padding and borders in the width: &lt;code&gt;box-sizing: border-box;&lt;/code&gt;&lt;/p&gt;

&lt;h2 id='collapsing_margins'&gt;Collapsing margins&lt;/h2&gt;

&lt;p&gt;I can&amp;#8217;t imagine why I never noticed before, but it turns out CSS collapses margins on &amp;#8220;regular&amp;#8221; block elements. &lt;a href='http://reference.sitepoint.com/css/collapsingmargins'&gt;It&amp;#8217;s complicated&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id='display_runin'&gt;display: run-in;&lt;/h2&gt;

&lt;p&gt;I never used it, but it seems like an interesting property. It makes things like headings appear inline with the content of the block below it.&lt;/p&gt;

&lt;h2 id='styling_range_input_fields'&gt;Styling range input fields&lt;/h2&gt;

&lt;p&gt;Some modern browsers support input fields of &lt;code&gt;type=&amp;quot;range&amp;quot;&lt;/code&gt;, for imprecise number values. However, style on these elements is normally completely ignored.&lt;/p&gt;

&lt;p&gt;Bring in &lt;code&gt;-webkit-appearance: none;&lt;/code&gt;, which turns the slider track back into a normal box. Then apply the knob styling to the &lt;code&gt;::-webkit-slider-thumb&lt;/code&gt; pseudo element.&lt;/p&gt;

&lt;h2 id='position_all_four_corners'&gt;position all four corners&lt;/h2&gt;

&lt;p&gt;Another part in my alignment puzzle. Note that not all browsers support this. If you can&amp;#8217;t do with 2 sides plus size, it is possible to specify all 4 and leave the sizing implicit.&lt;/p&gt;</content>
		
		<category term="css" />
		
		<category term="sombrero" />
		
	</entry>
	
	<entry>
		<title>Playing Minecraft Offline</title>
		<link href="http://pepijndevos.nl/2011/08/11/playing-minecraft-offline.html"/>
		<updated>2011-08-11T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/08/11/playing-minecraft-offline</id>
		<content type="html">&lt;p&gt;Me and my friends like to play Minecraft sometimes, but it often happens to be in the middle of nowhere, without internet. The most interesting part is most often the setup, not the playing.&lt;/p&gt;

&lt;p&gt;We usually start by sharing the latest Minecraft binaries and setting up an ad-hoc WiFi network. Then someone boots a server, and we&amp;#8217;re set&amp;#8230; NOT!&lt;/p&gt;

&lt;p&gt;Minecraft usually performs some DRM and verification with the Minecraft website. For the server, this can be disabled by setting &lt;a href='http://www.minecraftwiki.net/wiki/Server.properties#online-mode'&gt;&lt;code&gt;online-mode&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; in &lt;code&gt;server.properties&lt;/code&gt;&lt;/a&gt;, but with the client, you&amp;#8217;re out of luck.&lt;/p&gt;

&lt;p&gt;Initially, the solution consisted of sending someone with a smartphone out to find an open WiFi network. Later, before the new launcher, it used to be possible to fake the login server&lt;sup id='fnref:1'&gt;&lt;a href='#fn:1' rel='footnote'&gt;1&lt;/a&gt;&lt;/sup&gt;. But recently, I found a way to play in offline mode on the client as well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spoiler alert&lt;/strong&gt;: Minecraft is The Matrix.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/mine_matrix.png' alt='Minecraft Matrix' /&gt;&lt;/p&gt;

&lt;p&gt;That&amp;#8217;s it. It had to be said. Now, let&amp;#8217;s hack Minecraft Matrix style.&lt;/p&gt;

&lt;p&gt;Normally, when you click &amp;#8220;Play Offline&amp;#8221; after a failed login, you are named &amp;#8220;Player&amp;#8221;, which means that you are going to kick each other because you all have the same name.&lt;/p&gt;

&lt;p&gt;Now, fire up your terminals&lt;sup id='fnref:2'&gt;&lt;a href='#fn:2' rel='footnote'&gt;2&lt;/a&gt;&lt;/sup&gt;, and change directory to the &lt;code&gt;bin&lt;/code&gt; folder of your Minecraft directory&lt;sup id='fnref:3'&gt;&lt;a href='#fn:3' rel='footnote'&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Now, I can&amp;#8217;t read and write Matrix like Mouse&lt;sup id='fnref:4'&gt;&lt;a href='#fn:4' rel='footnote'&gt;4&lt;/a&gt;&lt;/sup&gt;, but luckily, the GNU toolchain can. What we&amp;#8217;re going to do is change a few occurrences of &amp;#8220;Player&amp;#8221; with any string of equal length&lt;sup id='fnref:5'&gt;&lt;a href='#fn:5' rel='footnote'&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;The first step is to extract the jar. It turns out it works just fine as a directory, and it&amp;#8217;s much easier to work with that way.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mv minecraft.jar minecraft-orig.jar
mkdir minecraft.jar
cd minecraft.jar
jar -xf ../minecraft-orig.jar&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we need to figure out which files need to be modified. Beware of Déjà vu!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;grep -r Player .
# Binary file ./ei.class matches
# ./lang/stats_US.lang:stat.playerKills=Player Kills
# Binary file ./net/minecraft/client/Minecraft.class matches
# Binary file ./net/minecraft/client/MinecraftApplet.class matches
# Binary file ./ow.class matches&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Some experimentation shows that &lt;code&gt;MinecraftApplet.class&lt;/code&gt; is the one that matters. Now you need to use &lt;code&gt;sed&lt;/code&gt; to replace &amp;#8220;Player&amp;#8221; with another name of equal length.&lt;/p&gt;

&lt;p&gt;Mac users will need to install GNU sed, as BSD sed scrambles the binary file beyond repair. I used &lt;code&gt;brew install gnu-sed&lt;/code&gt;, but Macports and Fink might also work.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gsed -ibak s/Player/_Notch/g net/minecraft/client/MinecraftApplet.class&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Done!&lt;/p&gt;
&lt;div class='footnotes'&gt;&lt;hr /&gt;&lt;ol&gt;&lt;li id='fn:1'&gt;
&lt;p&gt;Not anymore, it uses SSL now.&lt;/p&gt;
&lt;a href='#fnref:1' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;li id='fn:2'&gt;
&lt;p&gt;Mac users can use the &amp;#8220;Homebrew&amp;#8221; style at fullscreen for extra Matrix factor.&lt;/p&gt;
&lt;a href='#fnref:2' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;li id='fn:3'&gt;
&lt;p&gt;Mac: &lt;code&gt;~/Library/Application\ Support/minecraft/bin&lt;/code&gt;, Linux: &lt;code&gt;~/.minecraft/bin&lt;/code&gt;, Windows: &lt;code&gt;~/.AppData/Roaming/.minecraft/bin&lt;/code&gt;&lt;/p&gt;
&lt;a href='#fnref:3' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;li id='fn:4'&gt;
&lt;p&gt;Mouse, please tell me how you wrote the lady in the red dress.&lt;/p&gt;
&lt;a href='#fnref:4' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;li id='fn:5'&gt;
&lt;p&gt;Equal length you hear me, you&amp;#8217;ll crash Minecraft otherwise.&lt;/p&gt;
&lt;a href='#fnref:5' rev='footnote'&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content>
		
		<category term="minecraft" />
		
		<category term="matrix" />
		
	</entry>
	
	<entry>
		<title>The NoSQL Burden</title>
		<link href="http://pepijndevos.nl/2011/07/29/the-nosql-burden.html"/>
		<updated>2011-07-29T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/07/29/the-nosql-burden</id>
		<content type="html">&lt;p&gt;Some people claim that &lt;a href='http://smoothspan.wordpress.com/2011/07/22/nosql-is-a-premature-optimization/'&gt;NoSQL is premature optimization&lt;/a&gt; and places an extra burden on the developer. The main points seem to be that NoSQL has no schemas and drops consistency in favour of the other parts of &lt;a href='http://en.wikipedia.org/wiki/CAP_theorem'&gt;CAP&lt;/a&gt;(availability, partitioning).&lt;/p&gt;

&lt;p&gt;I largely agree, however, I think we should differentiate between two kinds of NoSQL databases.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;ScaleDB: Hard-core MapReduce, thousands of nodes, sacrifices everything for speed and scalability. If you use this below Google-size, you have &lt;a href='http://www.xtranormal.com/watch/6995033/mongo-db-is-web-scale'&gt;no idea what you&amp;#8217;re doing&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;EasyDB: Relax, life is to short to update your schema and master SQL, give me an easy API to persist and query my data and I&amp;#8217;ll be happy. I really think some NoSQL databases should realize this and drop scalability as a prepackaged buzzword feature and focus on the real needs of the majority of their user base.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Relax, does that word ring a bell? It&amp;#8217;s the tag line of CouchDB. With its nice REST API and with replication as the only way to scale horizontally, I think CouchDB classifies as an EasyDB.&lt;/p&gt;

&lt;p&gt;However, CouchDB uses &lt;a href='http://en.wikipedia.org/wiki/Multiversion_concurrency_control'&gt;MVCC&lt;/a&gt;, this avoids locking and provides a form of consistency, but it does place the burden of handling update conflicts on the client. Or&amp;#8230; does it?&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/couch-concur.png' alt='CouchDB concurrency' /&gt;&lt;/p&gt;

&lt;p&gt;I would like to draw a parallel with how Clojure handles controlled shared mutable state. The simplest form present in Clojure is the &lt;a href='http://clojure.org/atoms'&gt;Atom&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;An atom is a MVCC construct that provides a low-level &lt;code&gt;compare-and-set!&lt;/code&gt; function that executes an atomic update if the expected old value matches the actual value. Much like CouchDB compares the &lt;code&gt;_rev&lt;/code&gt; of a document before updating.&lt;/p&gt;

&lt;p&gt;Interestingly, though, atoms also provide the very convenient &lt;code&gt;swap!&lt;/code&gt;, which takes a pure function that takes the old value and returns the new one. &lt;code&gt;swap!&lt;/code&gt; calls &lt;code&gt;compare-and-set!&lt;/code&gt; in a loop, recomputing the new value on every iteration until the update succeeds.&lt;/p&gt;

&lt;p&gt;So what about CouchDB? Can we have easy fire-and-forget updates there as well? Yes we can! I previously hacked together an &lt;a href='https://github.com/pepijndevos/couch-atom'&gt;atom implementation on top of CouchDB&lt;/a&gt;, but it turns out CouchDB already offers a little known feature called &lt;a href='http://wiki.apache.org/couchdb/Document_Update_Handlers'&gt;Document Update Handlers&lt;/a&gt;, which does exactly this.&lt;/p&gt;

&lt;p&gt;Sadly, the Clojure view server included with &lt;a href='https://github.com/ashafa/clutch'&gt;Clutch&lt;/a&gt; does not yet include support for document update handlers, but this can be easily remedied!&lt;/p&gt;</content>
		
		<category term="nosql" />
		
		<category term="clojure" />
		
		<category term="couchdb" />
		
	</entry>
	
	<entry>
		<title>Lion Hacks</title>
		<link href="http://pepijndevos.nl/2011/07/22/lion-hacks.html"/>
		<updated>2011-07-22T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/07/22/lion-hacks</id>
		<content type="html">&lt;p&gt;I installed Mac OS X 10.7 Lion on my Mac yestereday. It did not went very smooth. I&amp;#8217;m not going to do &lt;a href='http://arstechnica.com/apple/reviews/2011/07/mac-os-x-10-7.ars'&gt;a review&lt;/a&gt;, but I &lt;em&gt;am&lt;/em&gt; going to share my story and some tricks used along the way.&lt;/p&gt;

&lt;h3 id='backup'&gt;Backup&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Always backup&lt;/strong&gt;, always, and make sure it works.&lt;/p&gt;

&lt;p&gt;I run Time Machine backups on an external 500GB HDD, but TM has the nasty habbit to gobble up all available disk space. So when I wanted to make a disk image of my complete HD, I had to remove the TM backup.&lt;/p&gt;

&lt;p&gt;Then I did something stupid, and proceeded with the installation without checking the image worked.&lt;/p&gt;

&lt;h4 id='trick_remove_single_revision'&gt;Trick: Remove Single Revision&lt;/h4&gt;

&lt;p&gt;Go into Time Machine to the revision and folder you want to remove. Now right-click and select &amp;#8220;Delete Backup&amp;#8221;.&lt;/p&gt;

&lt;p&gt;Note that the UI is not suitable for removing all but a few revisions, which is why I opted to remove the whole thing.&lt;/p&gt;

&lt;h4 id='trick_limit_time_machine_space'&gt;Trick: Limit Time Machine space&lt;/h4&gt;

&lt;p&gt;Only after I was finally running Lion did I discovered a way to limit the disk space used by Time Machine.&lt;/p&gt;

&lt;p&gt;There are &lt;a href='http://hints.macworld.com/article.php?story=20080519051720677'&gt;a few&lt;/a&gt; &lt;a href='http://hints.macworld.com/article.php?story=20071108020121567'&gt;complicated hints&lt;/a&gt; to achieve this for remote volumes, but nothing for local ones.&lt;/p&gt;

&lt;p&gt;This trick involves another Mac, because Lion refuses to connect to a &amp;#8220;remote&amp;#8221; disk that is actually the local disk shared over AFP.&lt;/p&gt;

&lt;p&gt;First, we need to trick Time Machine into using a sparsebundle instead of plain files.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connect the disk to another Mac&lt;/li&gt;

&lt;li&gt;Share it in System Preferences&lt;/li&gt;

&lt;li&gt;Initiate a backup, so that a sparsebundle is created&lt;/li&gt;

&lt;li&gt;Cancel the backup and disconnect the drive&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now Time Machine will continue using the disk image when the drive is connected directly. The only thing that remains is to limit the bundle in size, using this command:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;hdiutil resize -size 150G -shrinkonly /path/to/image.sparsebundle&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Where &lt;code&gt;150G&lt;/code&gt; and &lt;code&gt;/path/to/image.sparsebundle&lt;/code&gt; need to be replaced with the desired size and the path to the bundle, residing on your backup drive.&lt;/p&gt;

&lt;h3 id='installation'&gt;Installation&lt;/h3&gt;

&lt;p&gt;You&amp;#8217;re normally supposed to install Lion straight from the App Store, but &lt;a href='http://www.eggfreckles.net/tech/installing-lion-clean/'&gt;some smart guy found out&lt;/a&gt; you can burn your own DVD or USB drive.&lt;/p&gt;

&lt;p&gt;I ended up going the DVD route, because my main drive appeared unbootable by the installer and my USB stick was a &lt;em&gt;few MB&lt;/em&gt; to small.&lt;/p&gt;

&lt;h4 id='possible_trick_clean_install_without_dvd'&gt;&lt;em&gt;Possible&lt;/em&gt; trick: Clean install without DVD&lt;/h4&gt;

&lt;p&gt;I could not try this because of my broken HD, please let me know if it works.&lt;/p&gt;

&lt;p&gt;Lion installs a recovery partition, which plays an important role in the installation. You can&amp;#8217;t simply replace a running system, you know.&lt;/p&gt;

&lt;p&gt;Run the installation straight from the App Store up to the point where you need to reboot. Now the trick is to hold &amp;#8984;R to boot into the recovery mode rather than into the installer.&lt;/p&gt;

&lt;p&gt;Now, use Disk Utility to wipe your disk, and run the full installation from the recovery partition.&lt;/p&gt;

&lt;h3 id='migrationrecovery'&gt;Migration/Recovery&lt;/h3&gt;

&lt;p&gt;As I said, I did a clean install, wiped my drive, but forgot to check the image works. &lt;em&gt;tension&amp;#8230;&lt;/em&gt; It did not work of course.&lt;/p&gt;

&lt;p&gt;The right way, of course is to always make sure your Time Machine backup or your disk image works, and to verify and repair your hard drive before you make an image or upgrade.&lt;/p&gt;

&lt;p&gt;If you do all of that, Mac has a neat Migration Assistent which can import your old data.&lt;/p&gt;

&lt;h4 id='trick_mount_correct_image_of_damanged_partition'&gt;Trick: Mount correct image of damanged partition&lt;/h4&gt;

&lt;p&gt;Disk Utility is able to perform first aid on damaged disk images, but apparently not mine. Another weird thing is that the checksum matched, but no mountable volumes where found.&lt;/p&gt;

&lt;p&gt;So what I have is a &lt;strong&gt;working&lt;/strong&gt; image of a &lt;strong&gt;broken&lt;/strong&gt; disk.&lt;/p&gt;

&lt;p&gt;Luckly HFS+ has a feature called journaling, to recover from a bad state, but Disk Utility told me that the journal could not be replayed because the media was read-only.&lt;/p&gt;

&lt;p&gt;After using Disk Utility to convert the disk image to read/write, it would mount, and let me extract my files, but upon applying first aid, matters got worse again, and Disk Utility told me to take my files and ruuuun!&lt;/p&gt;

&lt;h3 id='settling_in'&gt;Settling in&lt;/h3&gt;

&lt;p&gt;This part went pretty smooth. I&amp;#8217;m swapping some software, waiting for some Lion updates, and looking at all the things that go &lt;em&gt;swoosh&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Homebrew is in, Macports is out. Homebrew makes sysadmins cringe, because it&amp;#8217;s written by a &amp;#8220;Ruby hippie&amp;#8221; that has no sens for dependency management. It does not include its own copy of everything included in OS X, which saves a lot of time and space IMO.&lt;/p&gt;

&lt;p&gt;I read iChat is now extensible to support &amp;#8220;legacy&amp;#8221; protcols, like MSN. Because I&amp;#8217;m barely using MSN and becaus everyone is hiring Adium devs, I&amp;#8217;m using iChat now. I&amp;#8217;ll wait until someone staples libpurple to iChat.&lt;/p&gt;

&lt;p&gt;I also heard Growl 1.3 will be a sexy Lion app available in the App Store. Not sure if I&amp;#8217;ll wait or install 1.2 anyway.&lt;/p&gt;

&lt;p&gt;One thing that &lt;em&gt;has&lt;/em&gt; to be done in Lion is un-dumbing Finder.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Customize the toolbar to include that path widget&lt;/li&gt;

&lt;li&gt;&lt;a href='http://www.tuaw.com/2008/12/05/terminal-tips-enable-path-view-in-finder/'&gt;Show full paths&lt;/a&gt; &lt;code&gt;defaults write com.apple.finder _FXShowPosixPathInTitle -bool YES&lt;/code&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href='http://lifehacker.com/188892/show-hidden-files-in-finder'&gt;Show hidden files&lt;/a&gt; &lt;code&gt;defaults write com.apple.finder AppleShowAllFiles -bool YES&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then restart finder, &lt;code&gt; killall Finder&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;</content>
		
		<category term="mac" />
		
		<category term="lion" />
		
		<category term="time machine" />
		
	</entry>
	
	<entry>
		<title>My Bookshelf 4/5: Mining the Social Web</title>
		<link href="http://pepijndevos.nl/2011/07/16/my-bookshelf-45-mining-the-social-web.html"/>
		<updated>2011-07-16T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/07/16/my-bookshelf-45-mining-the-social-web</id>
		<content type="html">&lt;p&gt;This book seems almost written for me. It starts of with my favourite platform: Twitter. Next it covers micro formats, which I was just getting interested in. And finally, working with similarity and clustering released a slew of new ideas.&lt;/p&gt;

&lt;p&gt;&lt;img src='/images/mining-the-social-web.jpg' alt='Mining the Social Web cover' /&gt;&lt;/p&gt;

&lt;p&gt;Wht is interesting to note is that this book &lt;em&gt;references&lt;/em&gt; a lot of material. This means that it contains more good stuff than fits between the covers, but also that some of the stuff you want to know cannot be found between the covers.&lt;/p&gt;

&lt;p&gt;All code used in the book (and more) can be &lt;a href='https://github.com/ptwobrussell/Mining-the-Social-Web'&gt;found on github&lt;/a&gt;, which saves a lot of typing when you want to play around. The downside is that some longer examples and utilities are &lt;em&gt;only&lt;/em&gt; on github, which is sub-ideal when you are reading away from the internet or the computer.&lt;/p&gt;

&lt;p&gt;The code used in the book is written in Python, arguably because of its readable syntax and library support, especially the &lt;a href='http://www.nltk.org/'&gt;NLTK&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The book also uses Redis and CouchDB extensively, which is not so easily justified at this small scale in my opinion. Later in the book, Pickle is used most of the time.&lt;/p&gt;

&lt;p&gt;This book covers a lot of ground in this broad subject, and gives you the tools to explore subjects in-depth yourself. Definitely recommended reading.&lt;/p&gt;</content>
		
		<category term="bookshelf" />
		
		<category term="review" />
		
		<category term="data mining" />
		
		<category term="python" />
		
	</entry>
	
	<entry>
		<title>Can't take value of a macro</title>
		<link href="http://pepijndevos.nl/2011/07/07/cant-take-value-of-a-macro.html"/>
		<updated>2011-07-07T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/07/07/cant-take-value-of-a-macro</id>
		<content type="html">&lt;p&gt;Do. not. ever. make me see that exception. Because in my opinion that means you failed at designing your shiny DSL.&lt;/p&gt;

&lt;p&gt;A macro is not a thing, but a transform from one thing to another. If your DSL does not have things &amp;#8211; domain specific values, as &lt;a href='http://blip.tv/clojure/christophe-grand-not-dsl-macros-4540700'&gt;Christophe Grand calls them&lt;/a&gt; &amp;#8211; at its core, you&amp;#8217;re doing it wrong.&lt;/p&gt;

&lt;p&gt;First and foremost, a macro should be simple, where simple means &amp;#8216;not compound&amp;#8217;, as &lt;a href='http://blip.tv/clojure/stuart-halloway-simplicity-ain-t-easy-4842694'&gt;explained by Stuart Halloway&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I would like to define a simple macro as one that is written as a compound of simple functions returning code that evaluates to a simple or composite value.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;(+ 1 1)&lt;/code&gt; returns a simple value&lt;/li&gt;

&lt;li&gt;&lt;code&gt;(a-record. 1 2 3)&lt;/code&gt; evaluates to a composite of simple things&lt;/li&gt;

&lt;li&gt;&lt;code&gt;(do (def foo 2) (def bar 4) (do-thing-to foo))&lt;/code&gt; is not simple&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another good non-reason to use macros is to defer execution.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='clojure'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defmacro &lt;/span&gt;&lt;span class='nv'&gt;assoc-once&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;m&lt;/span&gt; &lt;span class='nv'&gt;k&lt;/span&gt; &lt;span class='nv'&gt;v&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='o'&gt;`&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;if-not&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;get &lt;/span&gt;&lt;span class='nv'&gt;~m&lt;/span&gt; &lt;span class='nv'&gt;~k&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
     &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;assoc &lt;/span&gt;&lt;span class='nv'&gt;~m&lt;/span&gt; &lt;span class='nv'&gt;~k&lt;/span&gt; &lt;span class='nv'&gt;~v&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
     &lt;span class='nv'&gt;~m&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;assoc-once&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='nv'&gt;:a&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='nv'&gt;:a&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;println &lt;/span&gt;&lt;span class='s'&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;; {:a 1}&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;assoc-once&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='nv'&gt;:a&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='nv'&gt;:b&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;println &lt;/span&gt;&lt;span class='s'&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;; foo&lt;/span&gt;
&lt;span class='c1'&gt;; {:b nil, :a 1}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Works nicely, uh? Now assume we have an atom, try &lt;code&gt;(swap! a assoc-once ...)&lt;/code&gt; It&amp;#8217;ll honor our post title: Can&amp;#8217;t take value of a macro&lt;/p&gt;

&lt;p&gt;You know what else defers execution? A function.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='clojure'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;assoc-once&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;m&lt;/span&gt; &lt;span class='nv'&gt;k&lt;/span&gt; &lt;span class='nv'&gt;v&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;if-not&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;get &lt;/span&gt;&lt;span class='nv'&gt;m&lt;/span&gt; &lt;span class='nv'&gt;k&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;assoc &lt;/span&gt;&lt;span class='nv'&gt;m&lt;/span&gt; &lt;span class='nv'&gt;k&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;v&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='c1'&gt;; note parens&lt;/span&gt;
    &lt;span class='nv'&gt;m&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;assoc-once&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='nv'&gt;:a&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='nv'&gt;:a&lt;/span&gt; &lt;span class='o'&gt;#&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;println&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;; {:a 1}&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;assoc-once&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;&lt;span class='nv'&gt;:a&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='nv'&gt;:b&lt;/span&gt; &lt;span class='o'&gt;#&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;println&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;; foo&lt;/span&gt;
&lt;span class='c1'&gt;; {:b nil, :a 1}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This is of course not as good-looking as the macro, but the &lt;code&gt;swap!&lt;/code&gt; case works fine here. If you care enough, you could define a macro on top of the function, giving you a simple macro.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='clojure'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defmacro &lt;/span&gt;&lt;span class='nv'&gt;assoc-once&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;m&lt;/span&gt; &lt;span class='nv'&gt;k&lt;/span&gt; &lt;span class='nv'&gt;v&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='o'&gt;`&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;assoc-once*&lt;/span&gt; &lt;span class='nv'&gt;~m&lt;/span&gt; &lt;span class='nv'&gt;~k&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;fn &lt;/span&gt;&lt;span class='p'&gt;[]&lt;/span&gt; &lt;span class='nv'&gt;~v&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now, this is a very long and opinionated post for me already, so I&amp;#8217;m going to stop here. I highly recommend that you watch the 2 video&amp;#8217;s I linked to.&lt;/p&gt;

&lt;p&gt;I had in mind to take you through another example of using protocols and function composition to simplify and avoid macros, but I&amp;#8217;ll just give you &lt;a href='http://dev.clojure.org/jira/secure/attachment/10246/0001-rel-defrel-extend-rel.patch'&gt;this&lt;/a&gt;, &lt;a href='http://pragprog.com/magazines/2011-07/growing-a-dsl-with-clojure'&gt;this&lt;/a&gt; and &lt;a href='/clojure-micro-pattern-matcher/index.html'&gt;that&lt;/a&gt; as a homework assignment.&lt;/p&gt;</content>
		
		<category term="clojure" />
		
		<category term="dsl" />
		
		<category term="macro" />
		
	</entry>
	
	<entry>
		<title>Generative Music</title>
		<link href="http://pepijndevos.nl/2011/07/01/generative-music.html"/>
		<updated>2011-07-01T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/07/01/generative-music</id>
		<content type="html">&lt;p&gt;It&amp;#8217;s been a long time since I played with &lt;a href='https://github.com/rosejn/overtone'&gt;Overtone&lt;/a&gt;. What I&amp;#8217;ve always wanted to do is generate music automatically. Today I ran into &lt;a href='http://www.jfugue.org/'&gt;jFugue&lt;/a&gt;, which makes this really easy, listen to this:&lt;/p&gt;
&lt;object height='81' width='100%'&gt; &lt;param name='movie' value='http://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F18222911' /&gt; &lt;param name='allowscriptaccess' value='always' /&gt; &lt;embed src='http://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F18222911' allowscriptaccess='always' type='application/x-shockwave-flash' height='81' width='100%' /&gt; &lt;/object&gt;&lt;span&gt;&lt;a href='http://soundcloud.com/pepijndevossc/markov-generated-music'&gt;Markov generated music&lt;/a&gt; by &lt;a href='http://soundcloud.com/pepijndevossc'&gt;pepijndevos&lt;/a&gt;&lt;/span&gt;
&lt;p&gt;I just took some music from &lt;a href='http://www.wikifonia.org/'&gt;wikifonia&lt;/a&gt;, constructed a Markov-chain and did a random note-walk.&lt;/p&gt;

&lt;p&gt;This could work just as well with Overtone, but I used jFugue because it comes with a parser for &lt;a href='http://www.recordare.com/musicxml'&gt;MusicXML&lt;/a&gt; files.&lt;/p&gt;

&lt;p&gt;To run the code below, you need to have jFugue on the classpath. Then just pipe a couple of notes from generate into play.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='clojure'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;ns&lt;/span&gt; &lt;span class='nv'&gt;ponger&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;core&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;:require&lt;/span&gt; &lt;span class='nv'&gt;clojure&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;string&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;inflate-mxl&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;file&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;z&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;java&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;util&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;zip&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;ZipFile&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='nv'&gt;file&lt;/span&gt;&lt;span class='p'&gt;)]&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;slurp&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;getInputStream&lt;/span&gt; &lt;span class='nv'&gt;z&lt;/span&gt;
        &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;nextElement&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;entries&lt;/span&gt; &lt;span class='nv'&gt;z&lt;/span&gt;&lt;span class='p'&gt;))))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;parse-musicxml&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;file&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;parser&lt;/span&gt;   &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;org&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;jfugue&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;parsers&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;MusicXmlParser&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='nv'&gt;renderer&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;org&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;jfugue&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;MusicStringRenderer&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='p'&gt;)]&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;addParserListener&lt;/span&gt; &lt;span class='nv'&gt;parser&lt;/span&gt; &lt;span class='nv'&gt;renderer&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;parse&lt;/span&gt; &lt;span class='nv'&gt;parser&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;inflate-mxl&lt;/span&gt; &lt;span class='nv'&gt;file&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;getPattern&lt;/span&gt; &lt;span class='nv'&gt;renderer&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;notes&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;tokens&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;filter &lt;/span&gt;&lt;span class='o'&gt;#&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;re-matches&lt;/span&gt; &lt;span class='o'&gt;#&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;[A-GR].*&amp;quot;&lt;/span&gt; &lt;span class='nv'&gt;%&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nv'&gt;tokens&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;voices&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;tokens&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let &lt;/span&gt;&lt;span class='p'&gt;[[&lt;/span&gt;&lt;span class='nv'&gt;f&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;_&lt;/span&gt; &lt;span class='nv'&gt;&amp;amp;&lt;/span&gt; &lt;span class='nv'&gt;r&lt;/span&gt;&lt;span class='p'&gt;]]&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;split-with &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;complement &lt;/span&gt;&lt;span class='o'&gt;#&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;startsWith&lt;/span&gt; &lt;span class='nv'&gt;%&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;V&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='nv'&gt;tokens&lt;/span&gt;&lt;span class='p'&gt;)]&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;when &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;seq &lt;/span&gt;&lt;span class='nv'&gt;f&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cons &lt;/span&gt;&lt;span class='nv'&gt;f&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;voices&lt;/span&gt; &lt;span class='nv'&gt;r&lt;/span&gt;&lt;span class='p'&gt;)))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;make-chain&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;tokens&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;into &lt;/span&gt;&lt;span class='p'&gt;{}&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;for &lt;/span&gt;&lt;span class='p'&gt;[[&lt;/span&gt;&lt;span class='nv'&gt;k&lt;/span&gt; &lt;span class='nv'&gt;slice&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;group-by&lt;/span&gt; &lt;span class='nv'&gt;first&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;partition&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='nv'&gt;tokens&lt;/span&gt;&lt;span class='p'&gt;))]&lt;/span&gt;
      &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;k&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;map &lt;/span&gt;&lt;span class='nv'&gt;last&lt;/span&gt; &lt;span class='nv'&gt;slice&lt;/span&gt;&lt;span class='p'&gt;)])))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;walk-chain&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;chain&lt;/span&gt; &lt;span class='nv'&gt;start&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;nxt&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;rand-nth&lt;/span&gt;
              &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;get &lt;/span&gt;&lt;span class='nv'&gt;chain&lt;/span&gt; &lt;span class='nv'&gt;start&lt;/span&gt;
                   &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;apply &lt;/span&gt;&lt;span class='nv'&gt;concat&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;vals &lt;/span&gt;&lt;span class='nv'&gt;chain&lt;/span&gt;&lt;span class='p'&gt;))))]&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;cons&lt;/span&gt;
      &lt;span class='nv'&gt;nxt&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;lazy-seq&lt;/span&gt;
        &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;walk-chain&lt;/span&gt; &lt;span class='nv'&gt;chain&lt;/span&gt; &lt;span class='nv'&gt;nxt&lt;/span&gt;&lt;span class='p'&gt;)))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;generate&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;path&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;-&amp;gt; &lt;/span&gt;&lt;span class='nv'&gt;path&lt;/span&gt;
    &lt;span class='nv'&gt;parse-musicxml&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;getTokens&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='nv'&gt;notes&lt;/span&gt;
    &lt;span class='nv'&gt;make-chain&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;walk-chain&lt;/span&gt; &lt;span class='nv'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;play&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;token-seq&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;player&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;org&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;jfugue&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;StreamingPlayer&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='p'&gt;)]&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;doseq &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;token&lt;/span&gt; &lt;span class='nv'&gt;token-seq&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;stream&lt;/span&gt; &lt;span class='nv'&gt;player&lt;/span&gt; &lt;span class='nv'&gt;token&lt;/span&gt;&lt;span class='p'&gt;))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;save&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;token-seq&lt;/span&gt; &lt;span class='nv'&gt;path&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;saveMidi&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;org&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;jfugue&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;Player&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
         &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;clojure&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;string/join&lt;/span&gt; &lt;span class='s'&gt;&amp;quot; &amp;quot;&lt;/span&gt; &lt;span class='nv'&gt;token-seq&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
         &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;java&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;io&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='nv'&gt;path&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</content>
		
		<category term="clojure" />
		
		<category term="markov" />
		
		<category term="music" />
		
	</entry>
	
	<entry>
		<title>NIO in Clojure</title>
		<link href="http://pepijndevos.nl/2011/06/18/nio-in-clojure.html"/>
		<updated>2011-06-18T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/06/18/nio-in-clojure</id>
		<content type="html">&lt;p&gt;So, I&amp;#8217;m playing with the idea of writing a little webserver in Clojure, much like those asynchronous Python ones like Twisted and Tornado, but actually I&amp;#8217;m just writing this to play with my new blog.&lt;/p&gt;

&lt;p&gt;There you have the code, not as a gist this time. The code actually &lt;a href='https://github.com/pepijndevos/pepijndevos.github.com/blob/master/_includes/code/nio.clj'&gt;lives in a separate file on Github&lt;/a&gt;, and is included here by a few lines of Liquid markup.&lt;/p&gt;

&lt;p&gt;This code was modeled after &lt;a href='http://www.javaworld.com/javaworld/jw-04-2003/jw-0411-select.html'&gt;this Java code&lt;/a&gt;. If you have anything interesting to say about this code, NIO, webservers or Clojure, I&amp;#8217;d love to hear from you.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='clojure'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;ns&lt;/span&gt; &lt;span class='nv'&gt;nio&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;:import&lt;/span&gt;
     &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;java&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;net&lt;/span&gt;
      &lt;span class='nv'&gt;InetSocketAddress&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
     &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;java&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;nio&lt;/span&gt;
      &lt;span class='nv'&gt;ByteBuffer&lt;/span&gt;
      &lt;span class='nv'&gt;CharBuffer&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
     &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;java&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;nio&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;channels&lt;/span&gt;
      &lt;span class='nv'&gt;ServerSocketChannel&lt;/span&gt;
      &lt;span class='nv'&gt;Selector&lt;/span&gt;
      &lt;span class='nv'&gt;SelectionKey&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
     &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;java&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;nio&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;charset&lt;/span&gt;
      &lt;span class='nv'&gt;Charset&lt;/span&gt;&lt;span class='p'&gt;]))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;def &lt;/span&gt;&lt;span class='nv'&gt;*buffer*&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;ByteBuffer/allocate&lt;/span&gt; &lt;span class='mi'&gt;16384&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;selector&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;server-socket-channel&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;selector&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;Selector/open&lt;/span&gt;&lt;span class='p'&gt;)]&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;register&lt;/span&gt; &lt;span class='nv'&gt;server-socket-channel&lt;/span&gt; &lt;span class='nv'&gt;selector&lt;/span&gt; &lt;span class='nv'&gt;SelectionKey/OP_ACCEPT&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='nv'&gt;selector&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;setup&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;port&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;server-socket-channel&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;ServerSocketChannel/open&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='nv'&gt;_&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;configureBlocking&lt;/span&gt; &lt;span class='nv'&gt;server-socket-channel&lt;/span&gt; &lt;span class='nv'&gt;false&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='nv'&gt;server-socket&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;socket&lt;/span&gt; &lt;span class='nv'&gt;server-socket-channel&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='nv'&gt;inet-socket-address&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;InetSocketAddress&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='nv'&gt;port&lt;/span&gt;&lt;span class='p'&gt;)]&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;bind&lt;/span&gt; &lt;span class='nv'&gt;server-socket&lt;/span&gt; &lt;span class='nv'&gt;inet-socket-address&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;[(&lt;/span&gt;&lt;span class='nf'&gt;selector&lt;/span&gt; &lt;span class='nv'&gt;server-socket-channel&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
     &lt;span class='nv'&gt;server-socket&lt;/span&gt;&lt;span class='p'&gt;]))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;state=&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;state&lt;/span&gt; &lt;span class='nv'&gt;channel&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;= &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;bit-and &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;readyOps&lt;/span&gt; &lt;span class='nv'&gt;channel&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nv'&gt;state&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nv'&gt;state&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;buffer-&amp;gt;string&lt;/span&gt;
  &lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='nv'&gt;byte-buffer&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
   &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;buffer-&amp;gt;string&lt;/span&gt; &lt;span class='nv'&gt;byte-buffer&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;Charset/defaultCharset&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
  &lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='nv'&gt;byte-buffer&lt;/span&gt; &lt;span class='nv'&gt;charset&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
   &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;toString&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;decode&lt;/span&gt; &lt;span class='nv'&gt;charset&lt;/span&gt; &lt;span class='nv'&gt;byte-buffer&lt;/span&gt;&lt;span class='p'&gt;))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;string-&amp;gt;buffer&lt;/span&gt;
  &lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='nv'&gt;string&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
   &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;string-&amp;gt;buffer&lt;/span&gt; &lt;span class='nv'&gt;string&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;Charset/defaultCharset&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
  &lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='nv'&gt;string&lt;/span&gt; &lt;span class='nv'&gt;charset&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
   &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;encode&lt;/span&gt; &lt;span class='nv'&gt;charset&lt;/span&gt; &lt;span class='nv'&gt;string&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;accept-connection&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;server-socket&lt;/span&gt; &lt;span class='nv'&gt;selector&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;channel&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;-&amp;gt; &lt;/span&gt;&lt;span class='nv'&gt;server-socket&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;accept&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;getChannel&lt;/span&gt;&lt;span class='p'&gt;))]&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;println &lt;/span&gt;&lt;span class='s'&gt;&amp;quot;Connection from&amp;quot;&lt;/span&gt; &lt;span class='nv'&gt;channel&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;doto &lt;/span&gt;&lt;span class='nv'&gt;channel&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;configureBlocking&lt;/span&gt; &lt;span class='nv'&gt;false&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;register&lt;/span&gt; &lt;span class='nv'&gt;selector&lt;/span&gt; &lt;span class='nv'&gt;SelectionKey/OP_READ&lt;/span&gt;&lt;span class='p'&gt;))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;read-socket&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;selected-key&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;socket-channel&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;channel&lt;/span&gt; &lt;span class='nv'&gt;selected-key&lt;/span&gt;&lt;span class='p'&gt;)]&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;clear&lt;/span&gt; &lt;span class='nv'&gt;*buffer*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;read&lt;/span&gt; &lt;span class='nv'&gt;socket-channel&lt;/span&gt; &lt;span class='nv'&gt;*buffer*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;flip&lt;/span&gt; &lt;span class='nv'&gt;*buffer*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;if &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;= &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;limit&lt;/span&gt; &lt;span class='nv'&gt;*buffer*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;do&lt;/span&gt;
        &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;println &lt;/span&gt;&lt;span class='s'&gt;&amp;quot;Lost connection from&amp;quot;&lt;/span&gt; &lt;span class='nv'&gt;socket-channel&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;cancel&lt;/span&gt; &lt;span class='nv'&gt;selected-key&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;close&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;socket&lt;/span&gt; &lt;span class='nv'&gt;socket-channel&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;write&lt;/span&gt; &lt;span class='nv'&gt;socket-channel&lt;/span&gt; &lt;span class='nv'&gt;*buffer*&lt;/span&gt;&lt;span class='p'&gt;))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;react&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;selector&lt;/span&gt; &lt;span class='nv'&gt;server-socket&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;while&lt;/span&gt; &lt;span class='nv'&gt;true&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;when &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;&amp;gt; &lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;select&lt;/span&gt; &lt;span class='nv'&gt;selector&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;selected-keys&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;selectedKeys&lt;/span&gt; &lt;span class='nv'&gt;selector&lt;/span&gt;&lt;span class='p'&gt;)]&lt;/span&gt;
        &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;doseq &lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;k&lt;/span&gt; &lt;span class='nv'&gt;selected-keys&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
          &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;condp&lt;/span&gt; &lt;span class='nv'&gt;state=&lt;/span&gt; &lt;span class='nv'&gt;k&lt;/span&gt;
            &lt;span class='nv'&gt;SelectionKey/OP_ACCEPT&lt;/span&gt;
            &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;accept-connection&lt;/span&gt; &lt;span class='nv'&gt;server-socket&lt;/span&gt; &lt;span class='nv'&gt;selector&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
            &lt;span class='nv'&gt;SelectionKey/OP_READ&lt;/span&gt;
            &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;read-socket&lt;/span&gt; &lt;span class='nv'&gt;k&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
        &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nv'&gt;clear&lt;/span&gt; &lt;span class='nv'&gt;selected-keys&lt;/span&gt;&lt;span class='p'&gt;)))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;defn &lt;/span&gt;&lt;span class='nv'&gt;run&lt;/span&gt; &lt;span class='p'&gt;[]&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;apply &lt;/span&gt;&lt;span class='nv'&gt;react&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;setup&lt;/span&gt; &lt;span class='mi'&gt;2323&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</content>
		
		<category term="clojure" />
		
		<category term="nio" />
		
	</entry>
	
	<entry>
		<title>Blogging like a Ruby Hacker</title>
		<link href="http://pepijndevos.nl/2011/06/16/blogging-like-a-ruby-hacker.html"/>
		<updated>2011-06-16T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2011/06/16/blogging-like-a-ruby-hacker</id>
		<content type="html">&lt;p&gt;Kind of a weird thing to say for someone who does not program Ruby, don&amp;#8217;t you think?&lt;/p&gt;

&lt;p&gt;I have been wanting to move away from Posterous for quite a while now. I&amp;#8217;ve searched for solutions in languages I know and even &lt;a href='https://github.com/pepijndevos/utterson'&gt;spent some time writing something in Clojure&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All in all, I wasn&amp;#8217;t getting anywhere, so I just said to myself that I wanted to have my blog in a static site generator &lt;em&gt;today&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I chose &lt;a href='http://jekyllrb.com/'&gt;Jekyll&lt;/a&gt; because it&amp;#8217;s the first and most popular one I knew. It&amp;#8217;s also &lt;a href='http://pages.github.com/'&gt;used by Github&lt;/a&gt; and is named after &lt;a href='http://en.wikipedia.org/wiki/Strange_Case_of_Dr_Jekyll_and_Mr_Hyde'&gt;&amp;#8220;The Strange Case of Dr Jekyll and Mr Hyde&amp;#8221;&lt;/a&gt;. Only, it&amp;#8217;s in Ruby.&lt;/p&gt;

&lt;p&gt;It turns out Ruby syntax is quite easy to guess right for a Python dev. Before I could get started, I had to hack a &lt;a href='https://github.com/pepijndevos/jekyll/blob/patch-1/lib/jekyll/migrators/posterous.rb'&gt;Posterous migrator&lt;/a&gt; to support my old links, tags and images.&lt;/p&gt;

&lt;p&gt;So, I hope you like my new old theme and that you don&amp;#8217;t find to much broken stuff.&lt;/p&gt;

&lt;p&gt;I don&amp;#8217;t have comments for the moment, so you&amp;#8217;ll have to email me when you have problems. I do plan to add search from &lt;a href='http://tapirgo.com/'&gt;Tapir&lt;/a&gt; soon.&lt;/p&gt;</content>
		
		<category term="ruby" />
		
		<category term="blogging" />
		
		<category term="jekyll" />
		
	</entry>
	
	<entry>
		<title>My Bookshelf 3/5: Seven Languages in Seven Weeks</title>
		<link href="http://pepijndevos.nl/my-bookshelf-35-seven-languages-in-seven-week/index.html"/>
		<updated>2011-05-22T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/my-bookshelf-35-seven-languages-in-seven-week/my-bookshelf-35-seven-languages-in-seven-week</id>
		<content type="html">Phew, that took a while. I actually did some languages in under a day, but overall, 7 weeks is about what it took me.&lt;p /&gt;&lt;div&gt;&lt;div style=&quot;&quot;&gt;&lt;img src=&quot;/images/btlang.jpeg&quot; alt=&quot;My Bookshelf 3/5: Seven Languages in Seven Weeks&quot; /&gt;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;You can argue endlessly about which languages to include in the book, but I think he made a balanced choice that leads to a progressive increase in new concepts.&lt;/div&gt;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;The book starts easy with Ruby, a mainstream OO language that is the native&amp;nbsp;tongue of the author. Then, we move to prototype inheritance(Io), Logic programming(Prolog), and take the plunge into functional programing with Scala, followed by Erlang, Clojure, and finally the most functional of them all; Haskell.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;If you want to learn on specific language well, this book is not for you. But if you are the kind of person who wants to taste every cake in existence, it's great!&lt;/div&gt;&lt;p /&gt;&lt;div&gt;&lt;img src=&quot;/images/Screen_shot_2011-05-22_at_3.01.png&quot; alt=&quot;My Bookshelf 3/5: Seven Languages in Seven Weeks&quot; /&gt;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;The author recommends you to do all the exercises &quot;otherwise it'll just be some syntax&quot;. I disagree here. For languages where I did not do the exercises, I remember &lt;i&gt;only&lt;/i&gt; concepts, not any syntax at all. This is why I'm reading it, because of concepts, not to actually work with Io(though it's a gem).&lt;/div&gt;&lt;p /&gt;&lt;div&gt;So, it's a nice book, but if you want to learn some really wicked stuff, I suggest you also check out&amp;nbsp;&lt;a href=&quot;http://stackoverflow.com/questions/3958630/what-are-important-languages-to-learn-to-understand-different-approaches-and-conc#answer-3958962http://stackoverflow.com/questions/3958630/what-are-important-languages-to-learn-to-understand-different-approaches-and-conc#answer-3958962&quot;&gt;these languages suggested by Michael Fogus&lt;/a&gt;. (who is also the co-author of the next book on my shelf, Joy of Clojure)&lt;/div&gt;
</content>
		
		<category term="bookshelf" />
		
	</entry>
	
	<entry>
		<title>Lazy sorting</title>
		<link href="http://pepijndevos.nl/lazy-sorting/index.html"/>
		<updated>2011-05-02T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/lazy-sorting/lazy-sorting</id>
		<content type="html">&lt;p&gt;I was inspired by&amp;nbsp;&lt;a href=&quot;http://boss-level.com/?p=92&quot;&gt;Edmund's post&lt;/a&gt;&amp;nbsp;to try some other lazy sorts. These are far from competitive to Java's&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/Timsort&quot;&gt;timsort&lt;/a&gt;, but they are an interesting concept.&lt;/p&gt;
&lt;p&gt;It is not possible to make timsort lazy because it uses insertion sort which does not work that way.&lt;/p&gt;
&lt;blockquote class=&quot;posterous_medium_quote&quot;&gt;Insertion sort is very similar to&amp;nbsp;selection sort. As in selection sort, after&amp;nbsp;k&amp;nbsp;passes through the array, the first&amp;nbsp;k&amp;nbsp;elements are in sorted order. For selection sort these are the&amp;nbsp;k&amp;nbsp;smallest elements, while in insertion sort they are whatever the first&amp;nbsp;k&amp;nbsp;elements&amp;nbsp;were in the unsorted array.&lt;/blockquote&gt;
&lt;p&gt;A chunked lazy timsort might be attempted though.&amp;nbsp;Another option might be to use selection sort instead, or use another compounded sort like&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/Intro_sort&quot;&gt;introsort&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update: I added an insertion sort and a chunked lazy timsort, without all the frills that make it actually run fast.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;nv&quot;&gt;all&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;core/sort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 67.987 msecs&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;sorted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;core/sort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 22.214 msecs&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;core/sort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 56.249 msecs&amp;quot;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;all&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;test/qsort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 717.93 msecs&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;sorted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;test/qsort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 12388.316 msecs&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;test/qsort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 30.976 msecs&amp;quot;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;all&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;test/msort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 1317.334 msecs&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;sorted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;test/msort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 945.077 msecs&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;test/msort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 708.803 msecs&amp;quot;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;all&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;test/hsort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 83.909 msecs&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;sorted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;test/hsort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 75.235 msecs&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;test/hsort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 28.91 msecs&amp;quot;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;all&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;test/isort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 140.147 msecs&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;sorted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;test/isort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 23.097 msecs&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;test/isort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 110.453 msecs&amp;quot;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;all&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;test/tsort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 310.026 msecs&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;sorted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;test/tsort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 187.124 msecs&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;test/tsort&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 72.164 msecs&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ns&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;lazy-sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;qsort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;lazy-cat &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;qsort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;filter &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;qsort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;remove &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;merge*&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;r1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;l1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f2&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;r2&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;l2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cond&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nil? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;l2&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nil? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;l1&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;lt;= &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lazy-seq&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cons &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge*&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;r1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;l2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lazy-seq&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cons &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge*&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;l1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;r2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;msort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;split-at &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;/ &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;count &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;merge*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;msort&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;msort&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hsort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;concurrent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PriorityBlockingQueue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;count &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;take&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;^java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LinkedList&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;listIterator&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;and &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hasPrevious&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;previous&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;isort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; not lazy&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;reduce &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LinkedList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;treeduce&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;loop &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partition-all&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;lt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;count &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recur&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partition-all&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tsort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; naive&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;treeduce&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;merge*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;isort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partition-all&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;speed&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;doseq &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;sort&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;qsort&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;msort&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;hsort&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;isort&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;&amp;#39;tsort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
          &lt;span class=&quot;nv&quot;&gt;:let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;var-get &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;all   &amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;time &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dotimes &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dorun &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sort &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;shuffle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;sorted&amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;time &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dotimes &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dorun &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sort &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;first &amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;time &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dotimes &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sort &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;shuffle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/p&gt;
</content>
		
	</entry>
	
	<entry>
		<title>Leiningen project-in-a-gist</title>
		<link href="http://pepijndevos.nl/leiningen-project-in-a-gist/index.html"/>
		<updated>2011-04-30T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/leiningen-project-in-a-gist/leiningen-project-in-a-gist</id>
		<content type="html">&lt;p&gt;Since I wrote a&amp;nbsp;&lt;a href=&quot;http://pepijndevos.nl/clojure-micro-pattern-matcher&quot;&gt;pattern matcher&lt;/a&gt;&amp;nbsp;in under 50 lines of code, I do not feel like setting up an entire project for it, but I do want to use it in other projects and share it with you.&lt;/p&gt;
&lt;p&gt;Those great folks at Github added git access to Gists a while back, and it turns out you can make Leiningen run in a flat structure with a few extra lines of project.clj.&lt;/p&gt;
&lt;p&gt;This allows you to make cute mini projects with git access that can be installed and published and are embeddable and sharable.&lt;/p&gt;
&lt;p&gt;Here is the project.clj from my pattern matcher, I also&amp;nbsp;&lt;a href=&quot;http://clojars.org/seqex&quot;&gt;pushed the jar to clojars&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;defproject&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;seqex&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;1.0.0-SNAPSHOT&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;:description&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;a tiny pattern matcher&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;:dependencies&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;clojure/clojure&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;1.2.1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;:source-path&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;:aot&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;seqex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;:omit-source&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;First we tell Leiningen that our :source-path is the root dir. The other 2 lines are a bit of a hack to make sure only seqex.clj gets into the jar, Otherwise you'll get conflicts and broken jars.&lt;/p&gt;
</content>
		
		<category term="clojure" />
		
		<category term="github" />
		
		<category term="leiningen" />
		
	</entry>
	
	<entry>
		<title>Clojure micro pattern matcher</title>
		<link href="http://pepijndevos.nl/clojure-micro-pattern-matcher/index.html"/>
		<updated>2011-04-28T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/clojure-micro-pattern-matcher/clojure-micro-pattern-matcher</id>
		<content type="html">&lt;p&gt;Today I had some ideas for my game related to cellular automata that involved pattern matching. I googled, and found&amp;nbsp;&lt;a href=&quot;https://github.com/dcolthorp/matchure&quot;&gt;Matchure&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It might be a great pattern matcher, but the syntax and the amount of macro trickery makes me feel uncomfortable.&lt;/p&gt;
&lt;p&gt;In an attempt to write one that relies only on functions, I made this.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update: This is now a cute project-in-a-gist that can be used as a checkout dependency in Leiningen and Cake.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ns&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;seqex&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;:import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lang&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;Fn&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;IPersistentVector&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;IPersistentMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cps&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;funct&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when-let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;funct&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when-let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cont&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cons &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;    (and (funct f) (cont r))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;constantly &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defmulti &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;matcher&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pattern&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;reduce &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cps&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;matcher&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rseq &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
     &lt;span class=&quot;nv&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defmethod &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;matcher&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:default&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;partial &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defmethod &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;matcher&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Fn&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defmethod &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;matcher&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;IPersistentVector&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;partial &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defmethod &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;matcher&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;IPersistentMap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;every? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;identity&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when-let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;mv&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;matcher&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;mv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defmethod &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;matcher&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;regex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Pattern&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;partial &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;re-find&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; returns match&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;store&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;matcher&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defmacro &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cond-let&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;clauses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;clauses&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;if-let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;clauses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;clauses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;second &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;clauses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;IllegalArgumentException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
                         &lt;span class=&quot;s&quot;&gt;&amp;quot;cond-let requires an even number of forms&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cons &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cond-let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;clauses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;match&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:a&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;even?,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;count &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))}&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:a&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:d&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}])&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; [] (is truthy)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; []&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;match&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;\w.+?\w&amp;quot;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;store&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;foo bar&amp;quot;&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;        &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dotimes &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; foo&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; foo&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; foo&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; foo&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;defproject&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;seqex&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;1.0.0-SNAPSHOT&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;:description&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;a tiny pattern matcher&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;:dependencies&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;clojure/clojure&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;1.2.1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;:source-path&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;:aot&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;seqex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;:omit-source&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/p&gt;
</content>
		
		<category term="clojure" />
		
		<category term="patternmatching" />
		
	</entry>
	
	<entry>
		<title>A new seque</title>
		<link href="http://pepijndevos.nl/a-new-seque/index.html"/>
		<updated>2011-04-21T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/a-new-seque/a-new-seque</id>
		<content type="html">&lt;p&gt;I have used&amp;nbsp;&lt;a href=&quot;http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/seque&quot;&gt;clojure.core/seque&lt;/a&gt;&amp;nbsp;quite a bit lately, and I love it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;Creates a queued seq on another (presumably lazy) seq s. The queued&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;seq will produce a concrete seq in the background, and can get up to&lt;/div&gt;
&lt;div&gt;n items ahead of the consumer. n-or-q can be an integer n buffer&lt;/div&gt;
&lt;div&gt;size, or an instance of java.util.concurrent BlockingQueue. Note&lt;/div&gt;
&lt;div&gt;that reading from a seque can block if the reader gets ahead of the&lt;/div&gt;
&lt;div&gt;producer.&lt;/div&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div&gt;
&lt;div&gt;First I used it in&amp;nbsp;&lt;a href=&quot;https://github.com/pepijndevos/Begame&quot;&gt;Begame&lt;/a&gt;&amp;nbsp;for decoupling the frame computation from the rendering. But for most games, this needs to work without the frames getting ahead of rendering.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;This morning I wanted to make a lazy&amp;nbsp;&lt;a href=&quot;http://sortvis.org/algorithms/heapsort.html&quot;&gt;heapsort&lt;/a&gt;&amp;nbsp;in one line, rather than with&amp;nbsp;&lt;a href=&quot;http://pepijndevos.nl/sorting-obsession&quot;&gt;my own heap implementation&lt;/a&gt;.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;That is when problems started to occur. While seque optionally takes a&amp;nbsp;&lt;a href=&quot;http://download.oracle.com/javase/6/docs/api/java/util/concurrent/BlockingQueue.html&quot;&gt;BlockingQueue&lt;/a&gt;&amp;nbsp;as argument, it is not made to support exotic queues like&amp;nbsp;&lt;a href=&quot;http://download.oracle.com/javase/6/docs/api/java/util/concurrent/SynchronousQueue.html&quot;&gt;SynchronousQueue&lt;/a&gt;(for Begame) and&amp;nbsp;&lt;a href=&quot;http://download.oracle.com/javase/6/docs/api/java/util/concurrent/PriorityBlockingQueue.html&quot;&gt;PriorityBlockingQueue&lt;/a&gt;(for heapsort), which do a bit more than just threading items through a queue.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;Long story short, I submitted a&amp;nbsp;&lt;a href=&quot;http://dev.clojure.org/jira/browse/CLJ-776&quot;&gt;bug report&lt;/a&gt;&amp;nbsp;and wrote something that works for me.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;&lt;em&gt;Update: I'm not even sure It's possible anymore to write seque so that it works in all cases.&lt;/em&gt;&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ns&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;test&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;:import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;concurrent&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;BlockingQueue&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;LinkedBlockingQueue&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;SynchronousQueue&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;PriorityBlockingQueue&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;CyclicBarrier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;:use&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;:refer-clojure&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:exclude&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;seque&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; some BlockingQueues are...&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; not ordered&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; not finite&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; unable to contain nil&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; without content&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; mutable&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; dropping or recieving extra items&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; seque...&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; fills the que on another thread&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; propagates errors&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; replaces nil with a sentinel&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; detects the end of the input seq&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; can be consumed on any thread&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;seque&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&amp;quot;Creates a queued seq on another (presumably lazy) seq s. The queued&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  seq will produce a concrete seq in the background, and can get up to&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  n items ahead of the consumer. n-or-q can be an integer n buffer&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  size, or an instance of java.util.concurrent BlockingQueue. Note&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  that reading from a seque can block if the reader gets ahead of the&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  producer.&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:added&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;seque&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;n-or-q&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;^BlockingQueue&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;instance? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BlockingQueue&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;n-or-q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                             &lt;span class=&quot;nv&quot;&gt;n-or-q&lt;/span&gt;
                             &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;LinkedBlockingQueue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;n-or-q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;NIL&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;;nil sentinel since BQ doesn&amp;#39;t support nils&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fnil&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;identity&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;NIL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;channel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;LinkedBlockingQueue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;fill&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;fill&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try&lt;/span&gt;
                  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;do&lt;/span&gt;
                      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;put&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;channel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;take&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;put&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recur&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;put&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;channel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;InterruptedException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
                  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;e&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;put&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;channel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;fut&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;future&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fill&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;drain&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;drain&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
                 &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lazy-seq&lt;/span&gt;
                   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try&lt;/span&gt;
                     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cons &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;take&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;channel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;drain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;InterruptedException&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))]&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;identical? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;NIL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;drain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;trickle&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;slow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Thread/sleep&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;slow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deftest&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;identity?&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;seque&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deftest&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;priority&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;count &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;seque&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;PriorityBlockingQueue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:a&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:b&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:c&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deftest&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;synchronous&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;seque&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SynchronousQueue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deftest&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nils&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;seque&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]])&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]])))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deftest&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;errors&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;thrown?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Throwable&lt;/span&gt;
               &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dorun &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;seque&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deftest&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;threads&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;seque&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SynchronousQueue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;f1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;future&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;doall &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;f2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;future&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;doall &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;@f1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;@f2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;moronic&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; untestable&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;LinkedBlockingQueue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;future&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dotimes &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Thread/yield&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;poll&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;future&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dotimes &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Thread/yield&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;offer&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;seque&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
		
		<category term="clojure" />
		
		<category term="seque" />
		
	</entry>
	
	<entry>
		<title>PyMouse is looking for a new home</title>
		<link href="http://pepijndevos.nl/pymouse-is-looking-for-a-new-home/index.html"/>
		<updated>2011-04-16T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/pymouse-is-looking-for-a-new-home/pymouse-is-looking-for-a-new-home</id>
		<content type="html">&lt;div style=&quot;&quot;&gt;First of all, thank you very much for your interest and support in PyMouse over the years.&lt;/div&gt;&lt;p /&gt;&lt;div style=&quot;&quot;&gt;I have some sad news however. There are some outstanding issues and pull requests that need attention, and I haven’t been giving them any recently.&lt;/div&gt;&lt;p /&gt;&lt;div style=&quot;&quot;&gt;I started PyMouse back in 2009 for making a remote control with my iPod Touch. Since then I haven’t used PyMouse much.&lt;/div&gt;&lt;p /&gt;&lt;div style=&quot;&quot;&gt;PyMouse was my first big project, and still has the most watchers and forks on Github. I put a lot of energy in figuring out all the platform specific details, and learnt a lot from it.&lt;/div&gt;&lt;p /&gt;&lt;div style=&quot;&quot;&gt;However, I think the time has come to say goodbye, and hand it over to the community.&lt;/div&gt;&lt;p /&gt;&lt;div style=&quot;&quot;&gt;I put the project on &lt;a href=&quot;http://stillmaintained.com/pepijndevos/PyMouse&quot;&gt;stillmaintained.com&lt;/a&gt;, and if you are interested in taking over, please send me a message.&lt;/div&gt;
</content>
		
	</entry>
	
	<entry>
		<title>On the proccess of writing a game engine in Clojure</title>
		<link href="http://pepijndevos.nl/on-the-proccess-of-writing-a-game-engine-in-c/index.html"/>
		<updated>2011-04-14T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/on-the-proccess-of-writing-a-game-engine-in-c/on-the-proccess-of-writing-a-game-engine-in-c</id>
		<content type="html">&lt;p&gt;Or at least a set of engine-framework-commons-utils.&lt;/p&gt;
&lt;p&gt;There have been a few games and simulations in Clojure before, a few notable ones:&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The grandmother of all Clojure games is probably&amp;nbsp;&lt;a href=&quot;http://groups.google.com/group/clj-la/browse_thread/thread/1ea791516715487e&quot;&gt;ants.clj&lt;/a&gt;&amp;nbsp;by Rich himself, mostly a demonstration of concurrency in Clojure.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://mikera.net/ironclad/&quot;&gt;Ironclad&lt;/a&gt;&amp;nbsp;is a game that deserves to be noted for its completeness; It's more than just an example.&lt;/p&gt;
&lt;p&gt;And finally, this&amp;nbsp;&lt;a href=&quot;http://briancarper.net/blog/520/making-an-rpg-in-clojure-part-one-of-many&quot;&gt;unnamed&lt;/a&gt;(and likely unfinished as well) RPG, not so much for the game as for the blog post that describes the process of writing it.&lt;/p&gt;
&lt;p&gt;Just like Brian, I went through the process of agents and OpenGL, but let us begin with the begin.&lt;/p&gt;
&lt;h2&gt;Design 0: I want to make a game.&lt;/h2&gt;
&lt;p&gt;It's as simple as that. A nice and simple 2D game in Clojure. I started googling for game engines in Java and Clojure. The only ones I found that I liked and that did not look like they came from a past century where&amp;nbsp;&lt;a href=&quot;http://slick.cokeandcode.com/&quot;&gt;Slick&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href=&quot;http://www.interactivepulp.com/pulpcore/&quot;&gt;PulpCore&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Problem is, I did not even manage to compile Slick, and PulpCore is for applets only. Besides, they both use very OOP models that I suppose would feel awkward in Clojure.&lt;/p&gt;
&lt;p&gt;So after reading a few opinions about Swing vs OpenGL, I decided to write my own game in Clojure based on Swing.&lt;/p&gt;
&lt;h2&gt;Design 1: Agents, agents, agents...&lt;/h2&gt;
&lt;p&gt;My initial design philosophy was very simple. It should be&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;multithreaded&lt;/li&gt;
&lt;li&gt;functional&lt;/li&gt;
&lt;li&gt;easy&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So I set up an agent with a vector, made a Swing frame and overwrote its paintComponent to draw the objects in the vector to the frame.&lt;/p&gt;
&lt;p&gt;Then I added a watcher to the agent to mark all changed objects dirty on the Swing frame, so they would be redrawn.&lt;/p&gt;
&lt;h2&gt;Design 1.1: Changed?&lt;/h2&gt;
&lt;p&gt;Okay, which object changed? Hard to tell. I turned the vector into a map, a set, and a map again, so that I could use clojure.set/difference to tell what happened.&lt;/p&gt;
&lt;h2&gt;Design 1.2: I can walk through walls!&lt;/h2&gt;
&lt;p&gt;Wait, we need collision detection. Simple, right?&lt;/p&gt;
&lt;p&gt;Doing this the naive way would mean a quadratical increase in comparisons.&amp;nbsp;I was well on my way implementing a quad tree when it hit me: For any non-huge number of objects, it's not worth the trouble.&lt;/p&gt;
&lt;p&gt;I changed whatever I had at that moment into a sorted variant, so that I only had to check objects that where at least close in one dimension.&lt;/p&gt;
&lt;h2&gt;Design 1.999: This is getting out of hand!&lt;/h2&gt;
&lt;p&gt;At this moment I had changed every single line of code around 3 times. I had atoms, refs and agents, containing vectors, sets, maps, calling multimethods and protocols, I was knee-deep in thread pools and transactions when I remembered my second 2 goals.&lt;/p&gt;
&lt;p&gt;This beautiful, concurrent, asynchronous design that I had was just not functional and easy at all. It had mutable state and transactions everywhere.&lt;/p&gt;
&lt;h2&gt;Design 2: I'm back in the loop.&lt;/h2&gt;
&lt;p&gt;After a few more sidetracks, I switched to active rendering and reduced my game loop to something like this pseudo-code.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ns&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;game&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;world&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;lt;fooinstance&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:bar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;lt;barinstance&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;window&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;JPanel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;800&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;800&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;doseq &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;iterate &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;act&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;world&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;obj&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;draw&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;obj&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;h2&gt;Design 2.1: Reality.&lt;/h2&gt;
&lt;p&gt;After all this theorizing and experimenting, I finally got my stuff stable enough to actually write a little game; pong.&lt;/p&gt;
&lt;p&gt;Let me say this about it: Few lines of the original pong game and my engine where left unchanged, but they where more subtle changes than before.&lt;/p&gt;
&lt;p&gt;Next, I wrote a simple platform game. Again, changes where made.&lt;/p&gt;
&lt;h2&gt;Current design: Are we there yet?&lt;/h2&gt;
&lt;p&gt;I feel like what I have now is nearly ready to share with the world. I do believe that an event, or&amp;nbsp;&lt;a href=&quot;http://prog21.dadgum.com/23.html&quot;&gt;message processing&lt;/a&gt;&amp;nbsp;based system could work, but what I have now does so too.&lt;/p&gt;
&lt;p&gt;Begame currently provides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A game loop&lt;/li&gt;
&lt;li&gt;Time based animation&lt;/li&gt;
&lt;li&gt;Collision detection&lt;/li&gt;
&lt;li&gt;All the Swing stuff you don't care about&lt;/li&gt;
&lt;li&gt;Protocols      
&lt;ul&gt;
&lt;li&gt;actor; objects that do stuff&lt;/li&gt;
&lt;li&gt;visible; objects that draw themselves&lt;/li&gt;
&lt;li&gt;solid; objects involved in collision detection&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Get it.&lt;/h2&gt;
&lt;p&gt;See the&amp;nbsp;&lt;a href=&quot;https://github.com/pepijndevos/Begame/tree/master/src/examples&quot;&gt;examples&lt;/a&gt;, and check out the&amp;nbsp;&lt;a href=&quot;https://github.com/pepijndevos/Begame/&quot;&gt;source&lt;/a&gt;&amp;nbsp;from Github.&lt;/p&gt;
</content>
		
		<category term="begame" />
		
		<category term="clojure" />
		
		<category term="game" />
		
	</entry>
	
	<entry>
		<title>Sudoku in Logos</title>
		<link href="http://pepijndevos.nl/sudoku-in-logos/index.html"/>
		<updated>2011-03-17T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/sudoku-in-logos/sudoku-in-logos</id>
		<content type="html">&lt;p&gt;Upon reading the Prolog chapter in Seven Languages in Seven Weeks, I wanted to attempt the Sudoku example in Logos.&lt;/p&gt;

&lt;p&gt;I quickly found out that Logos had quite a few less helpers than Prolog. In Prolog, you just say fd_all_different on all the rows and columns, not so in Logos. Then I read fd_all_different is implemented as ≢'ing all elements. But then again, Logos does not yet support negation.&lt;/p&gt;

&lt;p&gt;So rather than saying &amp;ldquo;a number can not be on the same row twice&amp;rdquo; I had to say &amp;ldquo;this row must contain all numbers from 1 to 9 once&amp;rdquo;. This is done in permutation-o.&lt;/p&gt;

&lt;p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ns&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;logos&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sudoku&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;:refer-clojure&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:exclude&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;reify&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;inc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;:use&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;logos&lt;/span&gt;
           &lt;span class=&quot;nv&quot;&gt;minikanren&lt;/span&gt;
           &lt;span class=&quot;nv&quot;&gt;logic&lt;/span&gt;
           &lt;span class=&quot;nv&quot;&gt;nonrel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;
            &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)])&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bad-board&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
                &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;
                &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;
                &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;full-board&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
                 &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
                 &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;
                 &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
                 &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
                 &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;
                 &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
                 &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
                 &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;almost-board&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                   &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                   &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                   &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                   &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                   &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                   &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                   &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                   &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)])&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;empty-board&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;81&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;lvar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;disj-o&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cond-e&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;;a&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cons-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;exist&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cons-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cons-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;disj-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;permutation-o&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cond-e&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;== &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;== &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;exist&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cons-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cons-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;disj-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permutation-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;blocks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mapcat &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;concat&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partition&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partition&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;
                  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;drop &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;slice&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rows&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partition&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;cols&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;apply &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;blocks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;blocks&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rows&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cols&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;blocks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defmacro &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sudoku&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;81&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;gensym&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rows&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cols&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;blocks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;slice&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;permfn&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
                 &lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;permutation-o&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;~@row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;concat&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;exist&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;~@board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;== &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;~b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;~@board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;interleave&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;permfn&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;permfn&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cols&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;permfn&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;blocks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/p&gt;

&lt;p&gt;The beauty of Logos and logic programming in general is that it allows you to tell the computer the data and the rules, instead of telling it what to do. You&amp;rsquo;d imagine this to be shorter as well. Furthermore, miniKanren is quite efficient, and Logos equally so.&lt;/p&gt;

&lt;p&gt;So, how does this code compare to a regular Clojure version? To tell you the truth, not good. The plain Clojure version is both shorter and faster. By how much?&lt;/p&gt;

&lt;p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ns&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;sudoku&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;:use&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pprint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;:require&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;clojure&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;
            &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;
            &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;
            &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;
            &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hard&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; 3 added&lt;/span&gt;
           &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;
           &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;
           &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;
           &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;
           &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;
           &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;
           &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;
           &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; can be either 7 or 9&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;from-blocks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;19&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;21&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;22&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;26&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;27&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;36&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;45&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;37&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;46&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;29&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;38&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;47&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;39&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;31&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;49&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;41&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;33&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;51&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;34&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;43&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;52&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;35&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;44&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;53&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;54&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;63&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;72&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;55&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;73&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;56&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;65&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;74&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;57&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;66&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;75&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;58&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;67&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;76&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;59&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;68&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;77&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;69&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;78&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;61&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;70&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;79&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;62&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;71&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;to-blocks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;27&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;29&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;54&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;55&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;56&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;31&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;57&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;58&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;59&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;33&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;34&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;35&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;61&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;62&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;36&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;37&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;38&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;63&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;65&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;39&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;41&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;66&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;67&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;68&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;43&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;44&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;69&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;70&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;71&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;19&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;45&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;46&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;47&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;72&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;73&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;74&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;21&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;22&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;49&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;75&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;76&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;77&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;26&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;51&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;52&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;53&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;78&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;79&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;reduceable-board&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cell&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;number?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;cell&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;prune&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;nrs&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;filter &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;number?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cell&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cond&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;number?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cell&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;count &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;:else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;s/difference&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cell&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nrs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;transpose&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;old&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;apply &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;assoc&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;vec&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;old&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;interleave &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;mapping&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;old&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;slice&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rows&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;prune&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partition&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;cols&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;prune&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;apply &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;blocks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;prune&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partition&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transpose&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;flatten&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cols&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;to-blocks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transpose&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;flatten&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;blocks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;from-blocks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sudoku&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;loop &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reduceable-board&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;next-board&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;slice&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pprint&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partition&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;next-board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;or &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;board&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;next-board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;every? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;number?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;next-board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;some &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;next-board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;next-board&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recur&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;next-board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/p&gt;

&lt;p&gt;The Clojure code is just a tad shorter, but not significantly so. With pattern matching and negation in place(more on that later), I think the difference becomes negligible.&lt;/p&gt;

&lt;p&gt;In speed, however, the difference is huge. The Clojure version can solve a Sudoku in a matter of seconds, I had to leave the Logos version running overnight. Truth be told, for smaller fields or very, very easy boards, Logos can do it in half a second as well. This is why most examples implement &lt;a href=&quot;http://boss-level.com/?p=66&quot;&gt;mini-sudoku&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There is light at the end of the tunnel though! A recent update to Logos adds pattern matching, which allows for a more Prolog-ish way to express relations.&lt;/p&gt;

&lt;p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;defn-e&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;append-o&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;([()&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;([[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;?d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;?r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;append-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;?d&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;?r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;append-o&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cond-e&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;null-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;== &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;exist&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cons-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cons-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;append-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/p&gt;

&lt;p&gt;Negation is also planned, which would make it a lot faster to express the relation the numbers in a Sudoku row have.&lt;/p&gt;

&lt;p&gt;Last but not least, cond-a and cond-u will return, allowing me to cut away useless branches. Cond-a quits after the first match, rather than searching for alternate solutions.&lt;/p&gt;
</content>
		
		<category term="clojure" />
		
		<category term="logos" />
		
		<category term="prolog" />
		
		<category term="sudoku" />
		
	</entry>
	
	<entry>
		<title>Pure CSS Minecraft skin previewer</title>
		<link href="http://pepijndevos.nl/pure-css-minecraft-skin-previewer/index.html"/>
		<updated>2011-02-26T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/pure-css-minecraft-skin-previewer/pure-css-minecraft-skin-previewer</id>
		<content type="html">&lt;p&gt;If you where expecting the second part of my bookshelf, hang on, it's nearly done.&lt;/p&gt;
&lt;p&gt;Meanwhile, a few friends set up a Minecraft server, and I joined them to dig some holes and build a house.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/2011-02-26_13.42.05.png&quot; alt=&quot;Pure CSS Minecraft skin previewer&quot; /&gt;&lt;/p&gt;
&lt;p&gt;A neat thing with Minecraft is that you can make your own skin, only, it doesn't really look like something when you open it in Photoshop.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/pepijndevos.png&quot; alt=&quot;Pure CSS Minecraft skin previewer&quot; /&gt;&lt;/p&gt;
&lt;p&gt;There are a few skin editors floating around the web, but nothing with the power of Photoshop. So as a programmer, I decided to craft my own viewer, rather than installing some weird piece of software.&lt;/p&gt;
&lt;p&gt;What you see here is a piece of CSS that uses transforms and background-position(tiles) to show me a preview of my new skin. Thus, my workflow consisted of editing, saving, refreshing and more editing.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/Screen_shot_2011-02-25_at_4.36.png&quot; alt=&quot;Pure CSS Minecraft skin previewer&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Live demo, showing my current skin: &lt;a href=&quot;http://wishfulcoding.nl/char/char.html&quot;&gt;http://wishfulcoding.nl/char/char.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Recent versions of Safari, Chrome and Firefox should be able to preview you own skins.&lt;/p&gt;
</content>
		
		<category term="css" />
		
		<category term="minecraft" />
		
	</entry>
	
	<entry>
		<title>My bookshelf 2/5: The Reasoned Schemer</title>
		<link href="http://pepijndevos.nl/my-bookshelf-25-the-reasoned-schemer/index.html"/>
		<updated>2011-02-26T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/my-bookshelf-25-the-reasoned-schemer/my-bookshelf-25-the-reasoned-schemer</id>
		<content type="html">&lt;p&gt;This is the second part of&amp;nbsp;&lt;a href=&quot;http://pepijndevos.nl/tag/bookshelf&quot;&gt;my bookshelf&lt;/a&gt;, a series of posts about a couple of books I'm reading.&lt;/p&gt;
&lt;div&gt;Unlike the CouchDB book, The Reasoned Schemer(TRS henceforth) is a book that you don't simply read on the couch, but actually study. This is why it took weeks rather than days to come to this point, where I understand how to use(but not implement) miniKanren.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;The book has a gradient on the cover, which gives it the impression of a technical book(it's from MIT press), but it actually contains drawings and the typesetting is brilliant(it is written with some sort of LaTeX I believe).&amp;nbsp;It is also very suitable for vegetarians, since it uses vegetarian food rather than foo/bar/baz.&lt;/div&gt;
&lt;div&gt;&lt;img src=&quot;/images/9780262562140-f30.jpeg&quot; alt=&quot;My bookshelf 2/5: The Reasoned Schemer&quot; /&gt;&lt;/div&gt;
&lt;div&gt;The book is written in questions and answers, both in separate columns. You could overlay the answers, and try them yourself first.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;TRS describes miniKanren, a logic programming language. It is the bare essence of Prolog and Kanren, written in a few hundred lines of Scheme.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;I used&amp;nbsp;&lt;a href=&quot;https://github.com/swannodette/logos&quot;&gt;Logos&lt;/a&gt;, an implementation in Clojure by David Nolen, to follow the examples in the book. This worked out very well, but there are a couple of minor differences.&lt;/div&gt;
&lt;div&gt;
&lt;ul class=&quot;MailOutline&quot;&gt;
&lt;li&gt;fresh is called exist in Logos.&lt;/li&gt;
&lt;li&gt;Logos uses vectors for binding variables.&lt;/li&gt;
&lt;li&gt;Everything is interleaving, so there are no cond-i and all-i.&lt;/li&gt;
&lt;li&gt;Clojure does hot have pairs, and only proper conses are allowed, it uses lcons instead.&lt;/li&gt;
&lt;li&gt;Clojure has first and rest, so car-o and cdr-o are called after their clojure.core counterparts.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;Later in the book, an arithmetic system is implemented in miniKanren. I attempted to&amp;nbsp;&lt;a href=&quot;https://github.com/pepijndevos/logos/blob/master/src/logos/number.clj&quot;&gt;port it to Logos&lt;/a&gt;, though it is not complete and bug free yet.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;I do not yet fully understand the last few chapters of the book, one of which describes unification. The last chapter is unique in the book in that it does not use the question-answer style, but rather explains the inner workings of miniKanren in tightly packed chunks of information.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;I really enjoyed the book, and I hope to find some good uses for my newly acquired powers.&lt;/div&gt;
</content>
		
		<category term="bookshelf" />
		
		<category term="clojure" />
		
		<category term="logos" />
		
		<category term="minikanren" />
		
	</entry>
	
	<entry>
		<title>My bookshelf 1/5: CouchDB</title>
		<link href="http://pepijndevos.nl/my-bookshelf-15-couchdb/index.html"/>
		<updated>2011-02-10T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/my-bookshelf-15-couchdb/my-bookshelf-15-couchdb</id>
		<content type="html">&lt;p&gt;I recently ordered four programming books from Amazon, and one from Manning. I'm planning to share some comments, insights, thoughts and something akin to a review, as I 'resurface' on the web in between my reading spurts.&lt;/p&gt;
&lt;div&gt;
&lt;div style=&quot;&quot;&gt;&lt;img src=&quot;/images/unknown.png&quot; alt=&quot;My bookshelf 1/5: CouchDB&quot; /&gt;&lt;/div&gt;
&lt;div&gt;I started with&amp;nbsp;&lt;a href=&quot;http://guide.couchdb.org/&quot;&gt;CouchDB: A definitive Guide&lt;/a&gt;, because I expected it to be the least mind-taxing of the five, and because I am considering CouchDB for two projects of mine.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;The book contains a lot of good information, but is also very messy in places. It is baginer-paced, but omits a lot of details.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;I found the first chapters, the chapter about CouchApp and the appendices to be the most informative.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;The first chapters take you on a high-level tour of CouchDB, with a great deal of fine information.&amp;nbsp;I was pleasantly reminded of the nature of MVCC and B-trees.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;Multi Version Concurrency Control means there is absolutely no locking involved, so reads are really fast. Even more so, because views are generated on writing.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;Because both databases and views are stored as B-trees, a surprising number of actions are completed in logarithmic time. Surprising ones include updating a (re)reduced view, and taking a range from a large number of items.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;Another thing to remember is that everything is sorted by keys, and that keys can be complex types, such as lists.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;After about half of the book, I started to skip sections, and I completely skipped the chapters about scaling, which seem nearly inappropriate for a beginner-level book.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;One chapter I did read thoroughly is the chapter about CouchApp. CouchApp makes it really easy to maintain and deploy complex web applications that run &lt;em&gt;sans&amp;nbsp;lingua&lt;/em&gt;(I made that up; it means &quot;nothing but CouchDB&quot;).&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;That chapter was really helpful, but comes with a flip-side. The information about CouchApp on the web is&amp;nbsp;&lt;a href=&quot;http://couchapp.org/page/what-is-couchapp&quot;&gt;really sparse&lt;/a&gt;:&lt;/div&gt;
&lt;div&gt;
&lt;blockquote class=&quot;posterous_short_quote&quot;&gt;This blog post is in response to a lot of well-deserved confusion in the community around CouchApps.&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div&gt;The appendices mainly go into detail about things like installation and the details about the use of B-trees.&lt;/div&gt;
&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;So, that's it for now. I'd call this book a &quot;good mess&quot;. Keep an eye on this blog or my Twitter feed for the next books, and my first CouchDB apps.&lt;/div&gt;
</content>
		
		<category term="book" />
		
		<category term="bookshelf" />
		
		<category term="couchdb" />
		
		<category term="review" />
		
	</entry>
	
	<entry>
		<title>Take n distinct random items from a vector</title>
		<link href="http://pepijndevos.nl/take-n-distinct-random-items-from-a-vector/index.html"/>
		<updated>2011-02-01T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/take-n-distinct-random-items-from-a-vector/take-n-distinct-random-items-from-a-vector</id>
		<content type="html">&lt;p&gt;Another IRC hacking session.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://a.yfrog.com/img831/9729/10745599.png&quot; alt=&quot;plot&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://a.yfrog.com/img819/1616/42647628.png&quot; alt=&quot;plot&quot; /&gt;&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;ns&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;test&lt;/span&gt;
  &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sy&quot;&gt;:use&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;incanter core charts&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;; naive, O(n+m)&lt;/span&gt;
&lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;defn&lt;/span&gt; take-rand1 &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;n coll&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;take&lt;/span&gt; n &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;shuffle coll&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;; lazy, O(n!@#$%m^&amp;amp;)&lt;/span&gt;
&lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;defn&lt;/span&gt; take-rand2 &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;n coll&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;take&lt;/span&gt; n &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;distinct&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;repeatedly&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;#(&lt;/span&gt;rand-nth coll&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;; reduce, reorder, subvec, O(m)&lt;/span&gt;
&lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;defn&lt;/span&gt; take-rand3 &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;nr coll&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;len &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;count&lt;/span&gt; coll&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;; why doesn't rand-int take a start?&lt;/span&gt;
        &lt;span class=&quot;r&quot;&gt;rand-int&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;lo hi&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;+&lt;/span&gt; lo &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;rand-int&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;-&lt;/span&gt; hi lo&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;subvec&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;range&lt;/span&gt; nr&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
                 &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;reduce&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;#(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;conj&lt;/span&gt; %1 &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;%2 &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;rand-int&lt;/span&gt; %2 len&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
                 &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;reduce&lt;/span&gt;
                   &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;fn&lt;/span&gt; swap &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;a &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;i b&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;
                      &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;assoc&lt;/span&gt; a b &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;get&lt;/span&gt; a i&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; i &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;get&lt;/span&gt; a b&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
                   coll&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;i&quot;&gt;0&lt;/span&gt; nr&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;; amalloy, O(m)&lt;/span&gt;
&lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;defn&lt;/span&gt; take-rand4 &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;num&lt;/span&gt; coll&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;first&lt;/span&gt;
   &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;nth&lt;/span&gt;
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;iterate&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;ret candidates&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;
               &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;idx &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;rand-int&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;count&lt;/span&gt; candidates&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;
                 &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;conj&lt;/span&gt; ret &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;candidates idx&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
                  &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;subvec&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;assoc&lt;/span&gt; candidates idx &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;candidates &lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
                          &lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;
              coll&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;r&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;defn&lt;/span&gt; t &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;f&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;start &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;.&lt;/span&gt; System &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;nanoTime&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;.&lt;/span&gt; System &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;nanoTime&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; start&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;defn&lt;/span&gt; plot-len &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;f n&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;coll &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;vec&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;range&lt;/span&gt; n&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;t &lt;span class=&quot;of&quot;&gt;#(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;doall&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;f &lt;span class=&quot;i&quot;&gt;1000&lt;/span&gt; coll&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;defn&lt;/span&gt; plot-take &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;f n&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;coll &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;vec&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;range&lt;/span&gt; &lt;span class=&quot;i&quot;&gt;100000&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;t &lt;span class=&quot;of&quot;&gt;#(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;doall&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;f n coll&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; x &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;range&lt;/span&gt; &lt;span class=&quot;i&quot;&gt;1000&lt;/span&gt; &lt;span class=&quot;i&quot;&gt;100000&lt;/span&gt; &lt;span class=&quot;i&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;scatter-plot x &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;partial&lt;/span&gt; plot-len  take-rand1&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; x&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;sy&quot;&gt;:series-label&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;shuffle&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;sy&quot;&gt;:legend&lt;/span&gt; true&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;add-points   x &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;partial&lt;/span&gt; plot-len  take-rand2&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; x&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;sy&quot;&gt;:series-label&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;filtered&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;add-points   x &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;partial&lt;/span&gt; plot-len  take-rand3&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; x&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;sy&quot;&gt;:series-label&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;add-points   x &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;partial&lt;/span&gt; plot-len  take-rand4&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; x&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;sy&quot;&gt;:series-label&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;iterate&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;save &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;len.png&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;; http://yfrog.com/5r80779474p&lt;/span&gt;

&lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;scatter-plot x &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;partial&lt;/span&gt; plot-take take-rand1&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; x&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;sy&quot;&gt;:series-label&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;shuffle&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;sy&quot;&gt;:legend&lt;/span&gt; true&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;add-points   x &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;partial&lt;/span&gt; plot-take take-rand2&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; x&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;sy&quot;&gt;:series-label&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;filtered&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;add-points   x &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;partial&lt;/span&gt; plot-take take-rand3&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; x&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;sy&quot;&gt;:series-label&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;add-points   x &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;partial&lt;/span&gt; plot-take take-rand4&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; x&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;sy&quot;&gt;:series-label&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;iterate&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;save &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;take.png&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;; http://yfrog.com/mr42647628p&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
</content>
		
		<category term="clojure" />
		
	</entry>
	
	<entry>
		<title>Sorting obsession</title>
		<link href="http://pepijndevos.nl/sorting-obsession/index.html"/>
		<updated>2011-01-15T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/sorting-obsession/sorting-obsession</id>
		<content type="html">&lt;p&gt;It all started when, one day, I was thinking about the little I knew about sorting. What I knew was that sorting was usually done by comparing all items and switching them around, hitting the magical O(nlogn) barrier.&lt;/p&gt;
&lt;p&gt;Thinking about how I would sort a deck of cards, sorting seemed more like a O(n) operation. With that in mind, I started implementing what turned out to be called&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/Pigeonhole_sort&quot;&gt;Pigeonhole Sort&lt;/a&gt;. I also learned that sorting algorithms can be classified as being a&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/Comparison_sort&quot;&gt;Comparison sort&lt;/a&gt;&amp;nbsp;or not.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ns&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pigeonhole-sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;int-sort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;listmap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;reduce &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;update-in&lt;/span&gt;
                           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update-in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fnil&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;inc&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                           &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;max&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:max&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mapcat &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;repeat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;listmap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;inc &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;:max&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;listmap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;With that out of the way, I started to compare my sort to the sort used by Java and Clojure, which turned out to be using&amp;nbsp;&lt;a href=&quot;http://sortvis.org/algorithms/timsort.html&quot;&gt;Timsort&lt;/a&gt;,&amp;nbsp;originating in Python. In my quest to understand Timsort - and why it was faster than my Pigeonhole Sort - I found &lt;a href=&quot;http://sortvis.org/index.html&quot;&gt;this great website that graphs how different sort algorithms work&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Simply put, I was intrigued by the pattern displayed by&amp;nbsp;&lt;a href=&quot;http://sortvis.org/algorithms/heapsort.html&quot;&gt;Heap Sort&lt;/a&gt;. So next I found myself reading the Wikipedia pages for&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/Binary_heap&quot;&gt;Binary Heaps&lt;/a&gt;, and shortly after that, I had started implementing that in Clojure.&lt;/p&gt;
&lt;p&gt;This is, ladies and gentleman, a persistent heap, in all its heapyness, with a heapsort implemented on top of it.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ns&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;persistent-heap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;swap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;assoc &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idy&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;children&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;inc &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;* &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;idy&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;inc &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;not= &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;/ &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;- &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;odd?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tree&lt;/span&gt; 
  &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;children &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;node&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap-up&lt;/span&gt; 
  &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;heap-up&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dec &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;count &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compfn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;heap-up&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compfn&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dec &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;count &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compfn&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;if-let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;par&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;compfn&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;par&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recur&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;swap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;par&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compfn&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;par&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap-down&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;heap-down&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;pop &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;swap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dec &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;count &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compfn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;heap-down&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;pop &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;swap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dec &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;count &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compfn&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compfn&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;children &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;leftv&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;left&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;rightv&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;right&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;and &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;leftv&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rightv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cond&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;compfn&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;leftv&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;max &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rightv&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recur&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;swap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compfn&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;compfn&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rightv&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;max &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;leftv&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recur&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;swap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;idx&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compfn&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;:else&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deftype&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;PersistentHeap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ISeq&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;PersistentHeap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;heap-down&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;more&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cons &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;PersistentHeap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;heap-up&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;conj &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;persistent-heap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;coll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;into &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;PersistentHeap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;coll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;heapsort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;coll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;persistent-heap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;coll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;iterate &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;take &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;count &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;coll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;Some 'benchmark' results:&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;nv&quot;&gt;user=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;time &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dorun &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;heapsort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;shuffle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;e5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 3148.041 msecs&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;user=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;time &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dorun &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;int-sort&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;shuffle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;e5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 477.781 msecs&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;user=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;time &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dorun &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sort &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;shuffle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;e5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&amp;quot;Elapsed time: 105.354 msecs&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;Note that heapsort is lazy, insofar that it does realize but does not sort the sequence untill requested. There is also a bug that allows for the last 2 items to be out of order.&lt;/p&gt;
</content>
		
		<category term="clojure" />
		
		<category term="sorting" />
		
	</entry>
	
	<entry>
		<title>I'm tired of the NoSQL buzz, and bring you SlouchDB</title>
		<link href="http://pepijndevos.nl/im-tired-of-the-nosql-buzz-and-bring-you-slou/index.html"/>
		<updated>2011-01-13T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/im-tired-of-the-nosql-buzz-and-bring-you-slou/im-tired-of-the-nosql-buzz-and-bring-you-slou</id>
		<content type="html">&lt;p&gt;It has all the features your favorite NoSQL database has.&lt;/p&gt;
&lt;div&gt;
&lt;ul class=&quot;MailOutline&quot;&gt;
&lt;li&gt;Fast&lt;/li&gt;
&lt;li&gt;Scalable&lt;/li&gt;
&lt;li&gt;Concurrent&lt;/li&gt;
&lt;li&gt;Key/value store&lt;/li&gt;
&lt;li&gt;Document orientated&lt;/li&gt;
&lt;li&gt;MapReduce&lt;/li&gt;
&lt;li&gt;In-memory&lt;/li&gt;
&lt;li&gt;Persistent&amp;nbsp;&lt;strong&gt;&lt;span style=&quot;color: #f8201c;&quot;&gt;*&lt;/span&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;NoSQL&lt;/li&gt;
&lt;li&gt;REST API&amp;nbsp;&lt;strong&gt;&lt;span style=&quot;color: #f8201c;&quot;&gt;*&lt;/span&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Written in X, so...&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;span style=&quot;color: #f81f1c;&quot;&gt;&lt;strong&gt;*&lt;/strong&gt;&lt;/span&gt; Requires a &lt;span style=&quot;text-decoration: underline;&quot;&gt;few&lt;/span&gt; extra lines.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;The implementation looks like this.&lt;/div&gt;
&lt;p /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ns&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;slouchdb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; Fast scalable in-memory concurrent NoSQL database&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ref &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:bob&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:age&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;59&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:sex&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:male&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
              &lt;span class=&quot;nv&quot;&gt;:bill&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:age&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:sex&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:male&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
              &lt;span class=&quot;nv&quot;&gt;:mary&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:age&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:sex&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:female&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; Views ;;&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;total-age&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;reduce &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;pmap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;comp &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:age&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;@db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; Parallel MapReduce!&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; Examples ;;&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;apply &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;interpose&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;\newline&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Get an item&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;:bob&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;@db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&amp;quot;MapReduce&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;total-age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&amp;quot;Add/update an item&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dosync &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;alter &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;assoc-in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:bill&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&amp;quot;Delete an item&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dosync &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;alter &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dissoc&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:mary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))])))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; For scaling, press CMD or CTRL and + or -&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; For a persistent version, see java.io.Serializable&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; For a REST API, check out Moustache and Aleph.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
		
		<category term="nosql" />
		
	</entry>
	
	<entry>
		<title>Cooperative concurrency in Clojure</title>
		<link href="http://pepijndevos.nl/cooperative-concurrency-in-clojure/index.html"/>
		<updated>2011-01-05T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/cooperative-concurrency-in-clojure/cooperative-concurrency-in-clojure</id>
		<content type="html">&lt;p&gt;Today I had an interesting discussion about cheap preemptive threads in Clojure. Someone claimed Haskell can easily start 10.000 threads without getting slow, while Clojure - and native threads in general - do get slow after a couple of thousands.&lt;/p&gt;
&lt;p&gt;After a discussion about Agents and thread pools, I proposed cooperative concurrency as a cheap solution. Cooperative concurrency isn't exactly preemptive, but it works. This is a for-fun implementation of trampoline using a hidden gem in Clojure called PersistentQueue.&lt;/p&gt;
&lt;p&gt;Like trampoline, recursive functions return another function, which get called in a loop. Unlike trampoline, mine takes a seq of functions, puts them into a queue and executes the frontmost function, putting the result on the back of the queue.&lt;/p&gt;
&lt;p&gt;Below is an example of the classic &lt;a href=&quot;http://jakemccrary.com/blog/2010/12/06/trampolining-through-mutual-recursion.html&quot;&gt;mutual recursive odd and even functions&lt;/a&gt; running in parallel, or alternating actually. Like pcalls, but on a single thread.&lt;/p&gt;
&lt;div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ns&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cooperative&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cooperative-tasks&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&amp;quot;Trampoline over a queue for&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;  cooperative multitasking&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;not-any? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;fn?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;fs&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recur&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;doall &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fn?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))))&lt;/span&gt;


&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;comment&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my-odd?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;my-even?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;zero? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;my-odd?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dec &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Math/abs&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;my-odd?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;zero? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;false&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;my-even?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dec &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Math/abs&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cooperative-tasks&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;my-odd?&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50009&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;my-odd?&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50008&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;my-even?&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50008&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;my-even?&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50009&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)])&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
		
		<category term="clojure" />
		
		<category term="concurrency" />
		
	</entry>
	
	<entry>
		<title>Happy Christmas!</title>
		<link href="http://pepijndevos.nl/happy-christmas/index.html"/>
		<updated>2010-12-24T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/happy-christmas/happy-christmas</id>
		<content type="html">&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ns&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;xmas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;doseq &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;concat &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;take &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;str&lt;/span&gt;
                                          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;take &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+ &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rem &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                                                   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;/ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
                                                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;repeat &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;*&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
                                  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
                     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;take &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;repeat &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;*&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;%1$30s*%1$s&amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;                              *&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;                             ***&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;                            *****&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;                             ***&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;                            *****&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;                           *******&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;                            *****&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;                           *******&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;                          *********&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;                             ***&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;                             ***&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

</content>
		
	</entry>
	
	<entry>
		<title>8 ways to tell how many Xes are in a list</title>
		<link href="http://pepijndevos.nl/6-ways-to-tell-how-many-xes-are-in-a-list/index.html"/>
		<updated>2010-12-22T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/6-ways-to-tell-how-many-xes-are-in-a-list/6-ways-to-tell-how-many-xes-are-in-a-list</id>
		<content type="html">&lt;p&gt;Inspired by a question on #clojure. There we go.&lt;/p&gt;

&lt;p&gt;mrBliss(1):&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;(count (filter #{1} '(1 2 4 5 1 5 2))) ; Use this&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Raynes:&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;(count ((group-by identity [1 2 3 4 5 1 5 2]) 1))&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Me(1):&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;(get (frequencies [1 2 3 1 2 3]) 1) ; Or this&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Me(2):&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;(reduce #(if (= %2 1) (inc %1) %1) 0 [1 2 3 2 3 1])&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Me(3)&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;(count (nth (partition-by identity (sort [ 1 2 3 1 2 3])) 0))&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;mrBliss(2):&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;(count (remove (complement #{1}) '(1 2 3 1 2 3))) ; But don't ever do this&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;_ato(1):&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;((fn f [[x &amp;amp; xs :as coll]] (cond (= coll '(1)) 1, (nil? xs) 0, :else (apply + (map #(f (take-nth 2 %)) [coll xs])))) [1 2 3 4 5 1 5 2])&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;_ato(2):&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;(let [s (sort [1 2 3 4 5 1 5 2])] (- (.lastIndexOf s 1) (.indexOf s 1) -1))&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;But at least Clojure has an awesome and helpful community!&lt;/p&gt;
</content>
		
	</entry>
	
	<entry>
		<title>The Perfect Server</title>
		<link href="http://pepijndevos.nl/the-perfect-server/index.html"/>
		<updated>2010-12-11T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/the-perfect-server/the-perfect-server</id>
		<content type="html">&lt;p&gt;I want a server that...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is fast.&lt;/li&gt;
&lt;li&gt;Easy to setup and maintain.&lt;/li&gt;
&lt;li&gt;Fixable(at runtime, which every dynamic language promotes itself with)&lt;/li&gt;
&lt;li&gt;Serves everything I throw at it      
&lt;ul&gt;
&lt;li&gt;PHP&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Clojure&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Serving everything poses a bit of a problem here.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/hosting-venn.png&quot; alt=&quot;The Perfect Server&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Tomcat proxy'd behind Apache&lt;/h2&gt;
&lt;p&gt;This is by far the most common setup I believe. But now I have two servers to configure, run and maintain!&lt;/p&gt;
&lt;h2&gt;Java implementations of everything&lt;/h2&gt;
&lt;p&gt;I believe both Quercus and Jython run all major frameworks in their languages, and run at reasonable speeds. I still fear it'll be a constant fight for the alternative route though. Consider porting all of the mod_rewrite rules Wordpress uses to servlet rules. Eew!&lt;/p&gt;
&lt;h2&gt;Standard implementations under JFastCGI&lt;/h2&gt;
&lt;p&gt;Close, but much of the same problems as the previous one. Native Python and PHP libs are a big win though.&lt;/p&gt;
&lt;blockquote class=&quot;posterous_short_quote&quot;&gt;&quot;Wouldn't it be dreamy if there was a server that would be a breeze to setup, that runs all languages I use, but without the limitations involved with running PHP and Python in a servlet&quot;&lt;/blockquote&gt;
&lt;p&gt;- Dreamy girl from Head First books.&lt;/p&gt;
&lt;p&gt;mod_ring would be dreamy for one, running Clojure's HTTP API under Apache. But after a quick trip to Google and mod_wsgi, I gave up this idea. Doesn't exist; to complicated to write.&lt;/p&gt;
&lt;p&gt;Ring is a nice idea though. I wonder if I can wrap JFastCGI in a nice Ring sauce.&lt;/p&gt;
&lt;h2&gt;Yes we can!&lt;/h2&gt;
&lt;p&gt;Another trip to Google and SourceForge reveals that&amp;nbsp;FastCGIHandler takes adapters for the Servlet and Portlet API. So it would suffice to write an adapter for Ring, and I would be able to use Django and Wordpress in a nice Moustache wrapper.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/pepijndevos/fastcgi-ring&quot;&gt;https://github.com/pepijndevos/fastcgi-ring&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So, dit I meet my original goals?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is fast - Somewhat, see below.&lt;/li&gt;
&lt;li&gt;Easy to setup and maintain - yes, it's all Clojure and Leiningen/Cake.&lt;/li&gt;
&lt;li&gt;Fixable - yes, nREPL might come in handy here.&lt;/li&gt;
&lt;li&gt;Serves everything I throw at it - yes sir!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I ran a basic `ab -n 1000 -c 50` on both Apache and Aleph running fastcgi-ring, with an identical installation of Wordpress. Both utilize 100% of my CPU, where Apache spawns tens of workers, and php-cgi a predefined set of 4 workers. Apache is a bit faster, with the gap increasing when I just test &quot;hello world&quot;. I did not test the speed of other combinations like Tomcat+JFastCGI or Lighttpd.&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
$ ab -n 1000 -c 50 http://localhost:3000/index.php
This is ApacheBench, Version 2.3 &lt;$Revision: 655654 $&gt;
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:        aleph
Server Hostname:        localhost
Server Port:            3000

Document Path:          /index.php
Document Length:        8353 bytes

Concurrency Level:      50
Time taken for tests:   119.077 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      8558000 bytes
HTML transferred:       8353000 bytes
Requests per second:    8.40 [#/sec] (mean)
Time per request:       5953.868 [ms] (mean)
Time per request:       119.077 [ms] (mean, across all concurrent requests)
Transfer rate:          70.18 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.3      0       5
Processing:   337 5809 2453.4   5782   12297
Waiting:      336 5808 2453.4   5782   12296
Total:        338 5809 2453.3   5782   12297

Percentage of the requests served within a certain time (ms)
  50%   5782
  66%   6832
  75%   7467
  80%   7899
  90%   9152
  95%  10033
  98%  10848
  99%  11370
 100%  12297 (longest request)

$ ab -n 1000 -c 50 http://localhost/~pepijndevos/wp/
This is ApacheBench, Version 2.3 &lt;$Revision: 655654 $&gt;
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:        Apache/2.2.15
Server Hostname:        localhost
Server Port:            80

Document Path:          /~pepijndevos/wp/
Document Length:        8353 bytes

Concurrency Level:      50
Time taken for tests:   99.862 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      8626000 bytes
HTML transferred:       8353000 bytes
Requests per second:    10.01 [#/sec] (mean)
Time per request:       4993.091 [ms] (mean)
Time per request:       99.862 [ms] (mean, across all concurrent requests)
Transfer rate:          84.35 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.8      0      10
Processing:   880 4971 1019.3   4896    9849
Waiting:      865 4953 1019.1   4881    9833
Total:        884 4972 1019.2   4897    9849

Percentage of the requests served within a certain time (ms)
  50%   4897
  66%   5053
  75%   5144
  80%   5212
  90%   5657
  95%   6543
  98%   8279
  99%   8864
 100%   9849 (longest request)
&lt;/pre&gt;&lt;/p&gt;
</content>
		
		<category term="clojure" />
		
		<category term="fastcgi" />
		
		<category term="php" />
		
		<category term="python" />
		
		<category term="ring" />
		
		<category term="server" />
		
	</entry>
	
	<entry>
		<title>Free premium Twitter marketing tool</title>
		<link href="http://pepijndevos.nl/free-premium-twitter-marketing-tool/index.html"/>
		<updated>2010-12-06T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/free-premium-twitter-marketing-tool/free-premium-twitter-marketing-tool</id>
		<content type="html">&lt;p&gt;A friend told me about someone who sells a Twitter product for marketeers for around &amp;euro;300. What this tool does is that it keeps track of hash tags you specify and mails tweets to you, so you can answer questions and get new followers.&lt;/p&gt;
&lt;p&gt;I was surprised to say the least. I frequently write these kind of things, but I find them to trivial to sell, I told my friend. To prove my point, I wrote this Python script - which I will give away for &lt;strong&gt;free&lt;/strong&gt; - that tracks keywords, makes a noise and opens tweets in a browser as it finds them.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;json&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;webbrowser&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;urllib2&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;urllib&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#http://dev.twitter.com/pages/streaming_api_methods#track&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;kwds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;#durftevragen photoshop&amp;quot;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Twitter username&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#Twitter password&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;pwd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;password_mgr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urllib2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HTTPPasswordMgrWithDefaultRealm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;top_level_url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;http://stream.twitter.com&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;password_mgr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;top_level_url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pwd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urllib2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HTTPBasicAuthHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;password_mgr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;opener&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urllib2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build_opener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opener&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;http://stream.twitter.com/1/statuses/filter.json?track=&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urllib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quote_plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;http://twitter.com/&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;user&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;screen_name&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;/status/&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;id_str&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\a&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;webbrowser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;div&gt;Now that I have given you worth &amp;euro;300 of Python code for free, I'd like to ask you a favor. I recently started my own company that is specialized in Wordpress blogs, Twitter tools and other web services and I'd like to know about the Twitter tool you've always wanted and what you'd pay for it.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;Some ideas of myself(and my friend):&lt;/div&gt;
&lt;div&gt;
&lt;ul class=&quot;MailOutline&quot;&gt;
&lt;li&gt;Extend my&amp;nbsp;&lt;a href=&quot;https://github.com/pepijndevos/Twemail&quot;&gt;Twitter email suit&lt;/a&gt;&amp;nbsp;with this tracking.&lt;/li&gt;
&lt;li&gt;Multiple keywords&lt;/li&gt;
&lt;li&gt;Organized in nice IMAP folders.&lt;/li&gt;
&lt;li&gt;Reply per email(No need to visit Twitter).&lt;/li&gt;
&lt;li&gt;Assemble a FAQ/knowledge base on your Wordpress blog.&lt;/li&gt;
&lt;li&gt;Tweet random facts from there.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content>
		
		<category term="free" />
		
		<category term="marketing" />
		
		<category term="python" />
		
		<category term="twemail" />
		
		<category term="twitter" />
		
		<category term="wordpress" />
		
	</entry>
	
	<entry>
		<title>The age of APIs ... and virtual ghost towns?</title>
		<link href="http://pepijndevos.nl/the-age-of-apis-and-virtual-ghost-towns/index.html"/>
		<updated>2010-12-02T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/the-age-of-apis-and-virtual-ghost-towns/the-age-of-apis-and-virtual-ghost-towns</id>
		<content type="html">Nowadays almost any self-respecting site seems to have an API. What can you do with all this data?&lt;p /&gt;&lt;div&gt;&lt;ul class=&quot;MailOutline&quot;&gt;&lt;li&gt;Clients&lt;/li&gt;&lt;li&gt;Analytics&lt;/li&gt;&lt;li&gt;Aggregation&lt;/li&gt;&lt;li&gt;And... a clone? &amp;nbsp;Sure!&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;I was thinking it'd be fun to do a Reddit clone, and experiment with different voting systems. Point is, there are quite a few of them, so how am I going to get users? Answer: I don't need users!&lt;/div&gt;&lt;p /&gt;&lt;div&gt;I took&amp;nbsp;&lt;a href=&quot;http://pepijndevos.nl/crowd-sourced-news-with-clojure&quot;&gt;this&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href=&quot;http://www.bestinclass.dk/index.clj/2010/02/reddit-clone-in-10-minutes-and-91-lines-of-clojure.html&quot;&gt;this&lt;/a&gt;, and in a few hours(mostly spent updating the work of Lau), I had an&amp;nbsp;&lt;a href=&quot;https://github.com/pepijndevos/cloneit&quot;&gt;autonomous Reddit clone running of the Twitter API&lt;/a&gt;,&amp;nbsp;and I believe it to be possible to create a complete social network that runs without any user input.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;&lt;img src=&quot;/images/Screen_shot_2010-12-02_at_3.01.png&quot; alt=&quot;The age of APIs ... and virtual ghost towns?&quot; /&gt;&lt;/div&gt;
</content>
		
		<category term="api" />
		
		<category term="clojure" />
		
		<category term="reddit" />
		
		<category term="twitter" />
		
	</entry>
	
	<entry>
		<title>How much Clojure do you know?</title>
		<link href="http://pepijndevos.nl/how-much-clojure-do-you-know/index.html"/>
		<updated>2010-11-29T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/how-much-clojure-do-you-know/how-much-clojure-do-you-know</id>
		<content type="html">&lt;p&gt;&lt;img src=&quot;/images/Clojurmon.jpg&quot; alt=&quot;How much Clojure do you know?&quot; /&gt;&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;user=&amp;gt; (count (ns-publics 'clojure.core))
546&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;That are a lot of functions. Unless you wrote half of them I wager you don&amp;rsquo;t know them all. Don&amp;rsquo;t worry, neither do I. But it doesn&amp;rsquo;t hurt to learn some more. That is why I wrote a &lt;a href=&quot;https://github.com/pepijndevos/clojure-quiz&quot;&gt;Clojure quiz&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Simply do the standard stuff(make sure you have git and lein or cake)&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;git clone git://github.com/pepijndevos/clojure-quiz.git
cake deps
cake repl
(use 'clojure-quiz.core)&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Now you can play three types of quizzes.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;(doc-quiz) Find the correct doc string for the given function.&lt;/li&gt;
&lt;li&gt;(name-quiz-easy) Find the correct function for the given doc.&lt;/li&gt;
&lt;li&gt;(name-quiz) Same as above, but without multiple choice.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(name-quiz) is by far the hardest, and I generally score around 70% while I can usually get 100% on the others.&lt;/p&gt;
&lt;p&gt;You can tweak the quiz by using binding to set the namespace to use and the number of options to give:&lt;/p&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;(binding [target 'clojure.set number 5] (doc-quiz))&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Have fun!&lt;/p&gt;
</content>
		
		<category term="clojure" />
		
		<category term="quiz" />
		
	</entry>
	
	<entry>
		<title>Crowd sourced news with Clojure</title>
		<link href="http://pepijndevos.nl/crowd-sourced-news-with-clojure/index.html"/>
		<updated>2010-11-14T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/crowd-sourced-news-with-clojure/crowd-sourced-news-with-clojure</id>
		<content type="html">&lt;p&gt;This snippet gets tweets, filters their links, sorts, resolves and counts them in about 30 lines Clojure, showing off the power of its Java interoperability and concurrent data structures.&lt;/p&gt;
&lt;p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ns&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;news&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;:refer-clojure&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:exclude&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;:use&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;contrib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;:import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;io&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;BufferedReader&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;InputStreamReader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;net&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cred&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; username:password&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;json&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;con&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;openConnection&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;http://stream.twitter.com/1/statuses/sample.json&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;setRequestProperty&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;con&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Authorization&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Basic &amp;quot;&lt;/span&gt;
                                                          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;encode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sun&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;misc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BASE64Encoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;getBytes&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cred&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BufferedReader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;InputStreamReader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;getInputStream&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;con&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;urls&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;agent &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;resolve&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;memoize&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;try&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;con&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;doto &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;openConnection&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;setInstanceFollowRedirects&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
          &lt;span class=&quot;nv&quot;&gt;loc&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;getHeaderField&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;con&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Location&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;close&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;getInputStream&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;con&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;loc&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;loc&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;top&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;urls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;reduce &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;val &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;val &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
             &lt;span class=&quot;nv&quot;&gt;%1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;frequencies&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;@urls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;future&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;doseq &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tweet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;repeatedly&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;read-json&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;:urls&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;:entities&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tweet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))]&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;send-off &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;urls&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;conj&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;resolve &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;:url&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;And this is just the start. I want to see if I can use Aleph and ClojureQL to kickstart my own little news service with it.&lt;/p&gt;
</content>
		
		<category term="clojure" />
		
		<category term="twitter" />
		
	</entry>
	
	<entry>
		<title>Clojure versus Python</title>
		<link href="http://pepijndevos.nl/clojure-versus-python/index.html"/>
		<updated>2010-11-04T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/clojure-versus-python/clojure-versus-python</id>
		<content type="html">&lt;p&gt;or&lt;/p&gt;

&lt;h2&gt;Mian versus &lt;em&gt;Clo&lt;/em&gt;mian&lt;/h2&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;h2&gt;How Clojure sat in a corner converting and boxing while Python did the work&lt;/h2&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;h2&gt;A plot about Minecraft(pun intended)&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Update:&lt;/em&gt; The Clojure version is now a lot faster. Thanks to the people of the &lt;a href=&quot;http://groups.google.com/group/clojure/browse_thread/thread/3c759739c265d14d/073475ace2810b94&quot;&gt;Clojure mailing list&lt;/a&gt;. I also uploaded &lt;a href=&quot;http://dl.dropbox.com/u/10094764/World2.zip&quot;&gt;the map I used&lt;/a&gt; if you want to compare the results.&lt;/p&gt;

&lt;p&gt;Okay, back to business. During the writing of the &lt;a href=&quot;http://pepijndevos.nl/where-to-dig-in-minecraft&quot;&gt;original Python hack&lt;/a&gt; I had to do a few tricks I thought would be easy to do in Clojure. So I started to wonder how the Clojure code would look and how fast it&amp;rsquo;d be.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://posterous.com/getfile/files.posterous.com/temp-2010-11-04/dbcDxIueyxJgdpwGtxCnegzcJjBdhewoIFsquoJIDawAogrxzamyCFBqfAom/Screen_shot_2010-11-04_at_2.52.10_PM.png?content_part=JJqJnHHHqDvqAlIwHouH&quot; alt=&quot;plot&quot; /&gt;&lt;/p&gt;

&lt;p&gt;My original hack was kind of slow, but it&amp;rsquo;s &lt;a href=&quot;https://github.com/l0b0/mian&quot;&gt;greatly improved&lt;/a&gt; and now renders a whole map in under 10 seconds.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;4s for reading all files&lt;/li&gt;
&lt;li&gt;3s for calculating the graph&lt;/li&gt;
&lt;li&gt;8s total&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The code to read all the files:&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;paths = glob(join(world_dir, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*/*/*.dat&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;))

raw_blocks = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;kw&quot;&gt;for&lt;/span&gt; path &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt; paths:
    nbtfile = NBTFile(path, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;rb&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)

    raw_blocks += nbtfile[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Level&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;][&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Blocks&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;].value&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The code to calculate the graph:&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;layers = [raw_blocks[i::128] for i in xrange(127)]

counts = [[] for i in xrange(len(bt_hexes))]
for bt_index in range(len(bt_hexes)):
    bt_hex = bt_hexes[bt_index]
    for layer in layers:
        counts[bt_index].append(layer.count(bt_hex))&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Nice eh? Now the &lt;a href=&quot;https://github.com/pepijndevos/Clomian/&quot;&gt;Clojure version&lt;/a&gt;. Clojure doesn&amp;rsquo;t have a nice blob module, so I&amp;rsquo;ll spare you the code that gives me the data. Sufficient to say is that it also runs in about 4 seconds.&lt;/p&gt;

&lt;p&gt;My initial version for the calculating was short and sweet and looked like this:&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;defn&lt;/span&gt; freqs &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;blocks&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; blocks
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;partition&lt;/span&gt; &lt;span class=&quot;i&quot;&gt;128&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;vector&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;pmap&lt;/span&gt; frequencies&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Now, this is twice as fast as what I currently have, but it has a problem. While Python operates on bytes the whole time, these lines of Clojure operate on a sequence of objects. These objects are just a tad bigger than the bytes in a string, so keeping 99844096 of those in memory is impossible.&lt;/p&gt;

&lt;p&gt;So, either I had to find a way to make Clojure throw away all the objects it had already processed, or I had to make it use a more compact storage for them. I tried both, and ended up with a function to &lt;a href=&quot;https://github.com/pepijndevos/Clomian/blob/master/src/clomian.clj#L101&quot;&gt;concatenate Java arrays&lt;/a&gt;, but working with them is a real pain, so I made my function use them wrapped in Clojure goodness and made sure the Java GC threw them out as soon as I was done.&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;defn&lt;/span&gt; freqs &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;blocks&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; blocks
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;partition&lt;/span&gt; &lt;span class=&quot;i&quot;&gt;128&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;reduce&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;[&lt;/span&gt;counts col&lt;span class=&quot;of&quot;&gt;]&lt;/span&gt;
              &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;doall&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;#(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;assoc!&lt;/span&gt; %1 %2 &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;inc&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;get&lt;/span&gt; %1 %2 &lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt; counts col&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;repeatedly&lt;/span&gt; &lt;span class=&quot;i&quot;&gt;128&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;#(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;transient&lt;/span&gt; &lt;span class=&quot;of&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;of&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;r&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;persistent!&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;of&quot;&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;This is not threaded like to previous example, but it works. Everything I tried to make it use all my cores either started to eat more and more memory, or was slower then the single-treaded one. Most of them where both.&lt;/p&gt;

&lt;p&gt;So, how fast is it?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;5s file reading&lt;/li&gt;
&lt;li&gt;Over a minute of processing&lt;/li&gt;
&lt;li&gt;Over a minute + 5s total&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Wait, what? Python did this in 3 seconds, right? Yea&amp;hellip; So even if I had used the faster function and had 10GB of RAM it&amp;rsquo;d be 10 times slower.&lt;/p&gt;

&lt;p&gt;Why? I don&amp;rsquo;t know. All I can come up with is that that Python just acts on a string, while Clojure does boxing and converting 99844096 times. If you happen to know what&amp;rsquo;s wrong, or how to make it faster, be sure to tell me!&lt;/p&gt;
</content>
		
		<category term="clojure" />
		
		<category term="minecraft" />
		
		<category term="python" />
		
	</entry>
	
	<entry>
		<title>Where to dig in The Nether</title>
		<link href="http://pepijndevos.nl/where-to-dig-in-the-nehter/index.html"/>
		<updated>2010-11-02T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/where-to-dig-in-the-nehter/where-to-dig-in-the-nehter</id>
		<content type="html">&lt;p&gt;Spoiler: Don't&lt;/p&gt;
&lt;div&gt;You remember my&amp;nbsp;&lt;a href=&quot;http://pepijndevos.nl/where-to-dig-in-minecraft&quot;&gt;other Minecraft post&lt;/a&gt;? A lot happened since then.&amp;nbsp;Victor Engmark took my hack and&amp;nbsp;&lt;a href=&quot;http://github.com/l0b0/mian&quot;&gt;made a nice tool out of it&lt;/a&gt;&amp;nbsp;that runs way faster as well! Notch released the&amp;nbsp;&lt;a href=&quot;http://minecraft.net/boo/&quot;&gt;Halloween update&lt;/a&gt;&amp;nbsp;with a new world that is at the moment called The Nether. And last but not least, I ported Mian to Clojure to form&amp;nbsp;&lt;a href=&quot;http://github.com/pepijndevos/Clomian&quot;&gt;Clomian&lt;/a&gt;, to compare it to the Python version and to analyze The Nether.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;There are still some issues with the code, and I might actually have found my first bug that is actually in Clojure and not in my code. Therefore I will talk and compare in another post, and for now just show you the results.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;The bug:&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;reduce &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partition&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;e6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;StackOverflowError&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;reduce &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pmap&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partition&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;e6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;99999500000&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;99999700000&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;99999900000&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100000100000&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100000300000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;The graphs:&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;&lt;img src=&quot;/images/graph.png&quot; alt=&quot;Where to dig in The Nether&quot; /&gt;&lt;img src=&quot;/images/graph-low.png&quot; alt=&quot;Where to dig in The Nether&quot; /&gt;&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;As you can see The Nether is an unfriendly place with nothing but Bloodstone, Lava, Fire and Mushrooms.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;Unlike the normal world, The Nether is 100% enclosed by Bedrock and in the middle, half of everything is still Bloodstone.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;Unlike the normal world, there aren't any minerals and there isn't a clear distinction between above and below.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;The only valuables I see are mushrooms and Lightstone, and these are somewhat uncommon and scattered across the whole level.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt;&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;The Nether is an interesting world, but it's not worth getting killed for, unless you desperately need any of those special blocks or shrooms.&lt;/div&gt;
</content>
		
		<category term="clojure" />
		
		<category term="minecraft" />
		
		<category term="thenether" />
		
	</entry>
	
	<entry>
		<title>How to be a good programmer</title>
		<link href="http://pepijndevos.nl/how-to-be-a-good-programmer/index.html"/>
		<updated>2010-10-14T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/how-to-be-a-good-programmer/how-to-be-a-good-programmer</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;http://xkcd.com/303/&quot;&gt;Get back to work.&lt;/a&gt;&lt;/p&gt;
</content>
		
	</entry>
	
	<entry>
		<title>Where to dig in Minecraft</title>
		<link href="http://pepijndevos.nl/where-to-dig-in-minecraft/index.html"/>
		<updated>2010-10-10T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/where-to-dig-in-minecraft/where-to-dig-in-minecraft</id>
		<content type="html">&lt;p&gt;I have been playing&amp;nbsp;&lt;a href=&quot;http://minecraft.net/&quot;&gt;Minecraft&lt;/a&gt;&amp;nbsp;a lot lately, and I was wondering where to dig for certain minerals. I knew Redstone was only found in lower layers of the level, but I knew nothing concrete.&lt;/p&gt;
&lt;p /&gt;
&lt;div&gt;I pulled together&amp;nbsp;&lt;a href=&quot;http://gnuplot-py.sourceforge.net/&quot;&gt;Gnuplot&lt;/a&gt;&amp;nbsp;and a&amp;nbsp;&lt;a href=&quot;http://github.com/twoolie/NBT&quot;&gt;Python lib&lt;/a&gt;&amp;nbsp;for reading&amp;nbsp;&lt;a href=&quot;http://www.minecraft.net/docs/NBT.txt&quot;&gt;NBT&lt;/a&gt;&amp;nbsp;files and analyzed a level. Here is the result, the code and some notes.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;&lt;img src=&quot;/images/minecraft.png&quot; alt=&quot;Where to dig in Minecraft&quot; /&gt;&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;I suspect the sea level is around 60, because of the clay there. &lt;strong&gt;Coals is rare and Iron &lt;/strong&gt;&lt;em&gt;&lt;strong&gt;very&lt;/strong&gt;&lt;/em&gt;&lt;strong&gt; rare above sea level.&lt;/strong&gt;&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;Both Diamond and Redstone stop at 20, while gold can be found a little higher. There is no noticeable decline in Coal and Iron near the bottom, &lt;strong&gt;so best is to dig below level 20&lt;/strong&gt;.&lt;/div&gt;
&lt;div&gt;&lt;img src=&quot;/images/danger.png&quot; alt=&quot;Where to dig in Minecraft&quot; /&gt;As can be seen above, there is a lot of Lava, Water and Obsidian around and below level 10, &lt;strong&gt;so stay above level 10 for safe mining.&lt;/strong&gt;&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;The code:&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;nbt&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nbt&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;itertools&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;izip_longest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;repeat&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;glob&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Gnuplot&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;files&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;glob&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/Users/pepijndevos/Library/Application Support/minecraft/saves/World2/*/*/*.dat&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;minecraft.png&amp;quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;col&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nbt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NBTFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;rb&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;izip_longest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;iter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Level&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Blocks&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

    &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;layers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;minerals&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;#&amp;#39;Bedrock&amp;#39;: &amp;#39;\x07&amp;#39;,&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;#&amp;#39;Water&amp;#39;: &amp;#39;\x09&amp;#39;,&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;#&amp;#39;Lava&amp;#39;: &amp;#39;\x0B&amp;#39;,&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;#&amp;#39;Sand&amp;#39;: &amp;#39;\x0C&amp;#39;,&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;#&amp;#39;Gravel&amp;#39;: &amp;#39;\x0D&amp;#39;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;#39;Gold&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x0E&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;#39;Iron&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x0F&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;#39;Coal&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x10&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;#39;Obsedian&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x31&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;#39;Diamond&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x38&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;#39;Redstone&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x49&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;#39;Clay&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x52&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;names&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minerals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;hexes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minerals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;count_minerals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;filter_mineral&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mineral&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;layer&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mineral&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filter_mineral&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hexes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Gnuplot&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Gnuplot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;set term png&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;set out &amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;set style data lines&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count_minerals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;layer&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Gnuplot&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PlotItems&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mineral&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mineral&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;I regret doing this thing in Python. My coding style is strongly influenced by Clojure, and I had to do a number of hacks that would be trivial to do in Clojure. I might do a comparison in a future post if I ever do a Clojure version.&lt;/div&gt;
</content>
		
		<category term="gnuplot" />
		
		<category term="minecraft" />
		
		<category term="python" />
		
	</entry>
	
	<entry>
		<title>How reify works, and how to write a custom type</title>
		<link href="http://pepijndevos.nl/how-reify-works-and-how-to-write-a-custom-typ/index.html"/>
		<updated>2010-09-25T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/how-reify-works-and-how-to-write-a-custom-typ/how-reify-works-and-how-to-write-a-custom-typ</id>
		<content type="html">&lt;p&gt;Yesterday I had the idea of lazy sequences that can go in both directions. I dropped into #clojure on &lt;a href=&quot;http://irc.freenode.net&quot;&gt;irc.freenode.net&lt;/a&gt; to ask someone about it.&lt;/p&gt;
&lt;div&gt;
&lt;blockquote class=&quot;posterous_medium_quote&quot;&gt;Given the fact that Clojure-in-Clojure is possible, it is thus possible to define lazy seqs. Would it also be possible to define a lazy seq where the 0th element is actually in the middle of an infinite lazy seq extending in both ways? so like (iterate inc) with negative number included :)&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div&gt;I found Chris Houser(Author of&amp;nbsp;&lt;a href=&quot;http://joyofclojure.com/&quot;&gt;Joy of Clojure&lt;/a&gt;) interested, and willing to help me along.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;
&lt;blockquote class=&quot;posterous_short_quote&quot;&gt;so... how shall we proceed? You want to see my code or should I try to drop hints or ask leading questions?&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div&gt;I went for the later one, and had a great learning experience. Near then end Paul deGrandis chimed in to recommend Joy of Clojure. I'm convinced!&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;
&lt;blockquote&gt;
&lt;div&gt;Joy of Clojure has an awesome section on proxy, reify, defprotocol, and defrecord. I reference it often to judge if I'm abusing something&lt;/div&gt;
&lt;div&gt;At the point you're at in Clojure (based on what I follow in here), you'd get a lot of mileage out of it.&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;Bellow You'll find a grep'd-over version of the log with most of the background noise canceled. The full log is at&amp;nbsp;&lt;a href=&quot;http://clojure-log.n01se.net/date/2010-09-24.html&quot;&gt;http://clojure-log.n01se.net/date/2010-09-24.html&lt;/a&gt;&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;The final code for my version&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ns&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;biseq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;defprotocol&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Spinnable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;biseq&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;start&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fwd&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;bwd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reify&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ISeq&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;biseq&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fwd&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fwd&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;bwd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;more&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;Spinnable&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;biseq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;start&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;bwd&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fwd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extend-type&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LazySeq&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;Spinnable&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;seq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;seq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;biseq&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;inc&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;take &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;take &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;take &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
                       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lazy-seq&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cons&lt;/span&gt;
                                   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                                   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rest &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;zero? &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rem &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                                              &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                                              &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))))&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;(0  1  2  3  4  5  6  7  8  9)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;(0 -1 -2 -3 -4 -5 -6 -7 -8 -9)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;(0 -1 -2 -3 -4 -5 -4 -3 -2 -1 0 -1 -2 -3 -4 -5 -4 -3 -2 -1)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;and chousers version&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;defprotocol&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Spinnable&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Return a seq walking the opposite direction as this&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;iter-bi&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reify&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;Spinnable&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;iter-bi&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ISeq&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;more&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;iter-bi&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rest &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;; same as rest since all iter-bi&amp;#39;s are infinite seqs&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;equiv&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;; cheater!&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extend-type&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LazySeq&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;Spinnable&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;iter-bi&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;inc&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;drop &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;nv&quot;&gt;spin&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;take &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;=&amp;gt; (5 4 3 2 1 0 -1 -2 -3 -4)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;
&lt;blockquote&gt;
&lt;div&gt;&lt;strong&gt;fliebel: Given the fact that Clojure-in-Clojure is possible, it is thus possible to define lazy seqs. Would it also be possible to define a lazy seq where the 0th element is actually in the middle of an infinite lazy seq extending in both ways? so like (iterate inc) with negative number included :)&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;chouser: ISeq only provides an API for walking forwards. You'd need a different interface for walking the other direction.&lt;/div&gt;
&lt;div&gt;fliebel: Hrm :( that means I'll be unable to use with with existing functions, right?&lt;/div&gt;
&lt;div&gt;chouser: well, what existing function do you intend to call to get item before 'first'?&lt;/div&gt;
&lt;div&gt;fliebel: Dunno&amp;sbquo; I mean, if I'm not using ISeq, I can&amp;rsquo;t even use first, right?&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: well, your theoretical bidirectional lazy seq could implement ISeq for going forward&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: Oh wait, Java, so I can implement ISeq and add my own interface and fns for going the other way.&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;fliebel: How about this&amp;sbquo; you define a lazy seq like iterate but with 2 fns, for going in either direction. then you call spin on it to change which direction you're seqing over :)&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;chouser: hm, interesting.&lt;/div&gt;
&lt;div&gt;fliebel: So, what Clojure bits do I need to implement that?&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: a deftype and ... a function?&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: *looks up deftype*&lt;/div&gt;
&lt;div&gt;chouser: actually, just a deftype would do, though it's not quite as pretty.&lt;/div&gt;
&lt;div&gt;fliebel: I don't think I get it.&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: (rseq (rest (drop 10 (IterBi. 0 inc dec)))) ;=&amp;gt; (5 4 3 2 1 0 -1 -2 -3 -4 -5 ...)&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: so that's what you wanted, right? interesting idea.&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: I understand how I can do without the fn, but I don't understand deftype.&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: actually, you don't need deftype either. you could use reify or proxy if you prefer, and a normal function.&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: I never worked with those 1.2 things before. So it's going to be a lot of learning :)&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: so... how shall we proceed? You want to see my code or should I try to drop hints or ask leading questions?&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;fliebel: the later one :) extended with my guessing and reading&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: So I basically need to look up the ISeq interface and overwrite a few methods?&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: ok, so how would you use deftype or reify to implement an ISeq that just repeats the same value over and over&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: Where can I find the ISeq interface?&lt;/div&gt;
&lt;div&gt;chouser: &lt;a href=&quot;http://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/ISeq.java&quot;&gt;http://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/ISeq.java&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;fliebel: I guess it'd be (reify clojure.lang.ISeq (first [this] 1)) but that fails&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: Do I need to implement all of them? Or can I just use a concrete subclass of ISeq?&lt;/div&gt;
&lt;div&gt;chouser: just implement the ones you need for now. What happens when you call 'first' on your reify there?&lt;/div&gt;
&lt;div&gt;fliebel: I get java.lang.AbstractMethodError when defining it, because ISeq is an abstract interface.&lt;/div&gt;
&lt;div&gt;chouser: are you sure that's why?&lt;/div&gt;
&lt;div&gt;fliebel: Hm, first works, but just defining it fails.&lt;/div&gt;
&lt;div&gt;chouser: Ah, repl evaluates&lt;/div&gt;
&lt;div&gt;chouser: yep, and after E is P&lt;/div&gt;
&lt;div&gt;fliebel: ?&lt;/div&gt;
&lt;div&gt;chouser: REPL&lt;/div&gt;
&lt;div&gt;fliebel: ah&lt;/div&gt;
&lt;div&gt;chouser: and printing a seq means walking it an printing each of the items. we're not ready for that.&lt;/div&gt;
&lt;div&gt;fliebel: I see&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: so, (first ...) works. what about (next ...)?&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: let me try..&lt;/div&gt;
&lt;div&gt;fliebel: What about more and cons?&lt;/div&gt;
&lt;div&gt;chouser: ignore them for now.&lt;/div&gt;
&lt;div&gt;fliebel: yea, but not doing second on it still gives me the error.&lt;/div&gt;
&lt;div&gt;chouser: it's a shame it doesn't tell you the specific method it's trying to call that fails.&lt;/div&gt;
&lt;div&gt;fliebel: It doesn't even give a line or file.&lt;/div&gt;
&lt;div&gt;chouser: right, so use (.printStackTrace *e)&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;fliebel: But seq isn't in ISeq, or is that up in Seqable?&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: Yea, but you can put it under ISeq in your reify&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: I know, but I need to know it&amp;rsquo;s interface.&lt;/div&gt;
&lt;div&gt;chouser: &lt;a href=&quot;http://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Seqable.java#L16&quot;&gt;http://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Seqable.java#L16&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;fliebel: right&amp;sbquo; Now I made it return a list. It prints that and *then* gives the same error.&lt;/div&gt;
&lt;div&gt;chouser: yeah. so that final error is it calling equiv. not sure why&lt;/div&gt;
&lt;div&gt;fliebel: hm, Do we need to fix that?&lt;/div&gt;
&lt;div&gt;chouser: probably not&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;fliebel: (reify clojure.lang.ISeq (first [this] 1) (next [this] this) (seq [this] (list 1 2 3)))&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: do you have an ISeq handy already for your 'seq' to return?&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;fliebel: this?&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;chouser: what happens when you try it?&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;fliebel: I guess it'll print a lot of 1s&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: okay, it does :)&lt;/div&gt;
&lt;div&gt;chouser: good job!&lt;/div&gt;
&lt;div&gt;fliebel: but take 10 doesn't work yet&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: take is calling your (unimplemented) rest method&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;fliebel: I keep forgetting the difference between next and rest. There aren&amp;rsquo;t any docstrings on ISeq :(&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: the difference between more (called by clojure.core/rest) and next only matters when being very careful about nearly vs. complete laziness.&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;ohpauleez: new rest is almost always what you want, except when you don't&lt;/div&gt;
&lt;div&gt;chouser: that is, we don't really care much. So what happens if your 'more' is the same as your 'next'?&lt;/div&gt;
&lt;div&gt;fliebel: Works :)&lt;/div&gt;
&lt;div&gt;chouser: congrats!&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;fliebel: I know how to reverse it :D&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;chouser: :-P&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: ok, but you want to apply a function instead of just repeating, right? how would you do that?&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: Hey, my ISeq doesn't implement clojure.lang.Reversible&lt;/div&gt;
&lt;div&gt;chouser: hm, what are going to do about that?&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;fliebel: I don't think reify allows me to define multiple ancestors :(&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;fliebel: I would not have led you astray&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: Can I nest reifies? :P&lt;/div&gt;
&lt;div&gt;chouser: yes, but that's not what you want here.&lt;/div&gt;
&lt;div&gt;fliebel: Nope :(&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: according to the deftype docs, &quot;Each spec consists of...&quot;?&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: ah...&lt;/div&gt;
&lt;div&gt;fliebel: I added clojure.lang.Reversible (rev [this] this)&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;fliebel: (. rev (rseq)) what is this?&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: ancient syntax. the same as (.rseq rev)&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: lol&lt;/div&gt;
&lt;div&gt;fliebel: Can we go somewhat more down the inheritance tree to find something that covers the basics? Or do we need everything customized anyway?&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: reify doesn't let you inherit from anything but pure interfaces.&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: So what is next?&lt;/div&gt;
&lt;div&gt;fliebel: I'm now struggling with where to keep state and how to modify things without an endless recursion.&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: yep. hint: fn args are state&lt;/strong&gt;&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;== diner &amp;amp; work pause ==&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;fliebel: sure :) I nearly got it working :)&lt;/div&gt;
&lt;div&gt;chouser: ok, back. That's great. what have you got?&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;fliebel: 
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ns&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;biseq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;defprotocol&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Spinnable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;biseq&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;start&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fwd&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;bwd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reify&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ISeq&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;biseq&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fwd&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fwd&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;bwd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;more&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;Spinnable&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;biseq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;start&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;bwd&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fwd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extend-type&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LazySeq&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;Spinnable&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;seq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;seq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;biseq&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;inc&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;take &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;take &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;take &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
                       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lazy-seq&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cons&lt;/span&gt;
                                   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                                   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rest &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;zero? &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rem &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                                              &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                                              &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))))&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;(0  1  2  3  4  5  6  7  8  9)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;(0 -1 -2 -3 -4 -5 -6 -7 -8 -9)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;(0 -1 -2 -3 -4 -5 -4 -3 -2 -1 0 -1 -2 -3 -4 -5 -4 -3 -2 -1)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;chouser: nice!&lt;/div&gt;
&lt;div&gt;fliebel: thanks :) You're a good teacher :)&lt;/div&gt;
&lt;div&gt;chouser: I think that's the same as what I have. but you said &quot;nearly&quot;?&lt;/div&gt;
&lt;div&gt;fliebel: The problem I had was that first was defined as the first of this, but I couldn't do (first this) of course.&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: if you want to &quot;check&quot; your answer: 
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;defprotocol&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Spinnable&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Return a seq walking the opposite direction as this&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;iter-bi&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reify&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;Spinnable&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;iter-bi&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ISeq&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;more&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;iter-bi&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rest &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;; same as rest since all iter-bi&amp;#39;s are infinite seqs&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;equiv&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;; cheater!&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extend-type&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LazySeq&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;Spinnable&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;iter-bi&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;inc&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;drop &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;nv&quot;&gt;spin&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;take &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;=&amp;gt; (5 4 3 2 1 0 -1 -2 -3 -4)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: this is your version?&lt;/div&gt;
&lt;div&gt;chouser: yep&lt;/div&gt;
&lt;div&gt;fliebel: very close :) Only you have equiv defined and next uses more. Does it matter if you use (.more method call) or rest?&lt;/div&gt;
&lt;div&gt;chouser: not really. yours is probably faster&lt;/div&gt;
&lt;div&gt;but duplicates half a line of code. :-)&lt;/div&gt;
&lt;div&gt;fliebel: yea... :(&lt;/div&gt;
&lt;div&gt;chouser: so take your pick. what you've got is good.&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;fliebel: One problem I have is that drop 5 returns a lazy seq which I can't reverse&lt;/strong&gt;.&lt;/div&gt;
&lt;div&gt;chouser: yeah, you see how I work around that in my example?&lt;/div&gt;
&lt;div&gt;fliebel: rest, I used seq to do the job&lt;/div&gt;
&lt;div&gt;chouser: oh! smart!&lt;/div&gt;
&lt;div&gt;chouser: interesting -- I hadn't considered that, and wouldn't have been sure it would work. nicely done.&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;fliebel: I wasn&amp;rsquo;t sure it would work, but seq is magic you know..&lt;/strong&gt;.&lt;/div&gt;
&lt;div&gt;fliebel: One thing I haven't figured out yet is how to make a seq that goes 1 2 3 4 5 4 3 2 1, so changes direction in the middle.&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: ((fn f [s] (lazy-seq (cons (first s) (f (rest (if (zero? (rem (first s) 5)) (rseq (seq s)) s)))))) (iter-bi 1 inc dec))&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: I'm going to try and understand :)&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: BTW, I wanted to call attention to my comment on rseq. I think we're abusing it here and probably ought to define a new protocol instead. (defprotocol Spinnable (spin [_])) or something.&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: Okay. that simple?&lt;/div&gt;
&lt;div&gt;chouser: yep&lt;/div&gt;
&lt;div&gt;fliebel: So now in reify I replace reversible with spinnable?&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: there, now you don't have to call seq manually on lazy-seqs: 
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;defprotocol&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Spinnable&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Return a seq walking the opposite direction as this&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;iter-bi&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reify&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;Spinnable&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;iter-bi&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ISeq&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;more&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;iter-bi&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rest &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;; same as rest since all iter-bi&amp;#39;s are infinite seqs&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;equiv&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;; cheater!&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extend-type&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LazySeq&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;Spinnable&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;spin&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;iter-bi&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;inc&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;drop &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;nv&quot;&gt;spin&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;take &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;=&amp;gt; (5 4 3 2 1 0 -1 -2 -3 -4)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: What? You can just add behavior to existing types? Am I in #ruby?&lt;/div&gt;
&lt;div&gt;chouser: nope. in clojure we do it without monkey patching or adapter classes. :-)&lt;/div&gt;
&lt;div&gt;chouser: I mean &quot;nope&quot; you're not in #ruby. Of course you can write new functions that take existing classes as args that then do their own thing with them.&lt;/div&gt;
&lt;div&gt;fliebel: But you just added extra behavior to LazySeq, right?&lt;/div&gt;
&lt;div&gt;dnolen: it's a properly namespaced extension tho. It's not visible to other namespaces.&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: it certainly looks like I did. In this case we could have written spin like: (defn spin [x] (if (instance? LazySeq x) ...))) right?&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: I think so...&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: it's our function, we just defined it with defprotocol which allows us to add new cases on the fly&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: yay&lt;/div&gt;
&lt;div&gt;chouser: essentially. Except then rhickey sprinkled it with magic dust to make it very fast.&lt;/div&gt;
&lt;div&gt;fliebel: :)&lt;/div&gt;
&lt;div&gt;chouser: it's good to know not everyone knows about this yet -- it's my topic at Strange Loop&lt;/div&gt;
&lt;div&gt;fliebel: oh, I feel special now :)&lt;/div&gt;
&lt;div&gt;chouser: good I'm glad! But... why?&lt;/div&gt;
&lt;div&gt;fliebel: Because I know something not everyone knows ;)&lt;/div&gt;
&lt;div&gt;chouser: ah, good!&lt;/div&gt;
&lt;div&gt;fliebel: Except that I'm not o sure yet what exactly you just said. Only that it's magic and fast. Two things I like especially.&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;chouser: Here are the basics: &lt;a href=&quot;http://clojure.org/datatypes&quot;&gt;http://clojure.org/datatypes&lt;/a&gt;&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: I tried to read that this morning, but maybe with my new knowledge I can understand it.&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;ohpauleez: Joy of Clojure has an awesome section on proxy, reify, defprotocol, and defrecord. I reference it often to judge if I'm abusing something&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;chouser: thanks. didn't want to say it myself. :-)&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;ohpauleez: At the point you're at in Clojure (based on what I follow in here), you'd get a lot of mileage out of it.&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;ohpauleez: and the biggest problem I had in clojure was deciding, &quot;when&quot;&lt;/div&gt;
&lt;div&gt;fliebel: &amp;ldquo;when&amp;rdquo;?&lt;/div&gt;
&lt;div&gt;ohpauleez: Joy of Clojure it helped me a lot with that&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;ohpauleez: In Clojure, you have this whole array of functionality. Take concurrency&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;we all have that little chart burned in our brains by now&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;we know vars and atoms and agents&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;but when should I be using promises over futures, or when am I abusing a future and should really be using an agent&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;when should I use protocols and not some other small hack&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;fliebel: right&amp;hellip; I have that problem a lot indeed&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;ohpauleez: Joy of Clojure is structured by answering when, and for me, that pulled it all together.&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;chouser: that's very encouraging, thanks.&lt;/div&gt;
&lt;div&gt;fliebel: wow, under 10 there is a whole set of &quot;when to use &amp;hellip; &quot;&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</content>
		
		<category term="clojure" />
		
		<category term="irc" />
		
		<category term="joyofclojure" />
		
		<category term="reify" />
		
	</entry>
	
	<entry>
		<title>Say thanks to the man who makes your computer run</title>
		<link href="http://pepijndevos.nl/intel-hda-driver/index.html"/>
		<updated>2010-09-20T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/intel-hda-driver/intel-hda-driver</id>
		<content type="html">&lt;p&gt;Today I was browsing HackerNews and reading up on the latest cool projects including at least 3 buzzword technologies, when I suddenly realized how strange it was to go &quot;ooh&quot; and &quot;aah&quot; for weekend projects written in fancy high-level languages while we are ignorant to the people who get their hand dirty to make it possible in the first place.&lt;/p&gt;
&lt;p&gt;That is when I decided to find the authors of my sound card driver and thank them for their amazing work. I run Ubuntu now and then on my iMac, but the sound never worked for me, until recent versions of Ubuntu shipped the correct ALSA driver.&lt;/p&gt;
&lt;p&gt;I encourage you to do the same.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to a technology you use to write awesome applications or the solution to a problem you had.&lt;/li&gt;
&lt;li&gt;Look for the dependencies, and continue to drill down until you find a project that makes you blink your eyes ands say &quot;wow, I didn't know this was involved.&quot;&lt;/li&gt;
&lt;li&gt;Thank the author. Really, I'm serious!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I had to find out which sound card I have, what the driver for that was, and finally who the authors are. It turns out It's the Intel HDA driver in the alsa-driver package. The source file contained their email addresses.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Did you know Node.js uses V8, which uses Scons, which uses Python, which uses readline, which uses ncurses, which are all compiled using GCC or LLVM?&lt;/li&gt;
&lt;li&gt;Did you know you can use your package manager to see the dependencies of a project?&lt;/li&gt;
&lt;li&gt;Did you realize your package manager installs hundreds of dependencies and dependencies of dependencies to run something like Python?&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Consider who is more awesome, the guy who writes a Twitter app in Node, the guy who made Node, or the guy who made Node possible.&lt;/li&gt;
&lt;/ul&gt;
</content>
		
		<category term="hn" />
		
		<category term="technology" />
		
		<category term="thanks" />
		
	</entry>
	
	<entry>
		<title>Twitter OAuth for Open Source clients</title>
		<link href="http://pepijndevos.nl/twitter-oauth-for-open-source-clients/index.html"/>
		<updated>2010-09-14T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/twitter-oauth-for-open-source-clients/twitter-oauth-for-open-source-clients</id>
		<content type="html">After reading&amp;nbsp;&lt;a href=&quot;http://blog.nelhage.com/2010/09/dear-twitter/&quot;&gt;these&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;http://arstechnica.com/security/guides/2010/09/twitter-a-case-study-on-how-to-do-oauth-wrong.ars&quot;&gt;two&lt;/a&gt;&amp;nbsp;articles about how to compromise Twitter tokens from a client and about how Twitter is abusing OAuth secrets and screwing OS clients by blocking their tokens, I came up with the following plan.&lt;p /&gt;&lt;div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;your key&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;secret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;your secret&amp;quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sign&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;twitter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verify_credentials&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;401&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;BigFish key&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;secret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;BigFish secret&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;p /&gt;&lt;div&gt;I really love Twitter and the Twitter API, but it is obvious by now that Twitter does not care about small OSS projects.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;I propose small Open Source Twitter clients to use tokens from the big fish as a fallback for their own tokens. This will allow small clients to continue to work after their tokens are blocked(albeit under the big fish name), unless Twitter blocks their own clients as well or faces the fact that their approach doesn't work.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;A more politically correct option would be to write an OAuth Echo service that stores your tokens in a secure place, and accepts request without a secret. Take your pick.&lt;/div&gt;&lt;p /&gt;&lt;/div&gt;
</content>
		
		<category term="oauth" />
		
		<category term="opensource" />
		
		<category term="twitter" />
		
	</entry>
	
	<entry>
		<title>5 minutes Lisp in Python</title>
		<link href="http://pepijndevos.nl/5-minutes-lisp-in-python/index.html"/>
		<updated>2010-09-10T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/5-minutes-lisp-in-python/5-minutes-lisp-in-python</id>
		<content type="html">I love both Python and Clojure, so after I read&amp;nbsp;&lt;a href=&quot;http://gist.github.com/562017&quot;&gt;this gist about a Lisp in Ruby&lt;/a&gt;, I decided to craft my own in Python.&lt;p /&gt;&lt;div&gt;The idea is basically to abuse a few Python functions, namely Generators, Decorators and grouping to have a syntax that looks like Lisp with yield at the start of every statement.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;It's all still Python, so you can mix and mach however you like, I sneaked a List Comprehension in the example, which fits the Lisp syntax quite well.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;At the moment of writing, the Gist below is also&amp;nbsp;&lt;a href=&quot;http://news.ycombinator.com/item?id=1678367&quot;&gt;#3 on HackerNews&lt;/a&gt;.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;c&quot;&gt;# 5 minutes Lisp in Python&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Pepijn de Vos &amp;lt;http://pepijndevos.nl&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Inspired by 30 minutes Lisp in Ruby&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# http://gist.github.com/562017&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# &lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# This Lisp does not read or parse anything at all.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# A generator and a Decorator are abused to run sexps.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Usage:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# &lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Define a function decorated with @lisp and start every sexp with yield.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# The function names should be strings.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Result is stored in fn name.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Example below:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;lisp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;newval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;getattr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__builtins__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:])&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;AttributeError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;newval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;getattr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:])&lt;/span&gt;

            &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;StopIteration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;getattr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:])&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@lisp&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;example&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;join&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;quot;, #&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;__mul__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;str&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;range&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;__add__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))],&lt;/span&gt;
      &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;example&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
		
		<category term="gist" />
		
		<category term="hn" />
		
		<category term="lisp" />
		
		<category term="python" />
		
	</entry>
	
	<entry>
		<title>Twitter in your inbox</title>
		<link href="http://pepijndevos.nl/twitter-in-your-inbox/index.html"/>
		<updated>2010-09-07T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/twitter-in-your-inbox/twitter-in-your-inbox</id>
		<content type="html">I have been working on this for quite a while, with initial plans to make it a service. But I have changed plans, and am releasing it to the world.&lt;p /&gt;&lt;div&gt;What have I been working on, you ask? Not that I like sliced bread, but it's at least as good as that: It solves some problems while it introduces some others. It's a proxy between Twitter and your email client that sits on your computer or a server translating mail-language(POP, SMTP) to Twtter-language(REST API).&lt;/div&gt;&lt;p /&gt;&lt;div&gt;This way you can read your tweets in your mail client, store them in folders, search though them, and do all the other stuff mail clients are good at. It even allows you to reply and forward(retweet in Twitter lingo) tweets.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;Here is how to get it. You go to my GitHub repo, which lives at the link below, and pull/download the code.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;&lt;a href=&quot;http://github.com/pepijndevos/Twemail&quot;&gt;http://github.com/pepijndevos/Twemail&lt;/a&gt;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;The next step is to get the dependencies, which include Twisted, OAuth2 and Twitter-Text-Python. You might try to use setup.py for that, but I'm not sure it works.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;Now you simply run &quot;twistd -ny twemail.tac&quot; in the Twemail directory. If everything went well you'll see some messages rolling by about starting services.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;Now all that remains is to configure your mail client with the following information&quot;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;&lt;ul class=&quot;MailOutline&quot;&gt;&lt;li&gt;email: &lt;a href=&quot;mailto:username@twitter.com&quot;&gt;username@twitter.com&lt;/a&gt;&lt;/li&gt;&lt;li&gt;password: your Twitter password&lt;/li&gt;&lt;li&gt;POP server: localhost on port 1100&lt;/li&gt;&lt;li&gt;SMTP server: localhost on port 2500&lt;/li&gt;&lt;/ul&gt;&lt;p /&gt;&lt;/div&gt;&lt;div&gt;Here is how it works.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;&lt;ul class=&quot;MailOutline&quot;&gt;&lt;li&gt;You can send messages by mailing &lt;a href=&quot;mailto:post@twitter.com&quot;&gt;post@twitter.com&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Replying is done by hitting reply and replacing the subject line.&lt;/li&gt;&lt;li&gt;Retweets are done by forwarding to the sender of the tweet&lt;/li&gt;&lt;/ul&gt;&lt;p /&gt;&lt;/div&gt;&lt;div&gt;In the future I also want to handle attachments and IMAP, but this is currently not included.&lt;/div&gt;
</content>
		
		<category term="email" />
		
		<category term="proxy" />
		
		<category term="python" />
		
		<category term="twisted" />
		
		<category term="twitter" />
		
	</entry>
	
	<entry>
		<title>Clojure Rock-Paper-Scissors using a Markov chain</title>
		<link href="http://pepijndevos.nl/clojure-rock-paper-scissors-using-a-markov-ch/index.html"/>
		<updated>2010-09-04T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/clojure-rock-paper-scissors-using-a-markov-ch/clojure-rock-paper-scissors-using-a-markov-ch</id>
		<content type="html">&lt;p&gt;A long time ago I saw a challenge on a Python forum about writing a Rock-Paper-Scissors bot that performs better than a random bot.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;As strange as it might seem,&amp;nbsp;Rock-Paper-Scissors is anything but random. As long as it's played by people, they'll always try to come up with a winning move. I've been told there are even championships with this game.&lt;/div&gt;
&lt;img src=&quot;/images/4138951764_374df4af63.jpeg&quot; alt=&quot;Clojure Rock-Paper-Scissors using a Markov chain&quot; /&gt;
&lt;div&gt;So while trying to improve my Clojure skills I came up with the idea of using a Markov chain to write a&amp;nbsp;Rock-Paper-Scissors bot.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;Markov chains - as I recently learnt - are a random process where every step is only based on the previous. I'm not a psychologist, but when I play&amp;nbsp;Rock-Paper-Scissors, I usually go like &quot;I just lost using paper, so lets try rock&quot; or &quot;I won using rock, lets do it again&quot;, so I think it suits the challenge.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;I use this map to define the probability of certain actions:&lt;/div&gt;
&lt;div&gt;{:won {:same 1, :inferior 0, :superior 0}, :lost {:same 0, :inferior 1, :superior 0}, :draw {:same 0, :inferior 0, :superior 1}}&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;So with this example data, If I used rock, and won. I'll choose rock again, now I lose, so I choose the item inferior to rock: scissors. Draw, so I'll choose the item superior to scissors: rock.&lt;/div&gt;
&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;The roulette function takes a map like&amp;nbsp;{:same 1, :inferior 2, :superior 4} and returns one of the keys with the probability of the value. Calling this 7 times should approximately return 4 times :superior, 2 times :inferior and :same only once.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;The guess function uses the Markov map to predict my action, and take the item that wins from mine.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;Then there is the check function, which just returns if I won or lost based on the 2 items, and the relation fn which does the same for determining which of the 2 items is better.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;Then there is the play function which focuses on getting your input, comparing results, and updating the Markov data to represent your actual actions.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;You should update the map with the map that is printed at the end of the game, to improve the learning process of my bot. If you collect a lot of data, it could be interesting to send it in, so I can improve my bot to have a proper data set to start with.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;Have fun!&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ns&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;markov-stone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;{:won {:same 0, :inferior 0, :superior 0}, :lost {:same 0, :inferior 0, :superior 0}, :draw {:same 0, :inferior 0, :superior 0}}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;roulette&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;slices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;slices&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sort-by &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;slices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;total&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;reduce &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;vals &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;slices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rand &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;cumulative&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;vector&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;keys &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;slices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reductions&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;vals &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;slices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;drop-while &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;last &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cumulative&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;guess&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;markov&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;prev&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;inferior&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:s&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:p,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:r,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:r&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;superior&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;clojure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;set/map-invert&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;inferior&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;pred&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;markov&lt;/span&gt;
                  &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;
                  &lt;span class=&quot;nv&quot;&gt;roulette&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pred&lt;/span&gt;
          &lt;span class=&quot;nv&quot;&gt;:same&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;superior&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;prev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;nv&quot;&gt;:superior&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;inferior&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;prev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;nv&quot;&gt;:inferior&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;prev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cpu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cpu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;:draw&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cpu&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:s&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:p,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:r,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:r&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}))&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;:lost&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;:won&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;relation&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;prev&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cur&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;prev&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cur&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;:same&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;prev&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cur&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:s&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:p,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:r,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:r&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}))&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;:superior&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;:inferior&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;play&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;markov&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;prev&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;score&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Choose your weapon[r/p/s]!&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;if-let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:r&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;keyword &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;read-line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;names&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:r&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;ROCK&amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:p&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;PAPER&amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:s&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;SCISSORS&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;nv&quot;&gt;cpu&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;guess&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;markov&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;prev&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;nv&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cpu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;nv&quot;&gt;score&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;result&lt;/span&gt;
                      &lt;span class=&quot;nv&quot;&gt;:won&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;inc &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;score&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                      &lt;span class=&quot;nv&quot;&gt;:lost&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dec &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;score&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                      &lt;span class=&quot;nv&quot;&gt;:draw&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;score&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;names&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cpu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Game is&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;- Score:&amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;score&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recur&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;update-in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;markov&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;relation&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;prev&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;inc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;score&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Invalid input; Final score:&amp;quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;score&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;markov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;play&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:won&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:same&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:inferior&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:superior&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:lost&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:same&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:inferior&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:superior&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;38&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:draw&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:same&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:inferior&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:superior&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;21&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:r&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;:draw&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
		
	</entry>
	
	<entry>
		<title>Restore the old iTunes icon</title>
		<link href="http://pepijndevos.nl/restore-the-old-itunes-icon/index.html"/>
		<updated>2010-09-02T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/restore-the-old-itunes-icon/restore-the-old-itunes-icon</id>
		<content type="html">&lt;p&gt;Since the last keynote, where Apple announced iTunes 10, I've heard a lot of complaints about the vertical close buttons and the new icons. &lt;p /&gt; For the close buttons you should keep an eye on &lt;a href=&quot;http://hints.macworld.com/&quot;&gt;http://hints.macworld.com/&lt;/a&gt;, but at least I solved the problem of the ugly icon. &lt;p /&gt; Before updating, save the old icon by right-clicking on iTunes, and then on &quot;Show package contents&quot;, then browse to Content/Resources and copy iTunes.icns somewhere safe. &lt;p /&gt; Now upgrade iTunes, and do the same thing in reverse, so you'll overwrite the new iTunes.icns. Below is a video and the original icon, in case you are to late to copy it yourself. You might need to start and stop iTunes a few times, or even reboot to se the &quot;new&quot; icon.&lt;/p&gt;
&lt;p&gt;[[posterous-content:xcKOWzC5uTfI2Lgl3rky]]&lt;/p&gt;
&lt;p&gt;[[posterous-content:nGbvjkjyCfDKW1Svw1lV]]&lt;/p&gt;
&lt;p&gt;[update] Posterous doesn't like my icon. Download it from Dropbox instead:&amp;nbsp;&lt;a href=&quot;http://dl.dropbox.com/u/10094764/iTunes.icns&quot;&gt;http://dl.dropbox.com/u/10094764/iTunes.icns&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Also, about the control buttons:&amp;nbsp;defaults write com.apple.iTunes full-window -1&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://hints.macworld.com/article.php?story=20100901223846748&quot;&gt;http://hints.macworld.com/article.php?story=20100901223846748&lt;/a&gt;&lt;/p&gt;
</content>
		
		<category term="icon" />
		
		<category term="itunes" />
		
		<category term="macosx" />
		
	</entry>
	
	<entry>
		<title>A smile for web standards</title>
		<link href="http://pepijndevos.nl/a-smile-for-web-standards/index.html"/>
		<updated>2010-09-01T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/a-smile-for-web-standards/a-smile-for-web-standards</id>
		<content type="html">&lt;p&gt;We all love web standards. While I was implementing a little easter egg(which are also very lovable) on&amp;nbsp;&lt;a href=&quot;http://coverontwerp.nl/&quot;&gt;http://coverontwerp.nl/&lt;/a&gt; with a good deal of CSS3 love, I thought it would be nice to turn as many clicks as possible into a smile for web standards, a mini ACID test if you will.&lt;/p&gt;
&lt;p&gt;Bellow you'll find a CSS snippet that, when included on your site, will flash a smile for every link clicked in a supporting browser. &amp;nbsp;It is totally unobtrusive, and only blinks the moment anyone clicks a link, thus spreading some positive feelings to all supporters of web standards.&lt;/p&gt;
&lt;p&gt;Example implementations can be found &lt;a href=&quot;#&quot;&gt;here&lt;/a&gt; and on&amp;nbsp;&lt;a href=&quot;http://coverontwerp.nl/&quot;&gt;http://coverontwerp.nl/&lt;/a&gt;. Show some standards love, by including the snippet below on your site!&lt;/p&gt;
&lt;div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;css&quot;&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:active:after&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;inline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;bold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;:)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;webkit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rotate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
	&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;moz&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rotate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rotate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Other selectors, styling and ASCII arts are encouraged!&lt;/p&gt;
</content>
		
		<category term="acidtest" />
		
		<category term="css3" />
		
		<category term="smile" />
		
		<category term="webstandards" />
		
	</entry>
	
	<entry>
		<title>Search Google in running browser</title>
		<link href="http://pepijndevos.nl/search-google-in-running-browser/index.html"/>
		<updated>2010-08-23T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/search-google-in-running-browser/search-google-in-running-browser</id>
		<content type="html">&lt;p&gt;After reading &lt;a href=&quot;http://hints.macworld.com/article.php?story=20100527194703792&quot;&gt;this hint&lt;/a&gt;, I wanted to get it working with my &lt;a href=&quot;http://pepijndevos.nl/2010/05/open-external-links-in-running-browser&quot;&gt;previous script&lt;/a&gt; to open links in the currently running browser.&lt;/p&gt;

&lt;p&gt;I did not use OnMyCommand, but instead just made an Automator service. Here is how:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open Automator and create a service&lt;/li&gt;
&lt;li&gt;Set the type to text&lt;/li&gt;
&lt;li&gt;Add the &amp;lsquo;Run shell script&amp;rsquo; action&lt;/li&gt;
&lt;li&gt;Set the shell to Python and the input to &amp;lsquo;as arguments&amp;rsquo;&lt;/li&gt;
&lt;li&gt;Paste the script below&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The script(this text serves only to satisfy Posterous&amp;rsquo;s parsing engine, which is seriously pissing me off):&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;ic&quot;&gt;sys&lt;/span&gt;
&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;ic&quot;&gt;urllib&lt;/span&gt;
&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;ic&quot;&gt;webbrowser&lt;/span&gt;
webbrowser.open(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;http://www.google.nl/search?q=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + urllib.quote(sys.argv[&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;]))&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;img src=&quot;http://posterous.com/getfile/files.posterous.com/pepijndevos/jTXpVTtPGIuguNUYiAvbIYzpjmlFmBCbQNQNijhDaExIuIYRqv4gxEFZ1eYc/Screen_shot_2010-08-23_at_5.59.png.thumb100.jpg?content_part=YKnwiM1pvjrw39Qv040e&quot; alt=&quot;Automator&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You need to have my previous script installed to do the actual opening of the url. With some more trickery, it is even possible to add this service as a keyboard shortcut. I suggest you Google around a bit, and comment if you find something revolutionary.&lt;/p&gt;
</content>
		
		<category term="automator" />
		
		<category term="macosx" />
		
		<category term="python" />
		
		<category term="webbrowser" />
		
	</entry>
	
	<entry>
		<title>JS server benchmark: Node.js &amp; Rhino; Part 2</title>
		<link href="http://pepijndevos.nl/js-server-benchmark-nodejs-rhino-part-2/index.html"/>
		<updated>2010-08-22T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/js-server-benchmark-nodejs-rhino-part-2/js-server-benchmark-nodejs-rhino-part-2</id>
		<content type="html">After having tested the pure&amp;nbsp;&lt;a href=&quot;http://pepijndevos.nl/js-server-benchmark-nodejs-rhino&quot;&gt;JS speed of Node and Rhino&lt;/a&gt;&amp;nbsp;in my previous post, I wanted to see some actual numbers for serving stuff.&lt;p /&gt;&lt;div&gt;Long story short, I grabbed the &quot;Hello world!&quot; examples from both&amp;nbsp;&lt;a href=&quot;http://nodejs.org/&quot;&gt;Node.js&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href=&quot;http://github.com/thatcher/rhino-for-webapps/blob/master/scripts/helloworld/hello.js&quot;&gt;Rhino running on Jetty&lt;/a&gt;&amp;nbsp;and ran 'ab' on them.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;I was not able to do high-concurrency tests on my Mac, because Jetty gave up around 100, and Node somewhere around 200. I think I'm having&amp;nbsp;&lt;a href=&quot;http://stackoverflow.com/questions/1216267/ab-program-freezes-after-l&quot;&gt;the issue described here&lt;/a&gt;.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;So here is the graph. I don't have much experience with benchmarking, but again, it is obvious that Node.js is in fact quite a lot faster than the Rhino/Jetty combo.&lt;br /&gt;&lt;p /&gt;&lt;div&gt;&lt;img src=&quot;/images/out.png&quot; alt=&quot;JS server benchmark: Node.js &amp; Rhino; Part 2&quot; /&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;
</content>
		
	</entry>
	
	<entry>
		<title>Remove the bookmark button in Safari</title>
		<link href="http://pepijndevos.nl/remove-the-bookmark-button-in-safari/index.html"/>
		<updated>2010-08-20T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/remove-the-bookmark-button-in-safari/remove-the-bookmark-button-in-safari</id>
		<content type="html">&lt;div&gt;A while back I found&amp;nbsp;&lt;a href=&quot;http://www.collegehumor.com/article:1802516&quot;&gt;this comic&lt;/a&gt;, comparing Safari with a bike, and Firefox with a car with a lot of stuff attached to it.&lt;/div&gt;&lt;p /&gt;&lt;p /&gt;&lt;p&gt;&lt;img src=&quot;/images/collegehumor.82a2a603235eaa0e1.jpeg&quot; alt=&quot;Remove the bookmark button in Safari&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p /&gt;&lt;p /&gt;&lt;div&gt;But in reality, since Safari 5 supports&amp;nbsp;&lt;a href=&quot;http://extensions.apple.com/&quot;&gt;extensions&lt;/a&gt;, it starts to look more and more like this illustration from a Dutch children book.&lt;/div&gt;&lt;p /&gt;&lt;p /&gt;&lt;p&gt;&lt;img src=&quot;/images/Photo_on_2010-08-20_at_15.17.jpeg&quot; alt=&quot;Remove the bookmark button in Safari&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p /&gt;&lt;p /&gt;&lt;div&gt;Now that I have lots of goodies and a nice Delicious bookmark button, I wanted to get rid of the bookmark button embedded in the navigation bar. This video shows how to do it.&lt;/div&gt;&lt;p /&gt;&lt;p&gt;[[posterous-content:XUORk3FShLrdFY9GRo7d]]&lt;/p&gt;&lt;p&gt;&lt;p /&gt; If someone knows how to embed the Delicious button in the navigation bar, I would be very pleased.&lt;/p&gt;
</content>
		
	</entry>
	
	<entry>
		<title>JS server benchmark: Node.js &amp; Rhino</title>
		<link href="http://pepijndevos.nl/js-server-benchmark-nodejs-rhino/index.html"/>
		<updated>2010-08-19T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/js-server-benchmark-nodejs-rhino/js-server-benchmark-nodejs-rhino</id>
		<content type="html">&lt;h3&gt;Background&lt;/h3&gt;

&lt;p&gt;I&amp;rsquo;m playing with the idea of writing a little web framework in JavaScript using jQuery on both the server and the browser. To run jQuery on the server, you need &amp;mdash; except for JavaScript &amp;mdash; some magic, such as &lt;a href=&quot;http://github.com/thatcher/env-js&quot;&gt;env.js&lt;/a&gt; and &lt;a href=&quot;http://github.com/tmpvar/jsdom&quot;&gt;jsdom&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Env.js is a complete browser environment that allows you to run almost all &lt;em&gt;browser&lt;/em&gt; JS code(like jQuery) on Rhino, a JavaScript engine written in Java. It is very complete, but tied to Rhino.&lt;/p&gt;

&lt;p&gt;Jsdom is a younger project implementing only the DOM in CommonJS, though it is written for Node.js, an event-based network server based en Googles V8 JavaScript engine.&lt;/p&gt;

&lt;p&gt;While I know some Java, and env.js does all I need, I got the impression that Node.js offers more in terms of speed and is more suitable for a web framework.&lt;/p&gt;

&lt;p&gt;Since jsdom does not do AJAX and events, I&amp;rsquo;m facing the choice between using Rhino, or porting env.js to Node. I started to investigate the possibilities, and here is what I found.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;V8 &lt;em&gt;is&lt;/em&gt; fast&lt;/li&gt;
&lt;li&gt;env.js has only &lt;a href=&quot;http://github.com/thatcher/env-js/tree/master/src/platform/rhino/&quot;&gt;±100 lines of Rhino specific code&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Running the benchmark&lt;/h3&gt;

&lt;p&gt;Searching for benchmarks comparing server side JavaScript, I found none. I did find the &lt;a href=&quot;http://v8.googlecode.com/svn/data/benchmarks/v5/run.html&quot;&gt;JS benchmark Google uses to test V8&lt;/a&gt;, which might of course be skewed towards V8. I tried them anyway.&lt;/p&gt;

&lt;h4&gt;Node.js&lt;/h4&gt;

&lt;p&gt;Installing Node was a breeze, but getting the V8 benchmark to run on a V8 based framework was not so easy.&lt;/p&gt;

&lt;p&gt;For some unknown reason the V8 benchmark uses load() to load everything together, while Node uses require(), with a slightly different meaning, which made simply substituting them impossible.&lt;/p&gt;

&lt;p&gt;Stride on &lt;a href=&quot;irc://irc.freenode.net?join=#node.js&quot;&gt;#node.js&lt;/a&gt; came up with the solution, consisting of concatenating the files together with some shell magic:&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;cat base&lt;span class=&quot;other&quot;&gt;.&lt;/span&gt;js crypto&lt;span class=&quot;other&quot;&gt;.&lt;/span&gt;js deltablue&lt;span class=&quot;other&quot;&gt;.&lt;/span&gt;js earley&lt;span class=&quot;argument&quot;&gt;-boyer&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;.&lt;/span&gt;js raytrace&lt;span class=&quot;other&quot;&gt;.&lt;/span&gt;js regexp&lt;span class=&quot;other&quot;&gt;.&lt;/span&gt;js richards&lt;span class=&quot;other&quot;&gt;.&lt;/span&gt;js splay&lt;span class=&quot;other&quot;&gt;.&lt;/span&gt;js run&lt;span class=&quot;other&quot;&gt;.&lt;/span&gt;js &amp;gt; v8bench&lt;span class=&quot;other&quot;&gt;.&lt;/span&gt;js&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Note that the order of the files was important, otherwise a simple &amp;ldquo;cat *.js&amp;rdquo; would have sufficed.&lt;/p&gt;

&lt;p&gt;Now all that remained was commenting out the original imports and defining a print function:&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;print = require(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).log&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Now this is the result:&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;other&quot;&gt;$&lt;/span&gt; node v8bench&lt;span class=&quot;other&quot;&gt;.&lt;/span&gt;js
&lt;span class=&quot;number&quot;&gt;19&lt;/span&gt; Aug &lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;25&lt;/span&gt; &lt;span class=&quot;other&quot;&gt;-&lt;/span&gt; Crypto&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;2434&lt;/span&gt;
&lt;span class=&quot;number&quot;&gt;19&lt;/span&gt; Aug &lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;26&lt;/span&gt; &lt;span class=&quot;other&quot;&gt;-&lt;/span&gt; DeltaBlue&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;3150&lt;/span&gt;
&lt;span class=&quot;number&quot;&gt;19&lt;/span&gt; Aug &lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;28&lt;/span&gt; &lt;span class=&quot;other&quot;&gt;-&lt;/span&gt; EarleyBoyer&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;12752&lt;/span&gt;
&lt;span class=&quot;number&quot;&gt;19&lt;/span&gt; Aug &lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;29&lt;/span&gt; &lt;span class=&quot;other&quot;&gt;-&lt;/span&gt; RayTrace&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;6230&lt;/span&gt;
&lt;span class=&quot;number&quot;&gt;19&lt;/span&gt; Aug &lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;other&quot;&gt;-&lt;/span&gt; RegExp&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;2287&lt;/span&gt;
&lt;span class=&quot;number&quot;&gt;19&lt;/span&gt; Aug &lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;31&lt;/span&gt; &lt;span class=&quot;other&quot;&gt;-&lt;/span&gt; Richards&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;1547&lt;/span&gt;
&lt;span class=&quot;number&quot;&gt;19&lt;/span&gt; Aug &lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;33&lt;/span&gt; &lt;span class=&quot;other&quot;&gt;-&lt;/span&gt; Splay&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;8879&lt;/span&gt;
&lt;span class=&quot;number&quot;&gt;19&lt;/span&gt; Aug &lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;33&lt;/span&gt; &lt;span class=&quot;other&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;other&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;-&lt;/span&gt;
&lt;span class=&quot;number&quot;&gt;19&lt;/span&gt; Aug &lt;span class=&quot;number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;33&lt;/span&gt; &lt;span class=&quot;other&quot;&gt;-&lt;/span&gt; Score &lt;span class=&quot;other&quot;&gt;(&lt;/span&gt;version &lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;4090&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Note the last number(average score) and the length of the command(2 parts).&lt;/p&gt;

&lt;h4&gt;Rhino&lt;/h4&gt;

&lt;p&gt;Installing Rhino was equally easy(just &amp;ldquo;port install rhino nodejs&amp;rdquo;)&lt;/p&gt;

&lt;p&gt;Then the trouble started&amp;hellip; First I had to figure out how to run Rhino, because it doesn&amp;rsquo;t come with its own command, like Node does. Turns out it&amp;rsquo;s &amp;ldquo;java -jar /path/to/js.jar&amp;rdquo;&lt;/p&gt;

&lt;p&gt;After that, I ran &amp;lsquo;run.js&amp;rsquo; from the v8 benchmark, and it just worked! &lt;strong&gt;Without&lt;/strong&gt; modification! &amp;hellip; Until it gave java.lang.OutOfMemoryError. Some Googling reveals that unless you have a memory leak in your app, you can increase the memory limit, which I did.&lt;/p&gt;

&lt;p&gt;Here are the results for Rhino:&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;other&quot;&gt;$&lt;/span&gt; java &lt;span class=&quot;argument&quot;&gt;-Xmx265m&lt;/span&gt; &lt;span class=&quot;argument&quot;&gt;-jar&lt;/span&gt; js&lt;span class=&quot;other&quot;&gt;.&lt;/span&gt;jar run&lt;span class=&quot;other&quot;&gt;.&lt;/span&gt;js
Richards&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;
DeltaBlue&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;138&lt;/span&gt;
Crypto&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;120&lt;/span&gt;
RayTrace&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;253&lt;/span&gt;
EarleyBoyer&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;248&lt;/span&gt;
RegExp&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;59&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;
Splay&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;279&lt;/span&gt;
&lt;span class=&quot;other&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;-&lt;/span&gt;
Score &lt;span class=&quot;other&quot;&gt;(&lt;/span&gt;version &lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;other&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;number&quot;&gt;120&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Again note the score and the length of the command(5 parts). The -Xmx265m is for raising the memory limit.&lt;/p&gt;

&lt;h3&gt;My verdict&lt;/h3&gt;

&lt;p&gt;Sure, Node&amp;rsquo;s score is about 34 times the score of Rhino, but I talked to the author of &lt;a href=&quot;http://www.claypooljs.com/&quot;&gt;Claypool&lt;/a&gt;, and he used Rhino for several production sites, without performance problems. &lt;a href=&quot;http://xkcd.com/670/&quot;&gt;It&amp;rsquo;s a measurement without a scale&lt;/a&gt;, so I can&amp;rsquo;t judge if it will matter to me.&lt;/p&gt;

&lt;p&gt;With the speed sorted out, there is just the general style and comfort of both systems. Node.js is a very young C++ project, while Rhino has been around since the Netscape ages and is written in Java.&lt;/p&gt;

&lt;p&gt;While I&amp;rsquo;m attracted to the speed and freshness of Node, I know more Java than I know C++, and there are tons of Java libs available to Rhino. And then there is env.js, which needs to be ported to Node, if I decide to use that.&lt;/p&gt;

&lt;p&gt;Besides the porting and library issue, there is also hosting. Because Node is so new, you&amp;rsquo;d have to rent your own VPS, while Rhino can run in any Java servlet container, and even Google App Engine with the help of &lt;a href=&quot;http://github.com/thatcher/rhino-for-webapps&quot;&gt;Rhino-for-webapps&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, my verdict? &lt;strong&gt;Undecided&lt;/strong&gt;: As always, it depends on what you want, and I&amp;rsquo;m not yet sure what I want.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[update]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;FireFox gets only 394 in the same test, so Rhino is probably not &lt;em&gt;that&lt;/em&gt; bad.&lt;/p&gt;

&lt;p&gt;I would be very grateful if anyone could give me some information on the CommonJS load/require and print problem or ways to speed up Rhino.&lt;/p&gt;
</content>
		
		<category term="benchmark" />
		
		<category term="javascript" />
		
		<category term="nodejs" />
		
		<category term="rhino" />
		
	</entry>
	
	<entry>
		<title>Twisted pop3 example server</title>
		<link href="http://pepijndevos.nl/twisted-pop3-example-server/index.html"/>
		<updated>2010-08-18T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/twisted-pop3-example-server/twisted-pop3-example-server</id>
		<content type="html">Remember last time when&amp;nbsp;&lt;a href=&quot;http://pepijndevos.nl/twsited-smtp-server-with-authentication&quot;&gt;I showed you the Twisted SMTP server&lt;/a&gt;? This time it's a POP3 server. I think it is more common to write SMTP servers as a part of a project(to send notifications and stuff), but I needed a POP3 server, so I think there might be others who need a POP3 server as well.&lt;p /&gt;&lt;div&gt;The process is rather similar to SMTP, only you need to implement the&amp;nbsp;&lt;a href=&quot;http://twistedmatrix.com/documents/current/api/twisted.mail.pop3.IMailbox.html&quot;&gt;IMailbox interface&lt;/a&gt;. This is usually done with some sort of file or db based solution, but I used a simple list in this case. You might want to have a look at the&amp;nbsp;&lt;a href=&quot;http://docs.python.org/library/mailbox.html&quot;&gt;mailbox&lt;/a&gt;&amp;nbsp;module for a serious implementation.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;Below you'll find a bare bones POP3 server, which can be run with `twistd -ny pop3.tac` and below that a sample telnet session, by running `telnet localhost 1230` in another terminal.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;Connected&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;localhost&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Escape&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;character&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;^]&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OK&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;20100818095058.3878&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;894125537.0&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@pepijn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;de&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;voss&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;imac&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;local&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;guest&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OK&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;USER&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accepted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PASS&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OK&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Authentication&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;succeeded&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stat&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OK&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1020&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;retr&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OK&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;51&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;From&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;me&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;To&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;you&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Subject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mail&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;Hello&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;world&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;retr&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ERR&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bad&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argument&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;quit&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OK&lt;/span&gt; 
&lt;span class=&quot;n&quot;&gt;Connection&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;closed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;by&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foreign&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;An example pop3 server&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.application&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;internet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;service&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.cred.portal&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Portal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IRealm&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.internet.protocol&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ServerFactory&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.mail&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pop3&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.mail.pop3&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IMailbox&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.cred.checkers&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InMemoryUsernamePasswordDatabaseDontUse&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;zope.interface&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;implements&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;itertools&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;repeat&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;hashlib&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;md5&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;StringIO&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;StringIO&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleMailbox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;implements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IMailbox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;quot;&amp;quot;From: me&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;To: you&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;Subject: A test mail&lt;/span&gt;

&lt;span class=&quot;s&quot;&gt;Hello world!&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;repeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;


    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;listMessages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;StringIO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getUidl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;md5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;messages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hexdigest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;deleteMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;undeleteMessages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleRealm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;implements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IRealm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;requestAvatar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;avatarId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;interfaces&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IMailbox&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;interfaces&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IMailbox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SimpleMailbox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;NotImplementedError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;portal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Portal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SimpleRealm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;checker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InMemoryUsernamePasswordDatabaseDontUse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;checker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;guest&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;password&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;portal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;registerChecker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;checker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;application&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;example pop3 server&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ServerFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;protocol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pop3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;POP3&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;portal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;portal&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;internet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TCPServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1230&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setServiceParent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</content>
		
	</entry>
	
	<entry>
		<title>Check multiple twisted.cred checkers for a valid login</title>
		<link href="http://pepijndevos.nl/check-multiple-twistedcred-checkers-for-a-val/index.html"/>
		<updated>2010-08-01T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/check-multiple-twistedcred-checkers-for-a-val/check-multiple-twistedcred-checkers-for-a-val</id>
		<content type="html">&lt;p&gt;This is a snippet of a credential checker I wrote to authenticate a user &lt;br /&gt;first via my DB, and if that fails via Twitter. It helped me to speed up &lt;br /&gt;login, after the initial Twitter access tokens are stored. &lt;p /&gt; In theory, this snippet could be used to authenticate against any number &lt;br /&gt;of checkers, providing different interfaces. Only if all of them fail, &lt;br /&gt;it returns an error. &lt;p /&gt; 
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.cred.checkers&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ICredentialsChecker&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.cred&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;credentials&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;zope.interface&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;implements&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;collections&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deque&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CascadingChecker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    Check multiple checkers untill one succeeds.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    Else raise UnauthorizedLogin.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;implements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ICredentialsChecker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;credentialInterfaces&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;checkers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;checked&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;registerChecker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;checker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;checkers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;checker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;credentialInterfaces&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;checker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;credentialInterfaces&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_requestAvatarId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;ch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;queue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;popleft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;IndexError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UnauthorizedLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requestAvatarId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addErrback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_requestAvatarId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;requestAvatarId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_requestAvatarId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deque&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;checkers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.trial&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unittest&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;checkers&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CascadingChecker&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.cred.credentials&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UsernamePassword&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.cred.checkers&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InMemoryUsernamePasswordDatabaseDontUse&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.cred.error&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UnauthorizedLogin&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.cred.credentials&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IUsernameHashedPassword&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IUsernamePassword&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CascadingTest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unittest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TestCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setUp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ch1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InMemoryUsernamePasswordDatabaseDontUse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ch2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InMemoryUsernamePasswordDatabaseDontUse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cach&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CascadingChecker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;ch1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;bar&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ch1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;boo&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;far&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ch2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;for&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;bao&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cach&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;registerChecker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ch1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cach&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;registerChecker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ch2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testInterfaces&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cach&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;credentialInterfaces&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;difference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IUsernameHashedPassword&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IUsernamePassword&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testLoginFirstChecker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UsernamePassword&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;bar&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cach&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requestAvatarId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testLoginSecondChecker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UsernamePassword&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;for&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;bao&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cach&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requestAvatarId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testLoginFail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UsernamePassword&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;steve&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;pswd&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assertFailure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cach&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requestAvatarId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UnauthorizedLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/p&gt;
</content>
		
		<category term="checker" />
		
		<category term="twisted" />
		
		<category term="twistedcred" />
		
	</entry>
	
	<entry>
		<title>XAuth(CamelCase), xAuth(iCase), XOAUTH(ALLCAPS); 3 distinct technologies, confusing?</title>
		<link href="http://pepijndevos.nl/xauthcamelcase-xauthicase-xoauthallcaps-3-dis/index.html"/>
		<updated>2010-07-29T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/xauthcamelcase-xauthicase-xoauthallcaps-3-dis/xauthcamelcase-xauthicase-xoauthallcaps-3-dis</id>
		<content type="html">&lt;p&gt;While thinking up names, Unix/open source people tend to come up with
names containing &amp;lsquo;X&amp;rsquo;. I can almost hear them scream &amp;ldquo;&amp;lsquo;X&amp;rsquo;, the new and
free(as in beer, pizza and speech) &amp;lsquo;i&amp;rsquo;(as in iPhone, iPod, etc.)!&amp;rdquo;&lt;/p&gt;

&lt;p&gt;My (possibly fictive) story goes like this: Some time ago, 3 separate
development teams came together to find a name for their product.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://xauth.org/&quot;&gt;first team&lt;/a&gt; was making a secure, social, easy
way of authenticating browsers. Since they where developing an open
authentication protocol, and read loads of developer guidelines, they
came up with XAuth, using proper CamelCasing, as one was supposed to.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://dev.twitter.com/pages/xauth&quot;&gt;second team&lt;/a&gt; had a nice OAuth
implementation running, but some people required using good ol'
passwords, so they came up with the idea of requesting tokens using
regular credentials, instead of complicated token exchanges. Since they
wanted to be hip, and had a nice marketing department, they came up with
xAuth, in line with the iDevice casing.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://code.google.com/intl/nl/apis/gmail/oauth/protocol.html&quot;&gt;third
team&lt;/a&gt;
thought it would be nice to apply the security of OAuth to email. Since
this was way to cool to be called OAuth-for-email, they decided to add
the cool &amp;lsquo;X&amp;rsquo; in front of it. And as we all know(don&amp;rsquo;t we?), mail servers
talk to each other in ALL CAPS, so it was a logical thing to call their
system XOAUTH(although they&amp;rsquo;re not all that consistent about it).&lt;/p&gt;
</content>
		
		<category term="oauth" />
		
		<category term="xauth" />
		
		<category term="xoauth" />
		
	</entry>
	
	<entry>
		<title>Twisted SMTP server with authentication</title>
		<link href="http://pepijndevos.nl/twsited-smtp-server-with-authentication/index.html"/>
		<updated>2010-07-22T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/twsited-smtp-server-with-authentication/twsited-smtp-server-with-authentication</id>
		<content type="html">&lt;p&gt;This is the next post about Twisted, this time about Twisted.mail. After my Twisted project is done I'm going to contribute all my findings in some examples, docstrings and maybe even a howto. This post mainly serves as my notebook for things to remember about SMTP in Twisted.&lt;/p&gt;
&lt;div&gt;This is a twistd app taken from the Twisted examples section, and modified to support authentication. Below you'll find all my notes.&lt;/div&gt;
&lt;div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Copyright (c) 2001-2004 Twisted Matrix Laboratories.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# See LICENSE for details.&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# You can run this module directly with:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#    twistd -ny esmtpserver.tac&lt;/span&gt;


&lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;A toy email server with authentication.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;zope.interface&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;implements&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.internet&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defer&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.mail&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;smtp&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.mail.mail&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MailService&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# these challengers are located in imap4&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.mail.imap4&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOGINCredentials&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PLAINCredentials&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.cred.checkers&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InMemoryUsernamePasswordDatabaseDontUse&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;#except in examples and testing&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.cred.portal&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IRealm&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.cred.portal&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Portal&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ConsoleMessageDelivery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;implements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;smtp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IMessageDelivery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;receivedHeader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;helo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recipients&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Received: ConsoleMessageDelivery&amp;quot;&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;validateFrom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;helo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# All addresses are accepted&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;validateTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# Only messages directed to the &amp;quot;console&amp;quot; user are accepted.&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;console&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConsoleMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;smtp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SMTPBadRcpt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ConsoleMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;implements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;smtp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;lineReceived&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;eomReceived&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;New message received:&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;succeed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;connectionLost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# There was an error, throw away the stored lines&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ConsoleSMTPFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;smtp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SMTPFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;smtp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SMTPFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# make this factory make ESMTP servers&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;protocol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;smtp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ESMTP&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;buildProtocol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;smtp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SMTPFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buildProtocol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# add the challengers from imap4, more secure and complicated challengers are available&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;challengers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;LOGIN&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOGINCredentials&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;PLAIN&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PLAINCredentials&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleRealm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;implements&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IRealm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;requestAvatar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;avatarId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;interfaces&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# if we are authenticating a IMessageDelivery&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;smtp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IMessageDelivery&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;interfaces&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;c&quot;&gt;# a tuple of the implemented interface, an instance implementing it and a logout callable&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;smtp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IMessageDelivery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConsoleMessageDelivery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;NotImplementedError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.application&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;internet&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;twisted.application&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;service&lt;/span&gt;    
    
    &lt;span class=&quot;n&quot;&gt;portal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Portal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SimpleRealm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# initiate a simple checker&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;checker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InMemoryUsernamePasswordDatabaseDontUse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;checker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;guest&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;password&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;portal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;registerChecker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;checker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Application&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Console SMTP Server&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;internet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TCPServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConsoleSMTPFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;portal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setServiceParent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;application&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul class=&quot;MailOutline&quot;&gt;
&lt;li&gt;If you want anything beyond a toy, you'll need to use ESMTP instead of SMTP&lt;/li&gt;
&lt;li&gt;You need to have a portal with a realm and a checker set up to use the AUTH command&lt;/li&gt;
&lt;li&gt;challengers are what provide the protocol for logging in, note that they are located in twisted.imap4&lt;/li&gt;
&lt;li&gt;A portal takes one checker instance per authentication method, so you can have one for handling strange tokens, and one for regular username/password authentication, but not two for the same type.&lt;/li&gt;
&lt;li&gt;Take a look at the source for InMemoryUsernamePasswordDatabaseDontUse, it is really simple to write your own checker.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content>
		
		<category term="authentication" />
		
		<category term="esmtp" />
		
		<category term="python" />
		
		<category term="smtp" />
		
		<category term="twisted" />
		
	</entry>
	
	<entry>
		<title>Messing with the REPL with Twisted</title>
		<link href="http://pepijndevos.nl/messing-with-the-repl-with-twisted/index.html"/>
		<updated>2010-07-22T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/messing-with-the-repl-with-twisted/messing-with-the-repl-with-twisted</id>
		<content type="html">&lt;p&gt;I love to try out things on the REPL(read eval print loop) before I write scripts with them. The trouble with Twisted is that everything returns deferreds, and after your start the reactor, you can&amp;rsquo;t do anything anymore.&lt;/p&gt;

&lt;p&gt;All this is solved by this one single command. It gives you a REPL &lt;em&gt;powered by&lt;/em&gt; the Twisted event loop. To make things even better: It prints the value of a deferred once it is finished!&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;python &lt;span class=&quot;argument&quot;&gt;-m&lt;/span&gt; twisted&lt;span class=&quot;other&quot;&gt;.&lt;/span&gt;conch&lt;span class=&quot;other&quot;&gt;.&lt;/span&gt;stdio&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Added hint: Put this in a file, do &amp;ldquo;chmod +x&amp;rdquo; on it and put it on your $PATH.&lt;/p&gt;
</content>
		
		<category term="python" />
		
		<category term="repl" />
		
		<category term="twisted" />
		
	</entry>
	
	<entry>
		<title>Pepijndevos.nl moved to Posterous</title>
		<link href="http://pepijndevos.nl/pepijndevosnl-moved-to-posterous/index.html"/>
		<updated>2010-07-20T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/pepijndevosnl-moved-to-posterous/pepijndevosnl-moved-to-posterous</id>
		<content type="html">&lt;p&gt;After weighting the pros and the cons of moving to Posterous completely, I decided to do it. Wishful Coding has now completely moved to Posterous. &lt;p /&gt; If you see anything broken, drop me a line or try the original blog, which will be available for a while at &lt;a href=&quot;http://pepijn.cqhosting.nl&quot;&gt;pepijn.cqhosting.nl&lt;/a&gt;. &lt;p /&gt; I'd like to thank the awesome people of both Posterous and &lt;a href=&quot;http://cqhosting.nl&quot;&gt;CQ Hosting&lt;/a&gt;(who used to host my Wordpress blog). From the initial export tot the switch of the domain took only a few hours. &lt;p /&gt; The only thing that didn't go as planned are he images in old posts. They where still linked to pepijndevos.nl, which meant that switching the domain would break links. &lt;p /&gt; I asked CQ Hosting to make my old blog available through some sort of address, which they did almost instantly. Now I could replace every instance of pepijndevos.nl with pepijn.cqhosting.nl, and keep all images and links intact. &lt;p /&gt; My beautiful Wordpress Theme is gone for now, but I'll make my own Posterous theme later on. Watch out for some crazy CSS3 and HTML5!&lt;/p&gt;
</content>
		
		<category term="cqhosting" />
		
		<category term="posterous" />
		
		<category term="wordpress" />
		
	</entry>
	
	<entry>
		<title>My thoughts on iPhone reception</title>
		<link href="http://pepijndevos.nl/my-thoughts-on-iphone-reception/index.html"/>
		<updated>2010-07-20T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/my-thoughts-on-iphone-reception/my-thoughts-on-iphone-reception</id>
		<content type="html">&lt;div&gt;In the&amp;nbsp;&lt;a href=&quot;http://www.apple.com/apple-events/july-2010/&quot;&gt;press conference Apple gave on July 16&lt;/a&gt;&amp;nbsp;about the iPhone G4 reception issues, they basically said that the 4 or 5 bars you usually see where fake, and caused by a &quot;bug&quot; in the way signal strength is measured.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;If I remember correctly, there was another &quot;bug&quot; with the reception prior to iOS 4, that was solved by a&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/IOS_version_history#cite_ref-19&quot;&gt;software update &quot;improving&quot; G3 reception.&lt;/a&gt;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;I can't help thinking they just tweaked their formula to show high bars to save their asses, and this backfired on them with iOS 4.&lt;/div&gt;
</content>
		
	</entry>
	
	<entry>
		<title>Bring actual image data in sync with EXIF orientation</title>
		<link href="http://pepijndevos.nl/bring-actual-image-data-in-sync-with-exif-ori/index.html"/>
		<updated>2010-07-20T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/bring-actual-image-data-in-sync-with-exif-ori/bring-actual-image-data-in-sync-with-exif-ori</id>
		<content type="html">&lt;div&gt;While sorting out all my holiday photographs, I turned them to the right orientation using F-Spot photo manager. When I came home I imported them into Adobe bridge, sorted them all out using all sorts of labels, tags and ratings.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;Everything was fine so far, until I looked at them with a bad viewer, or uploaded them to Facebook. F-Spot and Bridge happily adjusted the orientation in the EXIF meta-date, but left the actual image untouched.&lt;/div&gt;
&lt;div&gt;Not all viewers check the EXIF data before displaying an image, so they display it in the original orientation, corresponding to orientation 1 in EXIF.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;Now I was stuck with over a thousand neatly sorted and rotated photos, that I could not publish without rotating them all again with another application.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;Luckily I was saved by this page: &lt;a href=&quot;http://sylvana.net/jpegcrop/exif_orientation.html&quot;&gt;http://sylvana.net/jpegcrop/exif_orientation.html&lt;/a&gt;&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;If you run Mac and probably Linux as well, jpegtran is already installed.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;Just download the C app and the Bash script, but them in the same folder and run this command to compile:&lt;/div&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;gcc -o jpegexiforient jpegexiforient.c&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;div&gt;Now run these commands to make the files executable:&lt;/div&gt;
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;chmod +x jpegexiforient
chmod +x exifautotran&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;div&gt;I had to change exifautotran to read ./jpegexiforient in 2 places instead of just jpegexiforient. Otherwise it'd say &quot;command not found&quot;.&lt;/div&gt;
&lt;div&gt;Now you can run &quot;./exifautotran file.jpg&quot; to convert a single file, or &quot;./exifautotran /dir/*.jpg&quot; to convert a whole directory of jpg files.&lt;/div&gt;
</content>
		
		<category term="bash" />
		
		<category term="batchediting" />
		
		<category term="exif" />
		
		<category term="photography" />
		
	</entry>
	
	<entry>
		<title>Twitter xAuth in Python using Twisted and Twitty Twister</title>
		<link href="http://pepijndevos.nl/twitter-xauth-in-python-using-twisted-and-twi/index.html"/>
		<updated>2010-07-19T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/twitter-xauth-in-python-using-twisted-and-twi/twitter-xauth-in-python-using-twisted-and-twi</id>
		<content type="html">&lt;p&gt;This is the first post in what will most likely be a series of posts related to Twitter, POP3, SMTP and Twisted. This post will be about asynchronous authentication with Twitter using xAuth.&lt;/p&gt;

&lt;p&gt;xAuth is a simplified form of OAuth. Instead of doing the dance, you use credentials(like basic auth), but exchange them for an access token. You need to send a request to &lt;a href=&quot;mailto:api@twitter.com&quot;&gt;api@twitter.com&lt;/a&gt; to enable it.&lt;/p&gt;

&lt;p&gt;This technique is also applicable to getting OAuth tokens, although that is more complicated.&lt;/p&gt;

&lt;p&gt;We are going to use Twitty Twister, which is a Twitter lib for Twisted which supports signing OAuth requests. It does not, however, include code for obtaining an access token.&lt;/p&gt;

&lt;p&gt;To obtain the token, it is suggested to use an external library. But since my app is 100% Twisted, and most OAuth libs blocking, I had a problem right there. We don&amp;rsquo;t want to have our nice reactor sit idle while we request our token, do we?&lt;/p&gt;

&lt;p&gt;The solution is to use python-oauth to make the request, but just before we send it, you call request.to_postdata() and use twisted.web.client.getPage to send the request in an asynchronous manner.&lt;/p&gt;

&lt;p&gt;My main resources where:
&lt;a href=&quot;http://dev.twitter.com/pages/xauth&quot;&gt;http://dev.twitter.com/pages/xauth&lt;/a&gt;
&lt;a href=&quot;http://github.com/simplegeo/python-oauth2#readme&quot;&gt;http://github.com/simplegeo/python-oauth2#readme&lt;/a&gt;
&lt;a href=&quot;http://twistedmatrix.com/documents/10.1.0/api/twisted.web.client.getPage.html&quot;&gt;http://twistedmatrix.com/documents/10.1.0/api/twisted.web.client.getPage.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The resulting code(insert your key, secret, username and password):&lt;/p&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kw&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;ic&quot;&gt;oauth&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;ic&quot;&gt;oauth&lt;/span&gt;
&lt;span class=&quot;kw&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;ic&quot;&gt;twisted.web.client&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;ic&quot;&gt;getPage&lt;/span&gt;
&lt;span class=&quot;kw&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;ic&quot;&gt;twisted.internet&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;ic&quot;&gt;reactor&lt;/span&gt;
&lt;span class=&quot;kw&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;ic&quot;&gt;twittytwister&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;ic&quot;&gt;twitter&lt;/span&gt;
&lt;span class=&quot;kw&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;ic&quot;&gt;cgi&lt;/span&gt;

url = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;https://api.twitter.com/oauth/access_token&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
consumer = oauth.OAuthConsumer(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)

&lt;span class=&quot;kw&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;respond&lt;/span&gt;(tokens):
    params = cgi.parse_qs(tokens, keep_blank_values=&lt;span class=&quot;pc&quot;&gt;False&lt;/span&gt;)
    key = params[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;oauth_token&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;][&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;]
    secret = params[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;oauth_token_secret&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;][&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;]
    &lt;span class=&quot;kw&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;got access&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

    token = oauth.OAuthToken(key, secret)
    tweet = twitter.Twitter(consumer=consumer, token=token).update(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Hello world! First tweet using xauth via #Twisted and #Python&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
    tweet.addCallback(posted)

&lt;span class=&quot;kw&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;posted&lt;/span&gt;(message):
    &lt;span class=&quot;kw&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;message:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, message

request = oauth.OAuthRequest.from_consumer_and_token(oauth_consumer=consumer, http_method=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;POST&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, http_url=url,
    parameters = {
        &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;x_auth_mode&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;: &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;client_auth&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;,
        &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;x_auth_username&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;: &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;,
        &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;x_auth_password&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;: &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
    }
)
request.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(), consumer, &lt;span class=&quot;pc&quot;&gt;None&lt;/span&gt;)

page = getPage(url, method=&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;POST&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;, postdata=request.to_postdata())
page.addCallback(respond)

&lt;span class=&quot;kw&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;running...&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
reactor.run()&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
</content>
		
		<category term="authentication" />
		
		<category term="python" />
		
		<category term="twisted" />
		
		<category term="twitter" />
		
	</entry>
	
	<entry>
		<title>Twitter to text message is back!</title>
		<link href="http://pepijndevos.nl/twitter-to-text-message-is-back/index.html"/>
		<updated>2010-07-19T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/twitter-to-text-message-is-back/twitter-to-text-message-is-back</id>
		<content type="html">&lt;img src=&quot;/images/Screen_shot_2010-07-19_at_4.32.png&quot; alt=&quot;Twitter to text message is back!&quot; /&gt;&lt;p&gt;When you click the small phone icon, you can select to receive a text message on you phone of tweets of that user. &lt;p /&gt; Twitter previously offered a feature to text you for any new tweet and to allow you to tweet by text, but I assume that was shut down when people started to have thousands of followers.&lt;/p&gt;
</content>
		
	</entry>
	
	<entry>
		<title>Trying out Posterous</title>
		<link href="http://pepijndevos.nl/trying-out-posterous-4/index.html"/>
		<updated>2010-07-13T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/trying-out-posterous-4/trying-out-posterous-4</id>
		<content type="html">&lt;img src=&quot;/images/DSCF2682.jpg&quot; alt=&quot;Trying out Posterous&quot; /&gt;&lt;p&gt;I received a message via Twitter that Posterous now features Wordpress in its switch campaign. Although I&amp;#39;m in Ireland at the moment, I did not hesitate to try it out!&lt;p /&gt;This is just a message sent from Gmail, that will probably end up on several other places thanks to the autoposting feature in Posterous.&lt;p /&gt; I will also attach an image, to see what will happen to it.&lt;p /&gt;In the future I might make &lt;a href=&quot;http://pepijndevos.nl&quot;&gt;pepijndevos.nl&lt;/a&gt; the domain for &lt;a href=&quot;http://pepijndevos.posterous.com&quot;&gt;pepijndevos.posterous.com&lt;/a&gt;, and make it my main website, but before I do that, I need to figure out how to port a few features of my old blog to the new Posterous blog.&lt;br /&gt;&lt;/p&gt;
</content>
		
	</entry>
	
	<entry>
		<title>A better Trash for Mac</title>
		<link href="http://pepijndevos.nl/2010/06/a-better-trash-for-mac/index.html"/>
		<updated>2010-06-19T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/06/a-better-trash-for-mac/2010-06-a-better-trash-for-mac</id>
		<content type="html">Different at least...

I bothers me that the Mac Trash leaves hidden .Trash folders everywhere, including external drives. I wrote a few AppleScripts to move all Trash in one place and delete files completely.

If you only want to remove trash from external drives, &lt;a href=&quot;http://pepijn.cqhosting.nl/2010/02/automatically-remove-trash-from-usb-sticks/&quot;&gt;see my earlier post.&lt;/a&gt;

This approach is still far from ideal, but it's interesting and it might inspire someone to do a better job than I did.

The idea is to move files to a sparse image and delete that image when you need to empty the Trash. You can do this with Disk Utility and a bit of AppleScript.
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;/images/media_httppepijncqhos_kCIgq.png&quot; alt=&quot;A better Trash for Mac&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;a href=&quot;http://pepijn.cqhosting.nl/subpress/wp-content/uploads/2010/06/Screen-shot-2010-06-19-at-11.45.49-AM.png&quot;&gt;&lt;/a&gt;To create the image, open Disk Utility in /Applications/Utilities, click New Image and create a Sparse Image.&lt;/p&gt;
&lt;img src=&quot;/images/media_httppepijncqhos_dbhjr.png&quot; alt=&quot;A better Trash for Mac&quot; /&gt;I think it is nice to make the image a Stationary Pad, so you get a new Trash can every day for easier selective deletion. To do this, select the image and press CMD+i and select Stationary Pad.

Now all that remains are the AppleScripts. Save those as Application Bundles named Trash and Delete respectively.
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;property image : POSIX file &amp;quot;/Users/pepijndevos/Trash/Trash.sparseimage&amp;quot; -- edit this
property mount : POSIX file &amp;quot;/Volumes/Trash&amp;quot; -- and this

tell application &amp;quot;Finder&amp;quot;
        if not (exists mount) then
                open image
                delay 5
        end if
        open mount
end tell

on open the_files
        tell application &amp;quot;Finder&amp;quot;
                if not (exists mount) then
                        open image
                        delay 5
                end if
                repeat with the_file in the_files
                        do shell script &amp;quot;mv -f &amp;quot; &amp;amp; quoted form of POSIX path of the_file &amp;amp; &amp;quot; &amp;quot; &amp;amp; quoted form of POSIX path of mount
                end repeat
        end tell
end open&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;on open the_files
        repeat with the_file in the_files
                do shell script &amp;quot;rm -rf &amp;quot; &amp;amp; quoted form of POSIX path of the_file
        end repeat
end open&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;img src=&quot;/images/media_httppepijncqhos_pyGDv.png&quot; alt=&quot;A better Trash for Mac&quot; /&gt;Now drag these to the Dock for easy access to the Trash and Delete functions. You can just drag files on them to trash or delete them.

Another option of course is to have only the Delete script and a regular folder in your Dock, but that is not half as fun, is it?
</content>
		
	</entry>
	
	<entry>
		<title>Updating to Wordpress 3.0</title>
		<link href="http://pepijndevos.nl/2010/06/updating-to-wordpress-3-0/index.html"/>
		<updated>2010-06-17T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/06/updating-to-wordpress-3-0/2010-06-updating-to-wordpress-3-0</id>
		<content type="html">I'm trying to upgrade this blog to WordPress 3.0. While I skipped 2.9.2 because it was only a minor fix, this time there are some cool new features, which I'm not going to tell about, use Google!

This theme used the default comment template in WordPress 2.9, but unfortunately this has been removed or broken. To fix this, I had to use the comments.php from the new and shiny twentyten theme.

I copied their comments.php over to my theme, but unfortunately this only made matter worse. It uses a few functions defined in functions.php.

Rather than trying to copy those specific functions over to my functions.php, I just included theirs:
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;include(TEMPLATEPATH . &amp;quot;/../twentyten/functions.php&amp;quot;);&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

Can you think of a more ugly solution? I'll fix it later. There might be more bugs to be discovered.

&lt;strong&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;Do you see anything out-of-order on this blog? Please leave a comment.&lt;/span&gt;&lt;/strong&gt;
</content>
		
		<category term="comments" />
		
		<category term="twentyten" />
		
		<category term="upgrade" />
		
		<category term="wordpress30" />
		
	</entry>
	
	<entry>
		<title>Wordpress RSS widget in a post/page</title>
		<link href="http://pepijndevos.nl/2010/06/wordpress-rss-widget-in-a-post-page/index.html"/>
		<updated>2010-06-10T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/06/wordpress-rss-widget-in-a-post-page/2010-06-wordpress-rss-widget-in-a-post-page</id>
		<content type="html">I'm currently writing a theme for a friend who is going to coach photographers. He wants to have a page that lists RSS feeds from all those photographers.

One part of the puzzle is easily solved by using &lt;a href=&quot;http://pipes.yahoo.com/&quot;&gt;Yahoo! Pipes&lt;/a&gt; to combine those feeds, the other part isn't that easy to solve.

WordPress comes with a standard RSS widget, but it's only a widget, not a &lt;a href=&quot;http://en.support.wordpress.com/shortcodes/&quot;&gt;shortcode&lt;/a&gt;. There are a bunch of plugins that either offer a RSS widget or turn feeds items into posts.

What I did is write my own plugin in only 10 lines of actual code, utilizing the &lt;a href=&quot;http://codex.wordpress.org/Shortcode_API&quot;&gt;shortcode API&lt;/a&gt; and the built-in &lt;a href=&quot;http://en.support.wordpress.com/widgets/rss-widget/&quot;&gt;RSS widget&lt;/a&gt;.
&lt;ol&gt;
	&lt;li&gt;Save and upload the snippet below to your plugins folder&lt;/li&gt;
	&lt;li&gt;Activate it in the WP admin&lt;/li&gt;
	&lt;li&gt;Add the [rsstag] shortcode to your post or page&lt;/li&gt;
	&lt;li&gt;Add the feed url like this: [rsstag url=&quot;http://pepijn.cqhosting.nl/feed/&quot;]&lt;/li&gt;
	&lt;li&gt;Save!&lt;/li&gt;
&lt;/ol&gt;
You can optionally add one or more of show_summary=1, show_date=1 or show_author=1 to add the respective meta-data to every entry.
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;php
/*
Plugin Name: Wordpress RSS shortcode
Plugin URI: http://pepijn.cqhosting.nl/2010/06/wordpress-rss-widget-in-a-post-page
Description: This plugin fetches an RSS feed as a shortcode
Author: Pepijn de Vos
Version: 1.0
Author URI: http://pepijn.cqhosting.nl
*/

function rsstag($atts) {
        $atts = shortcode_atts(array(
                'url' =&amp;gt; get_bloginfo('rss2_url'),
                'show_author' =&amp;gt; 0,
                'show_date' =&amp;gt; 0,
                'show_summary' =&amp;gt; 0
        ), $atts);
        //var_dump($atts);
        wp_widget_rss_output($atts['url'], $atts);
}
add_shortcode('rsstag', 'rsstag');
?&amp;gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

I will upload this to WordPress.org soon.
</content>
		
		<category term="plugin" />
		
		<category term="rss" />
		
		<category term="shortcode" />
		
		<category term="wordpress" />
		
	</entry>
	
	<entry>
		<title>Wordpress MU in Resin with Quercus</title>
		<link href="http://pepijndevos.nl/2010/05/wordpress-mu-in-resin-with-quercus/index.html"/>
		<updated>2010-05-22T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/05/wordpress-mu-in-resin-with-quercus/2010-05-wordpress-mu-in-resin-with-quercus</id>
		<content type="html">While researching Quercus today, I ran into some trouble running the new integrated Multi Site feature of Wordpress 3.0(previously a separate project known as Wordpress MU or WPMU for short) on Resin.

Quercus is a PHP implementation written in Java that runs on any Java Servlet Container, including but not limited to Jetty, Tomcat or Resin. I took Resin for it was the easiest to setup and includes Quercus.

Normally one would just use Apache and mod_php, but I also want to run Jython and Clojure projects, so I'm looking for a solution to combine these.

Wordpress MU allows me to run multiple blogs on a single installation(as seen on &lt;a href=&quot;http://wordpress.com&quot;&gt;wordpress.com&lt;/a&gt;), which I want to use for hosting websites for my clients.

The problem with WPMU is that to map the different urls to one installation, some tricky mod_rewrite code is required for Apache, but since I'm using Resin here, I'll have to find another solution.

There is &lt;a href=&quot;http://wiki.caucho.com/Quercus:_Wordpress_Mu&quot;&gt;a post on the Quercus wiki&lt;/a&gt; describing the process of setting up a Multi Site Wordpress installation, but this is for an old version of WPMU(before the merge) and an old version of Resin.

After a good few hours of trying, I got it working with the latest version of Wordpress 3.0, Quercus 4.0.3 and Resin 4.0.7.
Just follow the wiki, except for a few points:
&lt;ul&gt;
	&lt;li&gt;Download at least Wordpress 3.0, which is &lt;a href=&quot;http://wordpress.org/development/2010/05/wordpress-3-0-beta-2/&quot;&gt;currently in beta&lt;/a&gt;
&lt;/li&gt;
	&lt;li&gt;Enable the network feature &lt;a href=&quot;http://wptheming.com/2010/03/wordpress-3-0-enable-network/&quot;&gt;like this&lt;/a&gt;
&lt;/li&gt;
	&lt;li&gt;Use this xml file instead:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;xml&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;web-app&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;http://caucho.com/ns/resin&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;xmlns:resin=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;urn:java:com.caucho.resin&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;resin:Forward&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;regexp=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;^/index\.php$&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;target=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;resin:Dispatch&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;regexp=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;^&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
		&lt;span class=&quot;nt&quot;&gt;&amp;lt;resin:IfFileExists/&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;/resin:Dispatch&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;resin:Redirect&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;regexp=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;^(/[_0-9a-zA-Z-]+/)?wp-admin$&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;target=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;$1wp-admin/&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;resin:Forward&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;regexp=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;^(/[_0-9a-zA-Z-]+/)?files/(.+)&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;target=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/wp-includes/ms-files.php?file=$2&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;resin:Forward&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;regexp=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;^(/[_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*)&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;target=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/$2&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;resin:Forward&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;regexp=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;^(/[_0-9a-zA-Z-]+/)?(.*\.php)$&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;target=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/$2&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;resin:Forward&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;regexp=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/.*&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;target=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/index.php&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/web-app&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

Note that I did not use the pro version, skipped the DNS stuff by using directory instead of subdomains in WP, I also skipped the chown stuff by removing this block from resin.xml:
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&amp;lt;resin:if test=&amp;quot;${resin.userName == 'root'}&amp;quot;&amp;gt;
        &amp;lt;user-name&amp;gt;pepijndevos&amp;lt;/user-name&amp;gt;
        &amp;lt;group-name&amp;gt;staff&amp;lt;/group-name&amp;gt;
      &amp;lt;/resin:if&amp;gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
</content>
		
		<category term="java" />
		
		<category term="php" />
		
		<category term="quercus" />
		
		<category term="resin" />
		
		<category term="wordpress30" />
		
		<category term="wpmu" />
		
	</entry>
	
	<entry>
		<title>RSS feed of Twitter lists</title>
		<link href="http://pepijndevos.nl/2010/05/rss-feed-of-twitter-lists/index.html"/>
		<updated>2010-05-20T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/05/rss-feed-of-twitter-lists/2010-05-rss-feed-of-twitter-lists</id>
		<content type="html">You want them? Me to! Here is how. The old-fashioned way:
&lt;ol&gt;
	&lt;li&gt;Create a Yahoo! ID&lt;/li&gt;
	&lt;li&gt;Do some &lt;a href=&quot;http://pipes.yahoo.com/pipes/pipe.info?_id=fb60de5ff93e81319e3c5fa207b9b276&quot;&gt;Yahoo! Pipe magic&lt;/a&gt;
&lt;/li&gt;
	&lt;li&gt;Get the RSS feed&lt;/li&gt;
&lt;/ol&gt;
But this is sub-ideal. Pipes have a huge url, a delay to long for practical use with Twitter, and are unreliable at times.

I searched the API for a solution but found none. The only official format for lists is &lt;a href=&quot;http://dev.twitter.com/doc/get/:user/lists/:id/statuses#supported-formats&quot;&gt;XML and JSON&lt;/a&gt;.

Just by trying anyway, I and &lt;a href=&quot;https://twitter.com/jaap3&quot;&gt;Jaap&lt;/a&gt; found out that lists do not have an RSS feed, but they do have an Atom feed(which is sort of RSS on steroids)! This can be used in most cases where an RSS feed is required.

The new way:
&lt;ol&gt;
	&lt;li&gt;Copy the url of a list, for example
&lt;span&gt;&lt;a href=&quot;http://twitter.com/erwinelling/eightmedia&quot;&gt;http://twitter.com/erwinelling/eightmedia&lt;/a&gt;&lt;/span&gt;
&lt;/li&gt;
	&lt;li&gt;Modify the url to look like this
&lt;span style=&quot;color: #999999;&quot;&gt;http://&lt;/span&gt;api.&lt;span style=&quot;color: #999999;&quot;&gt;twitter.com/&lt;/span&gt;1/&lt;span style=&quot;color: #999999;&quot;&gt;erwinelling/&lt;/span&gt;lists/&lt;span style=&quot;color: #999999;&quot;&gt;eightmedia&lt;/span&gt;/statuses.atom&lt;/li&gt;
&lt;/ol&gt;
Have fun! One word of warning though, because this feed is undocumented, it might change or disappear at any time.
</content>
		
		<category term="atom" />
		
		<category term="lists" />
		
		<category term="rss" />
		
		<category term="twitter" />
		
		<category term="yahoopipes" />
		
	</entry>
	
	<entry>
		<title>Save your date with PyMouse</title>
		<link href="http://pepijndevos.nl/2010/05/save-your-date-with-pymouse/index.html"/>
		<updated>2010-05-06T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/05/save-your-date-with-pymouse/2010-05-save-your-date-with-pymouse</id>
		<content type="html">&lt;img src=&quot;/images/media_httpimgsxkcdcom_dIads.png&quot; alt=&quot;Save your date with PyMouse&quot; /&gt;

With PyMouse this would never have happened. Don't risk your date, get PyMouse right now at its &lt;a href=&quot;http://github.com/pepijndevos/PyMouse&quot;&gt;GitHub page&lt;/a&gt;!

All that it takes to wiggle your pointer with PyMouse is this:
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;from pymouse import PyMouse
from time import sleep
from random import randint

m = PyMouse()
w, h = m.screen_size()
while True:
    try:
        m.move(randint(0, w), randint(0, h))
        sleep(20)
    except KeyboardInterrupt:
        print &amp;quot;Goodby!&amp;quot;
        break&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
</content>
		
		<category term="pymouse" />
		
		<category term="python" />
		
		<category term="xkcd" />
		
	</entry>
	
	<entry>
		<title>Open external links in running browser</title>
		<link href="http://pepijndevos.nl/2010/05/open-external-links-in-running-browser/index.html"/>
		<updated>2010-05-03T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/05/open-external-links-in-running-browser/2010-05-open-external-links-in-running-browser</id>
		<content type="html">&lt;img src=&quot;/images/media_httppepijncqhos_kBCFu.jpg&quot; alt=&quot;Open external links in running browser&quot; /&gt;As a web developer I have like 5 browsers installed which I use regularly. That is, not on daily basis, but for occasional testing and browsing.

What annoys me most about this is that when I click a link in another application, no matter what browser I'm currently running, it opens a fresh Safari window.

The ideal solution would be to open any urls with the browser I'm using at that moment, no mater which browser that is and which one is set as the default browser.

I have written a piece of Applescript that will do just this, you might need to edit this for the browsers which you are using though.

Below you'll find a zip file containing the app bundle, and all the scripts needed to generate it yourself.
&lt;p style=&quot;text-align: center; font-size: 1.5em;&quot;&gt;&lt;a href=&quot;http://pepijn.cqhosting.nl/subpress/wp-content/uploads/2010/05/Browser-Loader1.zip&quot;&gt;Browser Loader&lt;/a&gt;&lt;/p&gt;
To edit the browsers you use, open &quot;/Applications/Utilities/AppleScript Editor.app&quot; and then open the app bundle, this will reveal the script below, where you can make adjustments to the browsers used and their order.

If you want do do this yourself, or the app bundle does not work for you for some reason, this is the actual Applescript I used:
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;on open location the_url
        tell application &amp;quot;System Events&amp;quot;
                set browser_apps to the name of every process whose visible is true
                if &amp;quot;Opera&amp;quot; is in browser_apps then
                        tell application &amp;quot;Opera&amp;quot;
                                open location the_url
                                activate
                        end tell
                else if &amp;quot;firefox-bin&amp;quot; is in browser_apps then
                        tell application &amp;quot;Firefox&amp;quot;
                                open location the_url
                                activate
                        end tell
                else if &amp;quot;Google Chrome&amp;quot; is in browser_apps then
                        tell application &amp;quot;Google Chrome&amp;quot;
                                open location the_url
                                activate
                        end tell
                else
                        tell application &amp;quot;WebKit&amp;quot;
                                open location the_url
                                activate
                        end tell
                end if
        end tell
end open location&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;img src=&quot;/images/media_httppepijncqhos_ArsBd.png&quot; alt=&quot;Open external links in running browser&quot; /&gt;Copy this file to the Applescript editor and hit Save, before you save, choose to save as an app bundle and make sure to check the &quot;Stay Open&quot; box.

Now we need to modify the app bundle to make it eligible for url opening. To do this, right-click on the app and select &quot;Show Package Contents&quot;, go to &quot;Contents&quot; and open &quot;Info.plist&quot;.

Edit &quot;Info.plist&quot; to contain this xml code within the outer dict element. For an example, download the app bundle above.
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&amp;lt;key&amp;gt;CFBundleIdentifier&amp;lt;/key&amp;gt;
        &amp;lt;string&amp;gt;nl.pepijndevos.urlhandler&amp;lt;/string&amp;gt;
        &amp;lt;key&amp;gt;CFBundleURLTypes&amp;lt;/key&amp;gt;
        &amp;lt;array&amp;gt;
                &amp;lt;dict&amp;gt;
                        &amp;lt;key&amp;gt;CFBundleURLName&amp;lt;/key&amp;gt;
                        &amp;lt;string&amp;gt;Applescript urls&amp;lt;/string&amp;gt;
                        &amp;lt;key&amp;gt;CFBundleURLSchemes&amp;lt;/key&amp;gt;
                        &amp;lt;array&amp;gt;
                                &amp;lt;string&amp;gt;http&amp;lt;/string&amp;gt;
                                &amp;lt;string&amp;gt;https&amp;lt;/string&amp;gt;
                                &amp;lt;string&amp;gt;file&amp;lt;/string&amp;gt;
                        &amp;lt;/array&amp;gt;
                        &amp;lt;key&amp;gt;LSIsAppleDefaultForScheme&amp;lt;/key&amp;gt;
                        &amp;lt;true/&amp;gt;
                &amp;lt;/dict&amp;gt;
        &amp;lt;/array&amp;gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

Now, when you click an url it will just open your browser. I'm not sure what to do exactly, but here is what I did
&lt;ol&gt;
	&lt;li&gt;Run the app once&lt;/li&gt;
	&lt;li&gt;Set it as the default browser in Safari&lt;/li&gt;
&lt;/ol&gt;
[update]

Using Linux? Try this script on &lt;a href=&quot;http://www.humbug.in/2010/open-links-in-your-linux-distros-current-browser-instead-of-the-default/&quot;&gt;Humbug.in&lt;/a&gt;

This script has also appeared on &lt;a href=&quot;http://lifehacker.com/5533695/open-links-in-your-macs-current-browser-instead-of-the-default&quot;&gt;lifehacker.com&lt;/a&gt; &lt;a href=&quot;http://mac.softpedia.com/get/Internet-Utilities/Browser-Loader.shtml&quot;&gt;download.com&lt;/a&gt; and &lt;a href=&quot;http://www.macosxhints.com/article.php?story=20100503134708927&quot;&gt;maxosxhints.com&lt;/a&gt;
</content>
		
		<category term="applescript" />
		
		<category term="cfbundleurlschemes" />
		
		<category term="chrome" />
		
		<category term="developer" />
		
		<category term="firefox" />
		
		<category term="opera" />
		
		<category term="safari" />
		
		<category term="webbrowser" />
		
	</entry>
	
	<entry>
		<title>Top 5 multi-protocol IM clients for Mac</title>
		<link href="http://pepijndevos.nl/2010/04/top-5-multi-protocol-im-clients-for-mac/index.html"/>
		<updated>2010-04-21T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/04/top-5-multi-protocol-im-clients-for-mac/2010-04-top-5-multi-protocol-im-clients-for-mac</id>
		<content type="html">Among the few applications I use constantly is my IM client. Just like my web browser, I constantly seek better and faster IM applications.

With browsers there are a few big ones and everyone knows them, for IM on Mac however, you have to take a close look to find something that suits your needs.

Since I've done a lot of this searching, I'm going to do a list of my favorites. If I missed your favorite, pleas leave a comment.
&lt;h4&gt;
&lt;img src=&quot;/images/media_httppepijncqhos_wDJjh.png&quot; alt=&quot;Top 5 multi-protocol IM clients for Mac&quot; /&gt;&lt;a href=&quot;http://adium.im&quot;&gt;Adium&lt;/a&gt;
&lt;/h4&gt;
One of the most used IM clients on Mac. Adium is an application based on the same technologies that power the popular Pidgin client, but offers a native Cocoa interface and a wealth of plugins and customizations, listed at their &lt;a href=&quot;http://www.adiumxtras.com/&quot;&gt;extras pages&lt;/a&gt;. The &lt;a href=&quot;http://adium.im/beta/&quot;&gt;1.4 beta&lt;/a&gt; supports some additional cool features, but due to a lack of manpower is still not done. I recommend using the beta, as it is quite stable.
&lt;h4&gt;
&lt;img src=&quot;/images/media_httppepijncqhos_EkgxI.png&quot; alt=&quot;Top 5 multi-protocol IM clients for Mac&quot; /&gt;&lt;a href=&quot;http://apple.com/macosx/features/ichat.html&quot;&gt;iChat&lt;/a&gt;
&lt;/h4&gt;
The chat client included with Mac OS X, it supports only the XMPP and AIM protocols, but I consider it one of the best if you don't need other protocols. It is possible to use other protocols via a &lt;a href=&quot;http://mac.appstorm.net/how-to/internet-howto/using-multiple-im-protocols-with-ichat/&quot;&gt;XMPP transport&lt;/a&gt;, but this very is unreliable at times.
&lt;h4&gt;
&lt;img src=&quot;/images/media_httppepijncqhos_zsIyu.png&quot; alt=&quot;Top 5 multi-protocol IM clients for Mac&quot; /&gt;&lt;a href=&quot;http://www.trillian.im/learn/tour-mac.html&quot;&gt;Trillian&lt;/a&gt;
&lt;/h4&gt;
Is a well known Windows client that has recently released an alpha version for Mac. It is not very feature rich yet, but it looks and works nice so far. One downside of Trillian is that it stores your credentials in a central account on their server, one of the upsides of Trillian is that it stores all your credentials in a central account, which is cool if you use Trillian on multiple computers/phones.
&lt;h4&gt;
&lt;img src=&quot;/images/media_httppepijncqhos_cbeDy.png&quot; alt=&quot;Top 5 multi-protocol IM clients for Mac&quot; /&gt;&lt;a href=&quot;http://www.pidgin.im/&quot;&gt;Pidgin&lt;/a&gt;
&lt;/h4&gt;
This app is mainly aimed at Linux and Windows users, but with a little help of my &lt;a href=&quot;http://pepijn.cqhosting.nl/2010/04/mac4lin-on-mac/&quot;&gt;previous post&lt;/a&gt; you can get it to work on Mac quite nicely. It uses the same technology as Adium, but due to a broader audience it might offer some features not currently present in Adium. Only use this if you know you need it, Adium has a nicer interface on Mac.
&lt;h4&gt;
&lt;img src=&quot;/images/media_httppepijncqhos_mfpos.png&quot; alt=&quot;Top 5 multi-protocol IM clients for Mac&quot; /&gt;&lt;a href=&quot;http://messenger.yahoo.com/&quot;&gt;Yahoo Messenger&lt;/a&gt;
&lt;/h4&gt;
Contrary to what you might think Yahoo also supports WLM, provides a good Mac look and a full set of features, unlike some other branded clients. It's not the ideal thing though for the real IM diehard.
&lt;h4&gt;Conclusion&lt;/h4&gt;
I'd go with Adium if you're a regular user, or iChat if you don't need any of those networks.

For the experimental people, Trillian and Pidgin might be good options.

For the social network people it might be worth waiting for &lt;a href=&quot;https://mozillalabs.com/raindrop&quot;&gt;Raindrop&lt;/a&gt; or &lt;a href=&quot;http://www.digsby.com/&quot;&gt;Digsby&lt;/a&gt;.

For the WLM oriented minds, the &lt;a href=&quot;http://www.microsoft.com/Mac/products/messenger/default.mspx&quot;&gt;official WLM client&lt;/a&gt;, &lt;a href=&quot;http://mercury.im/&quot;&gt;Mercury&lt;/a&gt; and &lt;a href=&quot;http://www.amsn-project.net/&quot;&gt;aMSN&lt;/a&gt; might be of interest.
</content>
		
		<category term="adium" />
		
		<category term="ichat" />
		
		<category term="instantmessaging" />
		
		<category term="macosx" />
		
		<category term="pidgin" />
		
		<category term="trillian" />
		
		<category term="yahoomessenger" />
		
	</entry>
	
	<entry>
		<title>display: inline-block; tricks</title>
		<link href="http://pepijndevos.nl/2010/04/display-inline-block-tricks/index.html"/>
		<updated>2010-04-14T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/04/display-inline-block-tricks/2010-04-display-inline-block-tricks</id>
		<content type="html">In most cases where you want to have a set of items on one row, you use floats to make things work. The truth is, floats are not meant to do this and they create all sorts of strange behavior, even in good browsers if you don't know what you're doing.

&lt;a href=&quot;http://blog.mozilla.com/webdev/2009/02/20/cross-browser-inline-block/&quot;&gt;This article tells an interesting story on how you could use inline-block in all major browsers.&lt;/a&gt;

I want to add a few tricks to the mix I learned in the past few years.

Use case 1: You want a horizontal menu with more items than fit on the screen, but with a flexible width. Floats are not up to the job; They would just wrap to the next line instead of creating a scrollbar.

Use case 2: You want to center something vertically. You could use a mix of position and margin statements to achieve this, but not if you don't know the width and height of the object.

&lt;strong&gt;Since the elements are in the text flow now, we can apply text-specific CSS!&lt;/strong&gt;

The first example is achieved by setting whitespace: no-wrap; and overflow: auto; which makes all the items stay on one line and create a scroll bar.

The second example is achieved by adding &amp;amp;zwnj; before the item to make it behave like a real line of text, that has vertical-align: middle; applied to it.
&lt;p style=&quot;text-align: center; font-size: 2em;&quot;&gt;&lt;a href=&quot;http://pepijn.cqhosting.nl/projects/inline-block/&quot;&gt;Examples&lt;/a&gt;&lt;/p&gt;
</content>
		
		<category term="css" />
		
		<category term="horizontalmenu" />
		
		<category term="inlineblock" />
		
		<category term="verticalalign" />
		
	</entry>
	
	<entry>
		<title>Control the mouse with a joystick</title>
		<link href="http://pepijndevos.nl/2010/04/control-the-mouse-with-a-joystick/index.html"/>
		<updated>2010-04-12T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/04/control-the-mouse-with-a-joystick/2010-04-control-the-mouse-with-a-joystick</id>
		<content type="html">When I made PyMouse I did so because I had the idea to make an &lt;a href=&quot;http://metapep.wordpress.com/2009/07/11/ipod-touch-wifi-mouse-with-python-web-app/&quot;&gt;iPhone mouse&lt;/a&gt;. Today I had another crazy idea for moving the mouse: &lt;strong&gt;with a joystick!&lt;/strong&gt;

It turns out it's quite easy to use the joystick via &lt;a href=&quot;http://www.pygame.org/&quot;&gt;PyGame&lt;/a&gt;, so that is what I did this evening.

I plugged in the joystick from my brother, copied some &lt;a href=&quot;http://theironlion.net/archive/making-hid-devices-easier-using-pygame-joysticks/&quot;&gt;PyGame example&lt;/a&gt;, imported my own &lt;a href=&quot;http://github.com/pepijndevos/PyMouse&quot;&gt;PyMouse&lt;/a&gt; module and here is the result. You might need to tweak it a little to make it work with your joystick or game controller.


&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pygame&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pymouse&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyMouse&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# edit this to reflect your joystick axis and buttons&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;y&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;multiplier&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;left&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;right&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;pygame&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pygame&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;joystick&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Joystick&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# first joystick&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyMouse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;Initialized Joystick : &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;pygame&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pump&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# check if any button state has changed and change mouse state accordingly&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;left&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;left press&amp;quot;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;press&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;left&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;left release&amp;quot;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;right&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;right press&amp;quot;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;press&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;right&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;right release&amp;quot;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;c&quot;&gt;# get_axis returns a value between -1 and 1&lt;/span&gt;
            &lt;span class=&quot;c&quot;&gt;# fumble a bit here to reverse axis&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_axis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_axis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;multiplier&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_axis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;y&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_axis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;multiplier&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

</content>
		
		<category term="joystick" />
		
		<category term="mouse" />
		
		<category term="pygame" />
		
		<category term="pymouse" />
		
	</entry>
	
	<entry>
		<title>Delicious bookmarks in Safari</title>
		<link href="http://pepijndevos.nl/2010/04/delicious-bookmarks-in-safari/index.html"/>
		<updated>2010-04-10T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/04/delicious-bookmarks-in-safari/2010-04-delicious-bookmarks-in-safari</id>
		<content type="html">I recently started using &lt;a href=&quot;http://delicious.com/pepijndevos&quot;&gt;Delicious&lt;/a&gt;, and while they have a nice Firefox plugin and a bunch of bookmarklets, there is no easy way to get Delicious bookmarks into the Safari bookmarks bar.

To get this done I wrote an Applescript with a little piece of Python to get Delicious bookmarks right in Safari. Here is how it looks:

&lt;img src=&quot;/images/media_httppepijncqhos_uHCgF.png&quot; alt=&quot;Delicious bookmarks in Safari&quot; /&gt;
Here is how to do it:
&lt;ol&gt;
	&lt;li&gt;Get the 2 scripts below and save them to a suitable location. You might want to place it in ~/Library/Scripts/Applications/Safari&lt;/li&gt;
	&lt;li&gt;Edit the Applescript with the location of the Python script and the URL of your Delicious feed.&lt;/li&gt;
	&lt;li&gt;Run the Applescript.&lt;/li&gt;
	&lt;li&gt;Drag the resulting bookmarks folder or its content anywhere you want.&lt;/li&gt;
&lt;/ol&gt;
This will work for any RSS and maybe even Atom feed, you could even bookmark the feed of your Twitter account, for... *hum* easy access to individual tweets.

This is the Python code:
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;import feedparser
print &amp;quot;&amp;lt;dl&amp;gt;&amp;quot;
for e in feedparser.parse( &amp;quot;http://feeds.delicious.com/v2/rss/pepijndevos&amp;quot; ).entries:
    print '&amp;lt;dt&amp;gt;&amp;lt;a href=&amp;quot;%s&amp;quot;&amp;gt;%s&amp;lt;/dt&amp;gt;' % (e.link, e.title.encode('ascii','ignore'))
print &amp;quot;&amp;lt;/dl&amp;gt;&amp;quot;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

Don't ask me why, but Safari needs broken html to import. Maybe because it is meant to import IE bookmarks? Anyway, this is the Applescript, the real thing:
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;do shell script &amp;quot;python ~/bin/feed2html.py &amp;gt; ~/Documents/delicious.html&amp;quot;
tell application &amp;quot;Safari&amp;quot;
        activate
        tell application &amp;quot;System Events&amp;quot;
                tell application process &amp;quot;Safari&amp;quot;
                        click menu item &amp;quot;Import Bookmarks…&amp;quot; of menu &amp;quot;File&amp;quot; of menu bar item &amp;quot;File&amp;quot; of menu bar 1
                        keystroke &amp;quot;g&amp;quot; using {shift down, command down}
                        keystroke &amp;quot;~/Documents/delicious.html&amp;quot;
                        keystroke return
                        keystroke return
                end tell
        end tell
end tell&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
</content>
		
		<category term="applescript" />
		
		<category term="bookmark" />
		
		<category term="delicious" />
		
		<category term="python" />
		
		<category term="safari" />
		
	</entry>
	
	<entry>
		<title>PyMouse 1.0: Mouse control and events on Python</title>
		<link href="http://pepijndevos.nl/2010/04/pymouse-mouse-control-and-events-on-python/index.html"/>
		<updated>2010-04-09T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/04/pymouse-mouse-control-and-events-on-python/2010-04-pymouse-mouse-control-and-events-on-python</id>
		<content type="html">Since the first release of &lt;a href=&quot;http://github.com/pepijndevos/PyMouse&quot;&gt;PyMouse&lt;/a&gt; I received a lot of feature requests. A list of all requests ordered by quantity:
&lt;ol&gt;
	&lt;li&gt;Receive mouse events&lt;/li&gt;
	&lt;li&gt;Keyboard support&lt;/li&gt;
&lt;/ol&gt;
Digging around in platform specific APIs is not my favorite hobby, but when Aldo came to me with a &lt;a href=&quot;http://github.com/krahser/PyMouse/blob/master/unix.py#L37&quot;&gt;good start for the Unix code&lt;/a&gt;, and copyrights send me &lt;a href=&quot;http://gist.github.com/361212&quot;&gt;some Windows code&lt;/a&gt;, I could do nothing but finish my Mac code and adapt everything to a common API.

I'm also very grateful for the help from mailing list members of PyObjC and Python Xlib. Without their help I'd probably have to reverse the current version number.

Keyboard support is not yet there, and I do not currently have time to write it. But I wrote down everything I know about the APIs I worked with on the &lt;a href=&quot;http://wiki.github.com/pepijndevos/PyMouse/&quot;&gt;PyMouse wiki&lt;/a&gt;, so it shouldn't be to hard to figure out for anyone willing to do it.
&lt;p style=&quot;text-align: center; font-size: 2em;&quot;&gt;&lt;a href=&quot;http://github.com/downloads/pepijndevos/PyMouse/PyMouse-1.0.tar.gz&quot;&gt;Download PyMouse&lt;/a&gt;&lt;/p&gt;
</content>
		
		<category term="api" />
		
		<category term="mouseevents" />
		
		<category term="pymouse" />
		
		<category term="python" />
		
	</entry>
	
	<entry>
		<title>Good looking X11 apps on Mac</title>
		<link href="http://pepijndevos.nl/2010/04/mac4lin-on-mac/index.html"/>
		<updated>2010-04-07T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/04/mac4lin-on-mac/2010-04-mac4lin-on-mac</id>
		<content type="html">A while back I discovered that &lt;a href=&quot;http://www.pidgin.im/&quot;&gt;Pidgin&lt;/a&gt; is now available for Mac. The problem is that it is still a GTK app.

For Mac users that means it runs in X11. It has always bothered me that all X11 applications you run on Mac look so extremely ugly.

When I used &lt;a href=&quot;http://www.ubuntu.com/&quot;&gt;Ubuntu&lt;/a&gt; a few years back I discovered &lt;a href=&quot;http://sourceforge.net/projects/mac4lin/&quot;&gt;mac4lin&lt;/a&gt;, a funny project that intends to make a Mac theme for Gnome.

Ironically, since Gnome is based on GTK you can run mac4lin on the system it intends to emulate, which would give your GTK apps a nice Mac look. Let's see how...

For this example I'm also going to install Pidgin, to show you how it looks.

First, however we need to get a bunch of software. You need to have &lt;a href=&quot;http://www.macports.org/&quot;&gt;MacPorts&lt;/a&gt; installed for this to work.
&lt;ol&gt;
	&lt;li&gt;First we need to get GTK without X11. You can leave of the variants if the build fails to get the X11 version.
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;sudo port install gtk2 +quartz +no_x11&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;/li&gt;
	&lt;li&gt;Now we can get Pidgin, or any other GTK2 app.
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;sudo port install pidgin +quartz +no_x11&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;/li&gt;
	&lt;li&gt;To be able to easily switch theme later we also need this little app.
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;sudo port install gtk2-chtheme&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;/li&gt;
	&lt;li&gt;Now download and extract the latest version of mac4lin from &lt;a href=&quot;http://sourceforge.net/projects/mac4lin/&quot;&gt;their website&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;Extract Mac4Lin_GTK_Aqua_v1.0.tar.gz in the GTK folder to /opt/local/share/themes/ (You'll need to authenticate)&lt;/li&gt;
	&lt;li&gt;Run /opt/local/bin/gtk2-chtheme, select the newly installed theme.&lt;/li&gt;
	&lt;li&gt;Click the font button and set it to Lucida Grande at 10pt, done!&lt;/li&gt;
	&lt;li&gt;Run /opt/local/bin/pidgin to see the effect.&lt;/li&gt;
&lt;/ol&gt;
Before:

&lt;img src=&quot;/images/media_httppepijncqhos_ttpFx.png&quot; alt=&quot;Good looking X11 apps on Mac&quot; /&gt;

After:

&lt;img src=&quot;/images/media_httppepijncqhos_xcxaE.png&quot; alt=&quot;Good looking X11 apps on Mac&quot; /&gt;

&lt;strong&gt;Keyboard shortcuts:&lt;/strong&gt; You might also want to use &lt;a href=&quot;http://www.macosxhints.com/article.php?story=20070206110939423&quot;&gt;this hint&lt;/a&gt; to enable the CMD key for keyboard shortcuts.

&lt;strong&gt;Sound:&lt;/strong&gt; By default Pidgin uses you 'system beep' to notify you, solution:
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;sudo port install qtplay&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;img src=&quot;/images/media_httppepijncqhos_HhxmB.png&quot; alt=&quot;Good looking X11 apps on Mac&quot; /&gt;
</content>
		
		<category term="gtk" />
		
		<category term="mac" />
		
		<category term="macports" />
		
		<category term="pidgin" />
		
		<category term="x11" />
		
	</entry>
	
	<entry>
		<title>easy_install: no eggs found</title>
		<link href="http://pepijndevos.nl/2010/04/easy-install-no-eggs-found/index.html"/>
		<updated>2010-04-06T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/04/easy-install-no-eggs-found/2010-04-easy-install-no-eggs-found</id>
		<content type="html">I blogged about this before, but I was bitten by the same issue again! When you run an old version of setuptools and easy_install, you might get an error concerning eggs not being found.

If you're having the same problem, the solution is simple:

  &lt;pre&gt;easy_install -U setuptools&lt;/pre&gt;
</content>
		
		<category term="easy_install" />
		
		<category term="noeggsfound" />
		
		<category term="python" />
		
		<category term="setuptools" />
		
	</entry>
	
	<entry>
		<title>Manage your social networks</title>
		<link href="http://pepijndevos.nl/2010/03/manage-your-social-networks/index.html"/>
		<updated>2010-03-28T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/03/manage-your-social-networks/2010-03-manage-your-social-networks</id>
		<content type="html">I recently had one of my &quot;search for relief&quot; attacks, which means I start to try out a lot of software in search for something better than I already have. This happens a few times a year, and leads to a lot of (remainders of) crap and cool software on my computer.

After I went through the OS(Mac), browser(WebKit), chat(Adium), editor(MacVim) and maybe more, it was time for the &lt;strong&gt;social networks&lt;/strong&gt;.

I have now figured out a set of social networks I like, but that led me to a new problem: &lt;strong&gt;management!&lt;/strong&gt;

An ideal piece of software would be able to manage at least:
&lt;ul&gt;
	&lt;li&gt;Gmail&lt;/li&gt;
	&lt;li&gt;Wordpress&lt;/li&gt;
	&lt;li&gt;Twitter&lt;/li&gt;
	&lt;li&gt;Facebook&lt;/li&gt;
&lt;/ul&gt;
And probably also:
&lt;ul&gt;
	&lt;li&gt;Delicious&lt;/li&gt;
	&lt;li&gt;Flickr&lt;/li&gt;
	&lt;li&gt;Buzz&lt;/li&gt;
&lt;/ul&gt;
&lt;img src=&quot;/images/media_httppepijncqhos_kHshr.png&quot; alt=&quot;Manage your social networks&quot; /&gt;That ideal application would be &lt;a href=&quot;https://mozillalabs.com/raindrop&quot;&gt;Raindrop&lt;/a&gt;, but there is a small problem, it isn't finished yet. I tried very hard, but it would not work for me at this stage.

&lt;img src=&quot;/images/media_httppepijncqhos_BkJJd.jpg&quot; alt=&quot;Manage your social networks&quot; /&gt;Wait a minute... All those services above are websites, aren't they? So, why not use the browser? Because you'd have to open about ten tabs and handle each service separately... Unless you use &lt;a href=&quot;http://www.flock.com/&quot;&gt;Flock&lt;/a&gt;!

Flock is a browser that is based around FireFox, but with social networks built right in the core. This might be your solution, but it is not mine; I like the speed, simplicity and integration of WebKit(developer version of Safari).

My solution is quite the opposite of Flock. I try to use applications for what they are meant to do, and update as much networks as possible on the way, which in practice means &lt;strong&gt;linking&lt;/strong&gt; networks together. Here is my current setup:
&lt;p style=&quot;text-align: left;&quot;&gt;&lt;img src=&quot;/images/media_httppepijncqhos_EdcHC.png&quot; alt=&quot;Manage your social networks&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Let me explain that in more detail. A lot of these services include an option to either read or write to Twitter, and for those that do not write to Twitter there is &lt;a href=&quot;http://twitterfeed.com/&quot;&gt;TwitterFeed&lt;/a&gt; to parse RSS feeds into Tweets.&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Buzz is kind of redundant, but when you click 'connected sites' under Buzz in Gmail it can dupe your Tweets for those that do use it.&lt;/li&gt;
	&lt;li&gt;Facebook is &lt;em&gt;not&lt;/em&gt; just another Twitter, so it might need some extra attention, but you can cover wall updates and photos by adding the &lt;a href=&quot;http://apps.facebook.com/twitter/&quot;&gt;Twitter app&lt;/a&gt; and importing your Flickr photos. To do this
&lt;ol&gt;
	&lt;li&gt;Go to your profile&lt;/li&gt;
	&lt;li&gt;Click 'Options' and then 'Settings' just above your feed&lt;/li&gt;
	&lt;li&gt;Select Flickr&lt;/li&gt;
	&lt;li&gt;Figure out the rest&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
	&lt;li&gt;Flickr can also be used as an Twitter image/video service by adding Twitter as a blog via &lt;a href=&quot;http://www.flickr.com/account/blogs/&quot;&gt;http://www.flickr.com/account/blogs/&lt;/a&gt; and then clicking 'blog this' above any photo. There are numerous Flickr uploaders to use if you want to.&lt;/li&gt;
	&lt;li&gt;Wordpress, Delicious, GitHub or any other service with a feed can be linked to your Twitter with &lt;a href=&quot;http://twitterfeed.com/&quot;&gt;TwitterFeed&lt;/a&gt;. You might choose to install additional software to facile operation of Wordpress and Delicious.&lt;/li&gt;
	&lt;li&gt;Update: By adding 'http://twitter.com/statuses/user_timeline/&amp;lt;username&amp;gt;&lt;strong&gt;&lt;/strong&gt;.rss' to TwitterFeed you can publish Twitter to Identi.ca and some other services as well.&lt;/li&gt;
&lt;/ul&gt;
&lt;img src=&quot;/images/media_httppepijncqhos_Ezspy.png&quot; alt=&quot;Manage your social networks&quot; /&gt;I suggest you browse around my social network a bit and check the 'via' tag to see where the content is coming from. If you are unsure how to connect a certain service, leave a comment, and I'll elaborate on that.

I'm starting to get a little concerned about content duplication, any thoughts about that?
</content>
		
		<category term="buzz" />
		
		<category term="delicious" />
		
		<category term="facebook" />
		
		<category term="flickr" />
		
		<category term="flock" />
		
		<category term="github" />
		
		<category term="rss" />
		
		<category term="socialnetworks" />
		
		<category term="twitter" />
		
		<category term="wordpress" />
		
	</entry>
	
	<entry>
		<title>Tweet-o-Graph</title>
		<link href="http://pepijndevos.nl/2010/03/tweet-o-graph/index.html"/>
		<updated>2010-03-22T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/03/tweet-o-graph/2010-03-tweet-o-graph</id>
		<content type="html">&lt;img src=&quot;/images/media_httppepijncqhos_epdoE.png&quot; alt=&quot;Tweet-o-Graph&quot; /&gt;&lt;a href=&quot;http://metapep.wordpress.com/2009/07/30/get-the-overview-on-what-is-happening-on-twitter-visually/&quot;&gt;Back in 2009&lt;/a&gt; I made a hackish Python script that would generate a graph like the one shown here from your Twitter account.

It turned out few people are willing to fumble with Python scripts to get 'just an image'. &lt;strong&gt;Luckily, I'm releasing a completely rewritten web app for the same cool idea!&lt;/strong&gt;

&lt;a href=&quot;http://tweetograph.pepijn.cqhosting.nl&quot;&gt;tweetograph.pepijn.cqhosting.nl&lt;/a&gt;

Now with support for oauth, mentions, retweets, replies, gif, svg, dot, and a lot more.

It is written with Python and web.py, using &lt;a href=&quot;http://pepijn.cqhosting.nl/2010/03/install-python-on-shared-host/&quot;&gt;this script from my previous post&lt;/a&gt;.
</content>
		
		<category term="graphviz" />
		
		<category term="oauth" />
		
		<category term="python" />
		
		<category term="twitter" />
		
		<category term="webpy" />
		
	</entry>
	
	<entry>
		<title>Cross-domain AJAX POST request -- Twitter client</title>
		<link href="http://pepijndevos.nl/2010/03/cross-domain-ajax-post-request-twitter-client/index.html"/>
		<updated>2010-03-16T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/03/cross-domain-ajax-post-request-twitter-client/2010-03-cross-domain-ajax-post-request-twitter-client</id>
		<content type="html">One of the top items on my web-project-wish-list is a client-side Twitter client written in JavaScript, without resorting to a proxy.
&lt;h3&gt;The problem&lt;/h3&gt;
The technology needed to write web applications is named AJAX, but for security reasons, AJAX has one important limitation!

You can &lt;span style=&quot;text-decoration: underline;&quot;&gt;not&lt;/span&gt; make requests to another domain. Imagine what would happen if a malicious website would request your gmail inbox while you are logged in!
&lt;h3&gt;Alternatives&lt;/h3&gt;
Because of this limitation, people started to look for other ways to make cross-domain request. Bring in &lt;a href=&quot;http://en.wikipedia.org/wiki/JSON#JSONP&quot;&gt;JSONP&lt;/a&gt;!

JSONP allows you to request data from another domain by inserting a script tag with a src attribute referring to the data location. This is used in the Twitter widget showed in my sidebar.

JSONP has two limitations.
&lt;ol&gt;
	&lt;li&gt;You give the other domain scripting access to your site, opening a potential XSS vulnerability.&lt;/li&gt;
	&lt;li&gt;You can only make a GET request.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;iframes&lt;/h3&gt;
Hidden iframes are another method to make asynchronous requests, but they to are limited to GET requests and are only accessible from the same domain.

I have not yet found a solution for the access problem, but I &lt;em&gt;can&lt;/em&gt; make POST requests.
&lt;h3&gt;The solution&lt;/h3&gt;
&lt;ol&gt;
	&lt;li&gt;Make an iframe and set its display property to hidden.&lt;/li&gt;
	&lt;li&gt;Load a page in the frame containing a form.&lt;/li&gt;
	&lt;li&gt;Add hidden inputs to the form.&lt;/li&gt;
	&lt;li&gt;Submit it!&lt;/li&gt;
&lt;/ol&gt;
Example:
&lt;a&gt;Click here to send a tweet to Twitter about this post!&lt;/a&gt;

&lt;p&gt;&lt;b&gt;iframe removed&lt;/b&gt;&lt;/p&gt;

The only remaining problem is that we can not access the return data, but as you can see, that is not needed in all cases.
</content>
		
		<category term="ajax" />
		
		<category term="clientside" />
		
		<category term="iframe" />
		
		<category term="javascript" />
		
		<category term="jsonp" />
		
		<category term="post" />
		
		<category term="twitter" />
		
	</entry>
	
	<entry>
		<title>Clojure static site generator</title>
		<link href="http://pepijndevos.nl/2010/03/clojure-static-site-generator/index.html"/>
		<updated>2010-03-12T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/03/clojure-static-site-generator/2010-03-clojure-static-site-generator</id>
		<content type="html">Ever wondered why systems like Wordpress &lt;em&gt;generate&lt;/em&gt; the whole page every time a visitor comes around? I did, and I'm not the only one. There are numerous static site generators and caching plugins around, and this is one of the former.

First I wanted to write a static site generator in Python, but there is already one. I started to learn Clojure, and met defn on the Clojure IRC channel, who also wanted to write a Clojure static site generator.

We started coding, and that is how Utterson came to life. I must admit though that I haven't heard very much of defn since the start of the project.

Utterson works by threading Markdown files through Clojure template files to generate static HTML files. Other files(images, etc.) are copied as-is.
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;java -jar utterson.jar src dest&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

The project is currently in a state in which it works, but it would make for an awkward blog, since there are still some base features missing.

&lt;a href=&quot;http://github.com/pepijndevos/utterson&quot;&gt;http://github.com/pepijndevos/utterson&lt;/a&gt;

For now this blog is going to be using Wordpress, until I finish the generator and find solutions to problems like comments.
</content>
		
		<category term="clojure" />
		
		<category term="markdown" />
		
		<category term="staticsitegenerator" />
		
	</entry>
	
	<entry>
		<title>Three good reasons to run a Webkit Nightly</title>
		<link href="http://pepijndevos.nl/2010/03/three-good-reasons-ton-run-a-webkit-nightly/index.html"/>
		<updated>2010-03-08T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/03/three-good-reasons-ton-run-a-webkit-nightly/2010-03-three-good-reasons-ton-run-a-webkit-nightly</id>
		<content type="html">&lt;ol&gt;
	&lt;li&gt;You get to use the &lt;a href=&quot;http://webkit.org/demos/&quot;&gt;latest an coolest features&lt;/a&gt; around.&lt;/li&gt;
	&lt;li&gt;You can try out my &lt;a href=&quot;http://metapep.wordpress.com/2009/10/27/webkit-feature-test/&quot;&gt;3D CSS browser game&lt;/a&gt;, which is &lt;a href=&quot;http://pepijn.cqhosting.nl/cgi-bin/comet/&quot;&gt;finally online&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;You can see this &lt;a href=&quot;http://pepijn.cqhosting.nl/projects/endlesszoom/&quot;&gt;wacky CSS endless zoom effect&lt;/a&gt;, and &lt;a href=&quot;http://css-vfx.googlecode.com/svn/trunk/examples/zflow_snow.html&quot;&gt;other beautiful show-offs&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
No, seriously... You might not need it for daily web usage, but if you are a developer, it's fun! Get it at &lt;a href=&quot;http://nightly.webkit.org/&quot;&gt;webkit.org&lt;/a&gt;, even the nightly is more reliable than IE6. I'm using it right now to write this.
</content>
		
		<category term="css" />
		
		<category term="webkit" />
		
	</entry>
	
	<entry>
		<title>How to install Python/web.py on a shared host</title>
		<link href="http://pepijndevos.nl/2010/03/install-python-on-shared-host/index.html"/>
		<updated>2010-03-03T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/03/install-python-on-shared-host/2010-03-install-python-on-shared-host</id>
		<content type="html">In the past I have written a few Python web applications, but when I asked my host about Python, they told me they where specialized in PHP and nothing but PHP(that is why this site runs Wordpress).

If your are lucky and have a very expensive dedicated server you can install whatever you want, but how about my poor projects? I'm not going to re-write them in PHP obviously.

I figured that as long as you have a CGI bin, you can do whatever you want. I started writing a CGI script that would install Python and Web.py for me; &lt;a href=&quot;http://pepijn.cqhosting.nl/cgi-bin/python/webpy.cgi/blog-reader&quot;&gt;Check out the resulting web.py example.&lt;/a&gt;

This is the script that I came up with. It should be doable to customize this for Pylons, TurboGears, Django, or any other Python framework.

You should at least fill in your own home directory twice, we're doing a Python installation inside you home directory.
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;#!/bin/sh

echo &amp;quot;Content-type: text/html

&amp;quot;;

curl http://www.python.org/ftp/python/2.6.4/Python-2.6.4.tgz | tar -zx
cd Python-2.6.4
./configure --prefix=/your/home/directory #change this to your home
make
make install
cd ..
curl http://www.saddi.com/software/flup/dist/flup-1.0.2.tar.gz | tar -zx
cd flup-1.0.2
/your/home/directory/bin/python setup.py install
cd ..
curl http://webpy.org/static/web.py-0.33.tar.gz | tar -zx
cp -r web.py-0.33/web .&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

Note that you should add .py as a CGI handler in your .htaccess file:
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;AddHandler cgi-script .py&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

Since our fresh Python installation is not on the PATH variable, you should include a shebang header in your scripts to point to the right path:
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;#!/your/home/directory/bin/python&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;a href=&quot;http://pepijn.cqhosting.nl/cgi-bin/python/webpy.cgi/blog-reader&quot;&gt;Again, check the result!&lt;/a&gt;
</content>
		
		<category term="cgibin" />
		
		<category term="framework" />
		
		<category term="html" />
		
		<category term="php" />
		
		<category term="python" />
		
		<category term="webpy" />
		
		<category term="webhosting" />
		
		<category term="wordpress" />
		
	</entry>
	
	<entry>
		<title>How to navigate the browser ballot screen</title>
		<link href="http://pepijndevos.nl/2010/02/how-to-navigate-the-browser-ballot-screen/index.html"/>
		<updated>2010-02-23T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/02/how-to-navigate-the-browser-ballot-screen/2010-02-how-to-navigate-the-browser-ballot-screen</id>
		<content type="html">&lt;img src=&quot;/images/media_httppepijncqhos_mmCqe.gif&quot; alt=&quot;How to navigate the browser ballot screen&quot; /&gt;

This is my response to the EU/Microsoft browser ballot screen. Honestly, most people don't even know what their browser is, what do you think the difference in IE market share will be?

&lt;a href=&quot;http://xkcd.com/627/&quot;&gt;http://xkcd.com/627/&lt;/a&gt; also applies here.

I recommend any of the five except IE. In case you're wondering, I'm using Safari.
</content>
		
		<category term="browserballot" />
		
		<category term="internetexplorer" />
		
		<category term="xkcd" />
		
	</entry>
	
	<entry>
		<title>Wordpress.com Stats: Top Posts Widget</title>
		<link href="http://pepijndevos.nl/2010/02/wordpress-com-stats-top-posts-widget/index.html"/>
		<updated>2010-02-22T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/02/wordpress-com-stats-top-posts-widget/2010-02-wordpress-com-stats-top-posts-widget</id>
		<content type="html">&lt;img src=&quot;/images/media_httppepijncqhos_tAbIy.jpg&quot; alt=&quot;Wordpress.com Stats: Top Posts Widget&quot; /&gt;This hack is so cool and so simple, I expect anyone to run up to me and yell that this has been done before. I created a 'Top Posts' sidebar widget based on the widget that comes with any &lt;a href=&quot;http://wordpress.com&quot;&gt;Worpdpress.com&lt;/a&gt; blog.

I know there are several widgets like this, but they all include their own statistics tracking. Mine is nothing more than an excerpt of the &lt;em&gt;Dashboard&lt;/em&gt; widget that comes with the &lt;a href=&quot;http://wordpress.org/extend/plugins/stats/&quot;&gt;Wordpress.com Stats&lt;/a&gt; plugin.

For people not interested in technical details, &lt;a href=&quot;http://downloads.wordpress.org/plugin/wordpresscom-stats-top-posts-sidebar-widget.zip&quot;&gt;here is a plugin file&lt;/a&gt;, that works as usual; Make sure you install the &lt;a href=&quot;http://wordpress.org/extend/plugins/stats/&quot;&gt;Wordpress.com Stats&lt;/a&gt; plugin first!

I said this hack was simple, here is way: The code is already there! I'm surprised Wordpress did not include the widget themselves. Lets have a look at stats.php:

Line 925-926:
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;foreach ( $top_posts = stats_get_csv( 'postviews', &amp;quot;days=$options[top]$csv_args[top]&amp;quot; ) as $post )
        $post_ids[] = $post['post_id'];&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

Line 942-949:
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&amp;lt;?php foreach ( $top_posts as $post ) : if ( !get_post( $post['post_id'] ) ) continue; ?&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;?php printf(
        $printf,
        '&lt;a href=&quot;' . get_permalink( $post['post_id'] ) . '&quot;&gt;' . get_the_title( $post['post_id'] ) . '&lt;/a&gt;',
//                        '&lt;a href=&quot;' . $post['post_permalink'] . '&quot;&gt;' . $post['post_title'] . '&lt;/a&gt;',
        number_format_i18n( $post['views'] )
); ?&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;?php endforeach; ?&amp;gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

My resulting guesswork looks like this:
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&amp;lt;h4&amp;gt;Top posts&amp;lt;/h4&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;?php foreach($top_posts = stats_get_csv('postviews', &amp;quot;days=7&amp;quot;) as $post): if(!get_post($post['post_id'])) continue; ?&amp;gt;
        &amp;lt;li&amp;gt;&lt;a href=&quot;&amp;lt;?php echo $post['post_permalink']; ?&amp;gt;&quot;&gt;&lt;/a&gt;&amp;lt;/li&amp;gt;
&amp;lt;?php endforeach; ?&amp;gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;del&gt;If anyone is interested, I can upload this to the Wordpress plugin repository.&lt;/del&gt;
&lt;ins&gt;Done: &lt;a href=&quot;http://wordpress.org/extend/plugins/wordpresscom-stats-top-posts-sidebar-widget/&quot;&gt;http://wordpress.org/extend/plugins/wordpresscom-stats-top-posts-sidebar-widget/&lt;/a&gt;&lt;ins&gt;&lt;/ins&gt;&lt;/ins&gt;
</content>
		
		<category term="plugin" />
		
		<category term="statistics" />
		
		<category term="wordpress" />
		
	</entry>
	
	<entry>
		<title>Food versus code</title>
		<link href="http://pepijndevos.nl/2010/02/food-versus-code/index.html"/>
		<updated>2010-02-21T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/02/food-versus-code/2010-02-food-versus-code</id>
		<content type="html">  &lt;pre&gt;Food: 279kJ/66kcal; E263, E181, E459;
Code: [a-zA-Z0-9]*; hey&lt;/pre&gt;


Now, which one is easier to decipher? Do you think we need simple food, simple code, or both?

For the record, the first food part is from coffee, the ingredients are Calcium acetate, Tannin and Beta-cyclodextrine. The first code part is a regex matching any number of alpha-numeric characters, the second part is 'hey' in html entities.
</content>
		
		<category term="food" />
		
		<category term="html" />
		
		<category term="programming" />
		
		<category term="regularexpression" />
		
	</entry>
	
	<entry>
		<title>Shorten Wordpress urls in Adium</title>
		<link href="http://pepijndevos.nl/2010/02/shorten-wordpress-urls-in-adium/index.html"/>
		<updated>2010-02-20T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/02/shorten-wordpress-urls-in-adium/2010-02-shorten-wordpress-urls-in-adium</id>
		<content type="html">I use &lt;a href=&quot;http://adium.im/&quot;&gt;Adium&lt;/a&gt; as my Twitter client, it includes a nice url shortener supporting multiple services, so what is my problem?

Nothing, I just had some fun making use of the &lt;a href=&quot;http://en.blog.wordpress.com/2009/08/14/shorten/&quot;&gt;wp.me&lt;/a&gt; service. Every Wordpress blog contains a header containing the short url, so it was only 3 lines of Applescript and one line of Bash to get the short url of any wp blog and post it to Adium.

If anyone with knowlegde of regex/grep comes around, he might get it to work with any shorturl/shortlink header.
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;/images/media_httppepijncqhos_HefDB.png&quot; alt=&quot;Shorten Wordpress urls in Adium&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;/p&gt;
The current line looks like this:
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;curl --head &amp;lt;url&amp;gt; -s | grep -o http://wp\.me/[a-zA-Z0-9\-]*&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;strong&gt;Update:&lt;/strong&gt; sed seems to be able to do what I want.
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;curl --head http://pepijn.cqhosting.nl/ -s | \
sed -n 's/Link: &amp;lt;\(.*\)&amp;gt;; rel=shortlink/\1/p'&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

Use:
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;%_shorten{&amp;lt;url&amp;gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

Download the script: &lt;a href=&quot;http://pepijn.cqhosting.nl/subpress/wp-content/uploads/2010/02/shorten.AdiumScripts.zip&quot;&gt;shorten.AdiumScripts&lt;/a&gt;
</content>
		
		<category term="adium" />
		
		<category term="applescript" />
		
		<category term="wordpress" />
		
	</entry>
	
	<entry>
		<title>Cross-domain caching </title>
		<link href="http://pepijndevos.nl/2010/02/cross-domain-caching/index.html"/>
		<updated>2010-02-20T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/02/cross-domain-caching/2010-02-cross-domain-caching</id>
		<content type="html">Looking at the &lt;a href=&quot;http://en.wikipedia.org/wiki/List_of_HTTP_headers&quot;&gt;list of HTTP headers at Wikipedia&lt;/a&gt;, you'll notice a few headers like If-Modified-Since, that serve to send content over only if it has changed since the last request.

While working with JavaScrip frameworks like &lt;a href=&quot;http://jquery.com/&quot; class=&quot;zem_slink&quot; title=&quot;JQuery&quot; rel=&quot;homepage&quot;&gt;jQuery&lt;/a&gt;, the thought occurred to me, that maybe half of all the websites I open are using the exact same JS framework, isn't that a waste of bandwidth?

The best real-life solution would be to get your JS from Google, so you at least share a cached version with others that do the same: &lt;a href=&quot;http://code.google.com/apis/ajaxlibs/&quot;&gt;http://code.google.com/apis/ajaxlibs/&lt;/a&gt;

My imaginary solution however, would allow the same file, served from different hosts to be cached only once.

Look again at the list of headers... We're looking for something to identify files as equal... What about Content-MD5? It exists, right there! But as far as I can tell it's used for content-verification only.

So I want to propose a new HTTP header: If-MD5-Differs

What do you think about it? Cool? Useless? Security issues?
</content>
		
		<category term="cache" />
		
		<category term="hypertexttransferprotocol" />
		
		<category term="listofhttpheaders" />
		
	</entry>
	
	<entry>
		<title>Automatically remove Trash from usb sticks</title>
		<link href="http://pepijndevos.nl/2010/02/automatically-remove-trash-from-usb-sticks/index.html"/>
		<updated>2010-02-19T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/02/automatically-remove-trash-from-usb-sticks/2010-02-automatically-remove-trash-from-usb-sticks</id>
		<content type="html">I think most Mac users have had this problem; You delete a bunch of files from your pen drive to make room for a large file, and it keeps complaining about lack of space.

The problem is that when you remove files on Mac, they're just moved to a hidden folder named '.Trashes', so they are actually still there. A commonly suggested solution is to empty the Trash while the USB stick is plugged in, but this might be problematic in some cases where you want to keep your Trash, just in case...
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;/images/media_httppepijncqhos_alhHD.png&quot; alt=&quot;Automatically remove Trash from usb sticks&quot; /&gt;&lt;/p&gt;
My new solution is to set this little script as a folder action, it will remove the trash &lt;strong&gt;only&lt;/strong&gt; from the USB stick as soon as you mount it(unmount proved problematic).
&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;on adding folder items to this_folder after receiving these_items
    do shell script &amp;quot;rm -rf &amp;quot; &amp;amp; POSIX path of these_items &amp;amp; &amp;quot;.Trashes/&amp;quot;
end adding folder items to&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

Save this script to /Library/Scripts/Folder Action Scripts/ and now set it as the folder action for /Volumes.

&lt;img src=&quot;/images/media_httppepijncqhos_fmjan.png&quot; alt=&quot;Automatically remove Trash from usb sticks&quot; /&gt;

You might need to show hidden files in Finder for /Volumes to be visible. To do this, follow &lt;a href=&quot;http://lifehacker.com/188892/show-hidden-files-in-finder&quot;&gt;this guide&lt;/a&gt;.
</content>
		
		<category term="applescript" />
		
		<category term="filemanagement" />
		
		<category term="macintosh" />
		
		<category term="usbflashdrive" />
		
	</entry>
	
	<entry>
		<title>Write clean code!</title>
		<link href="http://pepijndevos.nl/2010/02/write-clean-code/index.html"/>
		<updated>2010-02-18T00:00:00-08:00</updated>
		<id>tag:pepijndevos.nl,2011:/2010/02/write-clean-code/2010-02-write-clean-code</id>
		<content type="html">&lt;img src=&quot;/images/media_httppepijncqhos_agraJ.jpg&quot; alt=&quot;Write clean code!&quot; /&gt;
</content>
		
		<category term="programming" />
		
	</entry>
	
	<entry>
		<title>Nieuwe website</title>
		<link href="http://pepijndevos.nl/2009/08/nieuwe-website/index.html"/>
		<updated>2009-08-26T00:00:00-07:00</updated>
		<id>tag:pepijndevos.nl,2011:/2009/08/nieuwe-website/2009-08-nieuwe-website</id>
		<content type="html">Hehe, eindelijk, ik heb een eigen website opgezet! Ik had al een tijdje een &lt;a href=&quot;http://metapep.wordpress.com&quot;&gt;wordpress.com&lt;/a&gt; blog, maar nu heb ik een website waar ik &lt;em&gt;wel&lt;/em&gt; alles me kan doen wat ik wil.
</content>
		
		<category term="wordpress" />
		
	</entry>
	
	 
</feed>

