<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/">
  <channel>
    <title>Asymmetrical View</title>
    <atom:link href="http://asymmetrical-view.com/feed/" rel="self" type="application/rss+xml" />
    <link>http://asymmetrical-view.com/</link>
    <description>Seeking no barriers to abstraction</description>
    <pubDate>2012-01-18T09:02:12-05:00</pubDate>

    <generator>http://asymmetrical-view.com/</generator>
    <language>en</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>

    
    <item>
      <title>Look Ma, No Threads!</title>
      <link>http://asymmetrical-view.com/2011/10/15/look-ma-no-threads.html</link>
      <comments>http://asymmetrical-view.com/2011/10/15/look-ma-no-threads.html#comments</comments>

      <pubDate>2011-10-15T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2011/10/15/look-ma-no-threads.html</guid>

      <id>http://asymmetrical-view.com/2011/10/15/look-ma-no-threads</id>
      <description><![CDATA[<h1>Look Ma, No Threads!</h1>
<p>Java&#8217;s <span class="caps">NIO</span>, node.js, Netty, Tornado, Twisted, Perl&#8217;s <span class="caps">POE</span>&#8230;they all have in common one thing: non-blocking IO.</p>
<p>Node.js is based on V8.  V8 is a JavaScript implementation.  It comes form a place (the Browser) where blocking is anathema.  It&#8217;s just not permitted.  You can&#8217;t block the browser.  Node.js&#8217; community follows this to its core: thou shall not block.  Ever.  It permeates its culture and all the software the community accepts.  If something blocks, well, sorry, but it&#8217;s going to be rejected by the community.</p>
<p>This is why the approach isn&#8217;t as strong in the cultures of Python, Java and even Perl.  They&#8217;re all willing, in fact its the default, to accept blocking operations.  They see threads where the Node community sees non-blocking.</p>
<p>epoll?  kpoll? select?  If your goal is to learn about non-blocking IO, you can start simpler than that.  You can start with a basic C program interacting with stdin and stdout.  Consider:</p>
<pre class="code">
/* first.c */
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;memory.h&gt;

char* int_to_binary_ascii( int x ) {
  static char buff[8*sizeof(int) + 1];
  unsigned int ii, num_bits = (8 * sizeof(unsigned int));
  memset(buff,'\0',sizeof(buff));
  for ( ii = 0; ii &lt; num_bits; ii++ ) {
    buff[num_bits - ii - 1] = ( x &amp; (1 &lt;&lt; ii ) ) ? '1' : '0';
  }
  return buff;
}

/* Use a terminal escape to clear the line...*/
void clear_line () {
  printf("%c[2K\r", 27);
}

int main (void) {
  long ii;
  for ( ii=0;; ++ii ) {
    clear_line();
    printf("% 10ld: %s",ii, int_to_binary_ascii(ii));
    fflush(stdout);
  }
  return 0;
}
</pre>
<p>This program is a tight (infinite) loop printing out a counter as an integer and the counter represented as a string of ones and zeros.  It&#8217;s mesmerizing to watch the ones march ever more slowly to the left isn&#8217;t it?  If you run it, you should see output something like:</p>
<pre class="code">
   2622411: 00000000001010000000001111001011
</pre>
<p>It will print continuously to the same line, clearing it and printing again.  To run this program, lets us a shell script, make a file called <code>run.sh</code>:</p>
<pre class="code">
set -e
set -u
set -x

trap "stty sane" INT TERM EXIT

F="$1"

if [ -e $F ]; then
  SRC=$F
  F=$(basename $F .c)
else
  SRC=$F.c
fi

function compile () {
  gcc -O2 -Werror -Wall -o $2 $1
}

compile $SRC $F
stty raw
./$F
rm $F
</pre>
<p>This script does an important thing that we&#8217;ll need in a moment.  It puts the terminal into raw mode.  This will allow unfiltered (un-cooked or raw) keyboard input to be passed directly to the program.  In sane mode, the shell holds your input until you press enter.  We don&#8217;t want that, we want the characters you type to go immediately to our program as you type them.  We have to use raw mode to make this happen.  When you use this script to run our program, you won&#8217;t be able to stop it with CTRL+C.  You&#8217;ll have to go to another terminal, find out it&#8217;s pid and kill it.  You can do this with something like:</p>
<pre class="code">
kill $(ps aux | grep ./[f]irst | awk '{print $2}')
</pre>
<p>The reason you won&#8217;t be able to use CTRL+C any longer is because of that bit about &#8216;raw&#8217; mode.  In raw mode, the shell allows keyboard input (all of it) to go directly to the program.  In &#8216;sane&#8217;, or normal, mode, keyboard input like CTRL+C or CTRL+Z is handled by the shell.  In the case of CTRL+C, the shell will send a signal to the foreground process: a <span class="caps">SIGINT</span>.  For most programs, like ours, a <span class="caps">SIGINT</span> will kill the process.</p>
<p>The shell script compiles the program, puts the terminal into raw mode, runs the program and then ensures the terminal is returned to &#8216;sane&#8217; mode with the &#8216;trap <span class="caps">EXIT</span>&#8217;.</p>
<p>The program gives us no way to tell it to exit short of killing it.  It would be nice if we could ask it to stop.  We could stop it by waiting for some input:</p>
<pre class="code">
/* second.c */
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;memory.h&gt;
#include &lt;unistd.h&gt;

char* int_to_binary_ascii( int x ) {
  static char buff[8*sizeof(int) + 1];
  unsigned int ii, num_bits = (8 * sizeof(unsigned int));
  memset(buff,'\0',sizeof(buff));
  for ( ii = 0; ii &lt; num_bits; ii++ ) {
    buff[num_bits - ii - 1] = ( x &amp; (1 &lt;&lt; ii ) ) ? '1' : '0';
  }
  return buff;
}

/* Use a terminal escape to clear the line...*/
void clear_line () {
  printf("%c[2K\r", 27);
}

int main (void) {
  long ii;
  char c;
  for ( ii=0;; ++ii ) {
    clear_line();
    printf("% 10ld: %s",ii, int_to_binary_ascii(ii));
    fflush(stdout);
    read(0,&amp;c, sizeof(char));
    if ( 'q' == c ) {
      break;
    }
  }
  return 0;
}
</pre>
<p>This works, kinda.   It certainly exits when we press &#8216;q&#8217;, but the program is blocked awaiting our input.  We can keep pressing keys, but it doesn&#8217;t run without us.  How can we get it to run independently of waiting for input, but react if input is present?  You put stdin in non-blocking mode:</p>
<pre class="code">
/* third.c */
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;memory.h&gt;
#include &lt;unistd.h&gt;
#include &lt;fcntl.h&gt;

char* int_to_binary_ascii( int x ) {
  static char buff[8*sizeof(int) + 1];
  unsigned int ii, num_bits = (8 * sizeof(unsigned int));
  memset(buff,'\0',sizeof(buff));
  for ( ii = 0; ii &lt; num_bits; ii++ ) {
    buff[num_bits - ii - 1] = ( x &amp; (1 &lt;&lt; ii ) ) ? '1' : '0';
  }
  return buff;
}

/* Use a terminal escape to clear the line...*/
void clear_line () {
  printf("%c[2K\r", 27);
}

int main (void) {
  long ii;
  char c;
  int flags = fcntl(0,F_GETFL,0);
  flags |= O_NONBLOCK;
  fcntl(0,F_SETFL,flags);

  for ( ii=0;; ++ii ) {
    clear_line();
    printf("% 10ld: %s",ii, int_to_binary_ascii(ii));
    if ( 1 == read(0,&amp;c, sizeof(char)) ) {
      printf("\r\n");
      printf("You pressed: '%c'\r\n",c);
      fflush(stdout);
      if ( 'q' == c ) {
        break;
      }
    }
    fflush(stdout);
  }
  return 0;
}
</pre>
<p>The key lines are where you see <code>fcntl</code>, where we get the current set of flags for <code>stdin</code> (file descriptor 0), ensure <code>O_NONBLOCK</code> is set in the flags and then set the newly configured flags for stdin.  When you run the program and type a few characters into it, you should see something like:</p>
<pre class="code">
&gt; bash run.sh  third.c
+ trap 'stty sane' INT TERM EXIT
+ F=third.c
+ '[' -e third.c ']'
+ SRC=third.c
++ basename third.c .c
+ F=third
+ compile third.c third
+ gcc -O2 -Werror -Wall -o third third.c
+ stty raw
+ ./third
    343404: 00000000000001010011110101101100
You pressed: 'a'
    390059: 00000000000001011111001110101011
You pressed: 'b'
    416735: 00000000000001100101101111011111
You pressed: 'c'
    466926: 00000000000001110001111111101110
You pressed: 'd'
    490793: 00000000000001110111110100101001
You pressed: 'e'
    529303: 00000000000010000001001110010111
You pressed: 'f'
</pre>
<p>That change allows us to call <code>read</code> &#8211; and now read won&#8217;t block.  In the cases where <code>read</code> is called and there is no input, it returns -1.  If you read the man page for <code>read</code> you&#8217;ll see that it also sets <code>errno</code>, and if we print <code>errno</code>:</p>
<pre class="code">
/* fourth.c */
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;memory.h&gt;
#include &lt;unistd.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;errno.h&gt;

char* int_to_binary_ascii( int x ) {
  static char buff[8*sizeof(int) + 1];
  unsigned int ii, num_bits = (8 * sizeof(unsigned int));
  memset(buff,'\0',sizeof(buff));
  for ( ii = 0; ii &lt; num_bits; ii++ ) {
    buff[num_bits - ii - 1] = ( x &amp; (1 &lt;&lt; ii ) ) ? '1' : '0';
  }
  return buff;
}

/* Use a terminal escape to clear the line...*/
void clear_line () {
  printf("%c[2K\r", 27);
}

int main (void) {
  long ii;
  char c;
  int flags = fcntl(0,F_GETFL,0);
  flags |= O_NONBLOCK;
  fcntl(0,F_SETFL,flags);

  for ( ii=0;; ++ii ) {
    clear_line();
    printf("% 10ld: %s errno:%d",ii, int_to_binary_ascii(ii), errno);
    if ( 1 == read(0,&amp;c, sizeof(char)) ) {
      printf("\r\n");
      printf("You pressed: '%c'\r\n",c);
      fflush(stdout);
      if ( 'q' == c ) {
        break;
      }
    }
    fflush(stdout);
  }
  return 0;
}
</pre>
<p>On my Mac, it prints 35.  If I look in <code>/usr/include/sys/errno.h</code> I see:</p>
<pre class="code">
#define EAGAIN          35              /* Resource temporarily unavailable */
#define EWOULDBLOCK     EAGAIN          /* Operation would block */
</pre>
<p>Which can be taken to mean it would block, if it weren&#8217;t in non-blocking mode that is :)</p>
<h2>Conclusion</h2>
<p>These same techniques can be used on sockets as well as file handles.  This technique is the foundation all of these non-blocking frameworks are built on under the hood.  If you&#8217;re interested in learning more, the next function to study is <code>select</code> (or <code>poll</code>, <code>epoll</code>, or <code>kpoll</code>), which allows you to quickly determine which, of a set of, file handle is has input ready and can be read from, or can be written to, without blocking.</p>
<p>Kyle</p>]]></description>
      <content:encoded><![CDATA[<h1>Look Ma, No Threads!</h1>
<p>Java&#8217;s <span class="caps">NIO</span>, node.js, Netty, Tornado, Twisted, Perl&#8217;s <span class="caps">POE</span>&#8230;they all have in common one thing: non-blocking IO.</p>
<p>Node.js is based on V8.  V8 is a JavaScript implementation.  It comes form a place (the Browser) where blocking is anathema.  It&#8217;s just not permitted.  You can&#8217;t block the browser.  Node.js&#8217; community follows this to its core: thou shall not block.  Ever.  It permeates its culture and all the software the community accepts.  If something blocks, well, sorry, but it&#8217;s going to be rejected by the community.</p>
<p>This is why the approach isn&#8217;t as strong in the cultures of Python, Java and even Perl.  They&#8217;re all willing, in fact its the default, to accept blocking operations.  They see threads where the Node community sees non-blocking.</p>
<p>epoll?  kpoll? select?  If your goal is to learn about non-blocking IO, you can start simpler than that.  You can start with a basic C program interacting with stdin and stdout.  Consider:</p>
<pre class="code">
/* first.c */
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;memory.h&gt;

char* int_to_binary_ascii( int x ) {
  static char buff[8*sizeof(int) + 1];
  unsigned int ii, num_bits = (8 * sizeof(unsigned int));
  memset(buff,'\0',sizeof(buff));
  for ( ii = 0; ii &lt; num_bits; ii++ ) {
    buff[num_bits - ii - 1] = ( x &amp; (1 &lt;&lt; ii ) ) ? '1' : '0';
  }
  return buff;
}

/* Use a terminal escape to clear the line...*/
void clear_line () {
  printf("%c[2K\r", 27);
}

int main (void) {
  long ii;
  for ( ii=0;; ++ii ) {
    clear_line();
    printf("% 10ld: %s",ii, int_to_binary_ascii(ii));
    fflush(stdout);
  }
  return 0;
}
</pre>
<p>This program is a tight (infinite) loop printing out a counter as an integer and the counter represented as a string of ones and zeros.  It&#8217;s mesmerizing to watch the ones march ever more slowly to the left isn&#8217;t it?  If you run it, you should see output something like:</p>
<pre class="code">
   2622411: 00000000001010000000001111001011
</pre>
<p>It will print continuously to the same line, clearing it and printing again.  To run this program, lets us a shell script, make a file called <code>run.sh</code>:</p>
<pre class="code">
set -e
set -u
set -x

trap "stty sane" INT TERM EXIT

F="$1"

if [ -e $F ]; then
  SRC=$F
  F=$(basename $F .c)
else
  SRC=$F.c
fi

function compile () {
  gcc -O2 -Werror -Wall -o $2 $1
}

compile $SRC $F
stty raw
./$F
rm $F
</pre>
<p>This script does an important thing that we&#8217;ll need in a moment.  It puts the terminal into raw mode.  This will allow unfiltered (un-cooked or raw) keyboard input to be passed directly to the program.  In sane mode, the shell holds your input until you press enter.  We don&#8217;t want that, we want the characters you type to go immediately to our program as you type them.  We have to use raw mode to make this happen.  When you use this script to run our program, you won&#8217;t be able to stop it with CTRL+C.  You&#8217;ll have to go to another terminal, find out it&#8217;s pid and kill it.  You can do this with something like:</p>
<pre class="code">
kill $(ps aux | grep ./[f]irst | awk '{print $2}')
</pre>
<p>The reason you won&#8217;t be able to use CTRL+C any longer is because of that bit about &#8216;raw&#8217; mode.  In raw mode, the shell allows keyboard input (all of it) to go directly to the program.  In &#8216;sane&#8217;, or normal, mode, keyboard input like CTRL+C or CTRL+Z is handled by the shell.  In the case of CTRL+C, the shell will send a signal to the foreground process: a <span class="caps">SIGINT</span>.  For most programs, like ours, a <span class="caps">SIGINT</span> will kill the process.</p>
<p>The shell script compiles the program, puts the terminal into raw mode, runs the program and then ensures the terminal is returned to &#8216;sane&#8217; mode with the &#8216;trap <span class="caps">EXIT</span>&#8217;.</p>
<p>The program gives us no way to tell it to exit short of killing it.  It would be nice if we could ask it to stop.  We could stop it by waiting for some input:</p>
<pre class="code">
/* second.c */
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;memory.h&gt;
#include &lt;unistd.h&gt;

char* int_to_binary_ascii( int x ) {
  static char buff[8*sizeof(int) + 1];
  unsigned int ii, num_bits = (8 * sizeof(unsigned int));
  memset(buff,'\0',sizeof(buff));
  for ( ii = 0; ii &lt; num_bits; ii++ ) {
    buff[num_bits - ii - 1] = ( x &amp; (1 &lt;&lt; ii ) ) ? '1' : '0';
  }
  return buff;
}

/* Use a terminal escape to clear the line...*/
void clear_line () {
  printf("%c[2K\r", 27);
}

int main (void) {
  long ii;
  char c;
  for ( ii=0;; ++ii ) {
    clear_line();
    printf("% 10ld: %s",ii, int_to_binary_ascii(ii));
    fflush(stdout);
    read(0,&amp;c, sizeof(char));
    if ( 'q' == c ) {
      break;
    }
  }
  return 0;
}
</pre>
<p>This works, kinda.   It certainly exits when we press &#8216;q&#8217;, but the program is blocked awaiting our input.  We can keep pressing keys, but it doesn&#8217;t run without us.  How can we get it to run independently of waiting for input, but react if input is present?  You put stdin in non-blocking mode:</p>
<pre class="code">
/* third.c */
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;memory.h&gt;
#include &lt;unistd.h&gt;
#include &lt;fcntl.h&gt;

char* int_to_binary_ascii( int x ) {
  static char buff[8*sizeof(int) + 1];
  unsigned int ii, num_bits = (8 * sizeof(unsigned int));
  memset(buff,'\0',sizeof(buff));
  for ( ii = 0; ii &lt; num_bits; ii++ ) {
    buff[num_bits - ii - 1] = ( x &amp; (1 &lt;&lt; ii ) ) ? '1' : '0';
  }
  return buff;
}

/* Use a terminal escape to clear the line...*/
void clear_line () {
  printf("%c[2K\r", 27);
}

int main (void) {
  long ii;
  char c;
  int flags = fcntl(0,F_GETFL,0);
  flags |= O_NONBLOCK;
  fcntl(0,F_SETFL,flags);

  for ( ii=0;; ++ii ) {
    clear_line();
    printf("% 10ld: %s",ii, int_to_binary_ascii(ii));
    if ( 1 == read(0,&amp;c, sizeof(char)) ) {
      printf("\r\n");
      printf("You pressed: '%c'\r\n",c);
      fflush(stdout);
      if ( 'q' == c ) {
        break;
      }
    }
    fflush(stdout);
  }
  return 0;
}
</pre>
<p>The key lines are where you see <code>fcntl</code>, where we get the current set of flags for <code>stdin</code> (file descriptor 0), ensure <code>O_NONBLOCK</code> is set in the flags and then set the newly configured flags for stdin.  When you run the program and type a few characters into it, you should see something like:</p>
<pre class="code">
&gt; bash run.sh  third.c
+ trap 'stty sane' INT TERM EXIT
+ F=third.c
+ '[' -e third.c ']'
+ SRC=third.c
++ basename third.c .c
+ F=third
+ compile third.c third
+ gcc -O2 -Werror -Wall -o third third.c
+ stty raw
+ ./third
    343404: 00000000000001010011110101101100
You pressed: 'a'
    390059: 00000000000001011111001110101011
You pressed: 'b'
    416735: 00000000000001100101101111011111
You pressed: 'c'
    466926: 00000000000001110001111111101110
You pressed: 'd'
    490793: 00000000000001110111110100101001
You pressed: 'e'
    529303: 00000000000010000001001110010111
You pressed: 'f'
</pre>
<p>That change allows us to call <code>read</code> &#8211; and now read won&#8217;t block.  In the cases where <code>read</code> is called and there is no input, it returns -1.  If you read the man page for <code>read</code> you&#8217;ll see that it also sets <code>errno</code>, and if we print <code>errno</code>:</p>
<pre class="code">
/* fourth.c */
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;memory.h&gt;
#include &lt;unistd.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;errno.h&gt;

char* int_to_binary_ascii( int x ) {
  static char buff[8*sizeof(int) + 1];
  unsigned int ii, num_bits = (8 * sizeof(unsigned int));
  memset(buff,'\0',sizeof(buff));
  for ( ii = 0; ii &lt; num_bits; ii++ ) {
    buff[num_bits - ii - 1] = ( x &amp; (1 &lt;&lt; ii ) ) ? '1' : '0';
  }
  return buff;
}

/* Use a terminal escape to clear the line...*/
void clear_line () {
  printf("%c[2K\r", 27);
}

int main (void) {
  long ii;
  char c;
  int flags = fcntl(0,F_GETFL,0);
  flags |= O_NONBLOCK;
  fcntl(0,F_SETFL,flags);

  for ( ii=0;; ++ii ) {
    clear_line();
    printf("% 10ld: %s errno:%d",ii, int_to_binary_ascii(ii), errno);
    if ( 1 == read(0,&amp;c, sizeof(char)) ) {
      printf("\r\n");
      printf("You pressed: '%c'\r\n",c);
      fflush(stdout);
      if ( 'q' == c ) {
        break;
      }
    }
    fflush(stdout);
  }
  return 0;
}
</pre>
<p>On my Mac, it prints 35.  If I look in <code>/usr/include/sys/errno.h</code> I see:</p>
<pre class="code">
#define EAGAIN          35              /* Resource temporarily unavailable */
#define EWOULDBLOCK     EAGAIN          /* Operation would block */
</pre>
<p>Which can be taken to mean it would block, if it weren&#8217;t in non-blocking mode that is :)</p>
<h2>Conclusion</h2>
<p>These same techniques can be used on sockets as well as file handles.  This technique is the foundation all of these non-blocking frameworks are built on under the hood.  If you&#8217;re interested in learning more, the next function to study is <code>select</code> (or <code>poll</code>, <code>epoll</code>, or <code>kpoll</code>), which allows you to quickly determine which, of a set of, file handle is has input ready and can be read from, or can be written to, without blocking.</p>
<p>Kyle</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Cucumber, Gherkin and Multi-line arguments</title>
      <link>http://asymmetrical-view.com/2011/06/02/cucumber-gherkin-and-multiline-arguments.html</link>
      <comments>http://asymmetrical-view.com/2011/06/02/cucumber-gherkin-and-multiline-arguments.html#comments</comments>

      <pubDate>2011-06-02T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2011/06/02/cucumber-gherkin-and-multiline-arguments.html</guid>

      <id>http://asymmetrical-view.com/2011/06/02/cucumber-gherkin-and-multiline-arguments</id>
      <description><![CDATA[<h1>Cucumber, Gherkin and Multi-line arguments</h1>
<p><a href="https://github.com/cucumber/cucumber/wiki/Gherkin">Gherkin</a> is the language of the <a href="http://cukes.info/">Cucumber</a> testing tool uses for describing feature tests.</p>
<p>Writing a test today at $<span class="caps">WORK</span>, we needed to use a multi-line string and had some trouble finding an example in Google&#8230;</p>
<p>I am using Cucumber to test my Twilio based <span class="caps">IVR</span> and <span class="caps">SMS</span> applications.  You can find an example as part of my <a href="https://github.com/kyleburton/twilio-in-ten-minutes">  Twilio in Ten Minutes repo</a>, one of which I&#8217;ve included here:</p>
<script src="https://gist.github.com/1005314.js?file=ccard.feature"></script><p>The Scenario &#8220;I register my card in one step and sign up for all services.&#8221; shows how you embed a multi-line string into Gherkin &#8211; you surround your text with enclosing sets of triple double quotes.</p>
<p>I implemented two steps in my testing framework: the first supports a double quoted, single-line string.  The second supports the multi-line string:</p>
<script src="https://gist.github.com/1005329.js?file=cuke-step-multi-line.rb"></script><p>Note that the matcher for the multi-line string doesn&#8217;t include a capture group.  The multi-line string will end up being passed in anyway, as Gherkin recognizes the triple set of double quotes as the bounding delimiters for the multi-line string and passes it in.</p>
<p>The multi-line string will be passed to your step definition as a single string, which you can use as-is or split apart as I&#8217;m doing in my step definition.  Note that it will include any whitespace indentation present in your feature definition.</p>
<p>This will now make for an easy reminder for myself and hopefully it&#8217;ll show up the next time someone else searches Google for how to use multiline strings.</p>
<p class="meta">Kyle Burton, 06 Jun 2011 &#8211; Philadelphia PA</p>
<p><br /></p>]]></description>
      <content:encoded><![CDATA[<h1>Cucumber, Gherkin and Multi-line arguments</h1>
<p><a href="https://github.com/cucumber/cucumber/wiki/Gherkin">Gherkin</a> is the language of the <a href="http://cukes.info/">Cucumber</a> testing tool uses for describing feature tests.</p>
<p>Writing a test today at $<span class="caps">WORK</span>, we needed to use a multi-line string and had some trouble finding an example in Google&#8230;</p>
<p>I am using Cucumber to test my Twilio based <span class="caps">IVR</span> and <span class="caps">SMS</span> applications.  You can find an example as part of my <a href="https://github.com/kyleburton/twilio-in-ten-minutes">  Twilio in Ten Minutes repo</a>, one of which I&#8217;ve included here:</p>
<script src="https://gist.github.com/1005314.js?file=ccard.feature"></script><p>The Scenario &#8220;I register my card in one step and sign up for all services.&#8221; shows how you embed a multi-line string into Gherkin &#8211; you surround your text with enclosing sets of triple double quotes.</p>
<p>I implemented two steps in my testing framework: the first supports a double quoted, single-line string.  The second supports the multi-line string:</p>
<script src="https://gist.github.com/1005329.js?file=cuke-step-multi-line.rb"></script><p>Note that the matcher for the multi-line string doesn&#8217;t include a capture group.  The multi-line string will end up being passed in anyway, as Gherkin recognizes the triple set of double quotes as the bounding delimiters for the multi-line string and passes it in.</p>
<p>The multi-line string will be passed to your step definition as a single string, which you can use as-is or split apart as I&#8217;m doing in my step definition.  Note that it will include any whitespace indentation present in your feature definition.</p>
<p>This will now make for an easy reminder for myself and hopefully it&#8217;ll show up the next time someone else searches Google for how to use multiline strings.</p>
<p class="meta">Kyle Burton, 06 Jun 2011 &#8211; Philadelphia PA</p>
<p><br /></p>]]></content:encoded>
    </item>
    
    <item>
      <title>Simple Process Coordination with Tellmewhen</title>
      <link>http://asymmetrical-view.com/2011/04/26/simple-process-coordination-with-tellmewhen.html</link>
      <comments>http://asymmetrical-view.com/2011/04/26/simple-process-coordination-with-tellmewhen.html#comments</comments>

      <pubDate>2011-04-26T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2011/04/26/simple-process-coordination-with-tellmewhen.html</guid>

      <id>http://asymmetrical-view.com/2011/04/26/simple-process-coordination-with-tellmewhen</id>
      <description><![CDATA[<h1>Simple Process Coordination with Tellmewhen</h1>
<p>I subscribe to the <a href="http://c2.com/cgi/wiki?UnixIsAnIde">Unix is my <span class="caps">IDE</span></a> philosophy, mixing and matching the <a href="http://www.gnu.org/software/coreutils/manual/coreutils.html">gnu tools</a>, <a href="https://github.com/technomancy/leiningen">Leiningen</a>, and lots of other tools.  I frequently go to <a href="http://www.gnu.org/software/bash/">bash</a>, <a href="http://www.ruby-lang.org/en/">Ruby</a> and <a href="http://rake.rubyforge.org/">Rake</a> in order to tie or glue many of those tools together in ad-hoc combinations to get tasks done or create small automations.</p>
<p>I often want is to be notified when a task completes, or to trigger an action after another task completes.  <code>bash</code> has some features that allow you to background a process and await the completion of that process, like <a href="http://linux.die.net/man/1/wait">wait</a>, but <code>wait</code> doesn&#8217;t fit all of my use cases.</p>
<p>I recently checked out <a href="http://technomancy.us/">Phil Hagelberg&#8217;s</a> <a href="https://github.com/technomancy/slamhound/">Slamhound</a> dependency analysis and cleanup tool for <a href="http://clojure.org">Clojure</a> to troubleshoot an issue I was having.  Not knowing much about Leiningen plug-ins and how to effectively do interactive development with them, I started with the classical development cycle: edit the code (add print statements, make some tweaks); compile and install the code; and run the plug-in.</p>
<p>The disconnect for me was that my test case was in another project wasn&#8217;t part of Slamhound itself, so I was doing the build and install of Slamhound then switching to another tab and executing my test.</p>
<p>I created <a href="https://github.com/kyleburton/tellmewhen">Tellmewhen</a> for exactly this kind of use case.  You can used it to implement a lightweight form of <a href="http://en.wikipedia.org/wiki/Inter-process_communication"><span class="caps">IPC</span></a> using basic bash commands and files.</p>
<p>I stacked together the execution of Leiningen to build the software and then touch a trigger file in my <code>$HOME</code> directory that my other process could then wait on:</p>
<pre class="code">user@host ~/projects/slamhound $ lein deps &amp;&amp; lein install &amp;&amp; touch ~/x</pre>
<p>Meanwhile&#8230;in another terminal, I used <code>tellmewhen</code> to await the update to the file <code>~/x</code> and then execute my test:</p>
<pre class="code">user@host ~/personal/projects/impresario $ tellmewhen -m ~/x ; lein deps &amp;&amp; lein slamhound src/impresario/core.clj</pre>
<p>I could run this first (or just after I started the slamhound build) and it would (almost) immediately kick off when the slamhound install successfully completes.</p>
<p>This was a lightweight way for me to script and coordinate between these activities.  Automating it one step further was as easy as wrapping a while loop around the test case:</p>
<pre class="code">user@host ~/personal/projects/impresario $ while :; do \
  tellmewhen -m ~/x ; \
  lein deps &amp;&amp; lein slamhound src/impresario/core.clj; \
done</pre>
<p>Then my test case will execute, and await another build + install of slamhound from the other terminal.</p>
<p>The <a href="http://en.wikipedia.org/wiki/Unix_philosophy">Unix philosophy</a> focuses on modularity &#8211; small, re-usable, composable components.  I see parallels to the composability of <a href="http://en.wikipedia.org/wiki/Functional_programming">Functional Programming</a> constructs as well.  <code>tellmewhen</code> is becoming a tool I&#8217;m using more frequently, mixing it into my other tool-set.  I hope you find it useful too.</p>
<p class="meta">Kyle Burton, 04 Apr 2011 &#8211; Philadelphia PA</p>
<p><br /></p>]]></description>
      <content:encoded><![CDATA[<h1>Simple Process Coordination with Tellmewhen</h1>
<p>I subscribe to the <a href="http://c2.com/cgi/wiki?UnixIsAnIde">Unix is my <span class="caps">IDE</span></a> philosophy, mixing and matching the <a href="http://www.gnu.org/software/coreutils/manual/coreutils.html">gnu tools</a>, <a href="https://github.com/technomancy/leiningen">Leiningen</a>, and lots of other tools.  I frequently go to <a href="http://www.gnu.org/software/bash/">bash</a>, <a href="http://www.ruby-lang.org/en/">Ruby</a> and <a href="http://rake.rubyforge.org/">Rake</a> in order to tie or glue many of those tools together in ad-hoc combinations to get tasks done or create small automations.</p>
<p>I often want is to be notified when a task completes, or to trigger an action after another task completes.  <code>bash</code> has some features that allow you to background a process and await the completion of that process, like <a href="http://linux.die.net/man/1/wait">wait</a>, but <code>wait</code> doesn&#8217;t fit all of my use cases.</p>
<p>I recently checked out <a href="http://technomancy.us/">Phil Hagelberg&#8217;s</a> <a href="https://github.com/technomancy/slamhound/">Slamhound</a> dependency analysis and cleanup tool for <a href="http://clojure.org">Clojure</a> to troubleshoot an issue I was having.  Not knowing much about Leiningen plug-ins and how to effectively do interactive development with them, I started with the classical development cycle: edit the code (add print statements, make some tweaks); compile and install the code; and run the plug-in.</p>
<p>The disconnect for me was that my test case was in another project wasn&#8217;t part of Slamhound itself, so I was doing the build and install of Slamhound then switching to another tab and executing my test.</p>
<p>I created <a href="https://github.com/kyleburton/tellmewhen">Tellmewhen</a> for exactly this kind of use case.  You can used it to implement a lightweight form of <a href="http://en.wikipedia.org/wiki/Inter-process_communication"><span class="caps">IPC</span></a> using basic bash commands and files.</p>
<p>I stacked together the execution of Leiningen to build the software and then touch a trigger file in my <code>$HOME</code> directory that my other process could then wait on:</p>
<pre class="code">user@host ~/projects/slamhound $ lein deps &amp;&amp; lein install &amp;&amp; touch ~/x</pre>
<p>Meanwhile&#8230;in another terminal, I used <code>tellmewhen</code> to await the update to the file <code>~/x</code> and then execute my test:</p>
<pre class="code">user@host ~/personal/projects/impresario $ tellmewhen -m ~/x ; lein deps &amp;&amp; lein slamhound src/impresario/core.clj</pre>
<p>I could run this first (or just after I started the slamhound build) and it would (almost) immediately kick off when the slamhound install successfully completes.</p>
<p>This was a lightweight way for me to script and coordinate between these activities.  Automating it one step further was as easy as wrapping a while loop around the test case:</p>
<pre class="code">user@host ~/personal/projects/impresario $ while :; do \
  tellmewhen -m ~/x ; \
  lein deps &amp;&amp; lein slamhound src/impresario/core.clj; \
done</pre>
<p>Then my test case will execute, and await another build + install of slamhound from the other terminal.</p>
<p>The <a href="http://en.wikipedia.org/wiki/Unix_philosophy">Unix philosophy</a> focuses on modularity &#8211; small, re-usable, composable components.  I see parallels to the composability of <a href="http://en.wikipedia.org/wiki/Functional_programming">Functional Programming</a> constructs as well.  <code>tellmewhen</code> is becoming a tool I&#8217;m using more frequently, mixing it into my other tool-set.  I hope you find it useful too.</p>
<p class="meta">Kyle Burton, 04 Apr 2011 &#8211; Philadelphia PA</p>
<p><br /></p>]]></content:encoded>
    </item>
    
    <item>
      <title>An Interactive Voice Response System in 10 Minutes</title>
      <link>http://asymmetrical-view.com/2011/02/20/twilio-in-ten-minutes.html</link>
      <comments>http://asymmetrical-view.com/2011/02/20/twilio-in-ten-minutes.html#comments</comments>

      <pubDate>2011-02-20T00:00:00-05:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2011/02/20/twilio-in-ten-minutes.html</guid>

      <id>http://asymmetrical-view.com/2011/02/20/twilio-in-ten-minutes</id>
      <description><![CDATA[<link rel="stylesheet" href="/css/guide.css" />
<h1>An Interactive Voice Response System in 10 Minutes</h1>
<p>In this post I&#8217;m going to walk you through deploying a telephony application.  If you&#8217;ve ever called an automated system, listened to a menu and then pressed 1 to continue then you&#8217;ve interacted with a telephony application.</p>
<p>By following this guide you&#8217;ll deploy an application that you can call from your own phone that will read a random quote to you, allow you to repeat repeat the quote (by pressing 1) then disconnect (by pressing 2).</p>
<p>I must make many assumptions about you, the reader of this guide, in order to achieve the goal set by the title of this guide.  If you meet my assumptions then I hope that you&#8217;ll be able to get your first applicaiton up and running in a very, very short time.</p>
<p>If you&#8217;re a developer and you have a Ruby on Rails environment set up, you should be good to go.</p>
<p>If you don&#8217;t, don&#8217;t worry.  I will provide more details about what to do in subsequent posts.  So if you can&#8217;t get your app deployed in 10 min, don&#8217;t despair!  You&#8217;re probably still only a few steps away, look for more details in future posts.  Failing that, drop me (<a href="mailto:kyle.burton@gmail.com">Kyle Burton</a>) a line and I&#8217;ll help you work through things.</p>
<p>Anxious to pick up your phone and call your application?  Then lets get &#8217;er done!</p>
<h1>Deploing your First Application</h1>
<div class="pre-requisite shadow">Get Your App Deployed and Call it! <img src="/images/2011-02/goal.png" class="pre-req-img" alt="" /></div>
<p>We&#8217;re going to make and deploy an application that you can call with your phone and it will speak to you.  All the parts string together something like this:</p>
<div class="diagram shadow"><img src="/images/2011-02/twilio-to-heroku.png" alt="" /></div>
<h3>1. Sign up for Heroku</h3>
<p><a href="http://heroku.com/">Heroku</a> is a PaaS (<a href="http://en.wikipedia.org/wiki/Platform_as_a_service">Platform as a Service</a>) provider.  They graciously allow you to create an deploy an application for free (as long as it doesn&#8217;t take up many of their resources &#8211; and what you&#8217;re about to do fits that bill).</p>
<p><a href="http://heroku.com/">Click Here</a> to head to their home page and start the process.</p>
<p><img src="/images/2011-02/heroku-1-signup.png" class="shadow" alt="" /></p>
<p><img src="/images/2011-02/heroku-3-signup.png" class="shadow" alt="" /></p>
<p>You should then be shown your &#8216;applications page&#8217;.</p>
<p><img src="/images/2011-02/heroku-4-myapps.png" class="shadow" alt="" /></p>
<h3>Grab The Source Code For This Guide</h3>
<div class="pre-requisite shadow"><img src="/images/2011-02/pre-req.png" class="pre-req-img" alt="" /> You will need Git installed and have a connection to the Internet.</div>
<p><img src="/images/2011-02/git-clone-terminal.png" alt="" /></p>
<p>The <span class="caps">URL</span> to the git repository is: <a href="https://github.com/kyleburton/twilio-in-ten-minutes.git">https://github.com/kyleburton/twilio-in-ten-minutes.git</a></p>
<h3>Install the bundler gem</h3>
<p><img src="/images/2011-02/terminal-install-bundler-gem.png" alt="" /></p>
<h3>Run <code>bundle install</code></h3>
<p><img src="/images/2011-02/terminal-run-bundle-install.png" alt="" /></p>
<h3>Run <code>heroku create</code></h3>
<p>When prompted, enter the credentials you created when you signed up in the earlier step:</p>
<p><img src="/images/2011-02/terminal-run-heroku-create.png" alt="" /></p>
<p>Note your application&#8217;s url, this will be vital for when you sign up for Twilio.  For my example application, as seen in the screenshot above, it is <code>http://warm-wind-609.heroku.com/</code>.  Yours will be different.</p>
<p>Heroku automatically added your application&#8217;s git remote to your local git repository.</p>
<h3>Push the application code to heroku:</h3>
<p><img src="/images/2011-02/terminal-push-to-heroku.png" alt="" /></p>
<h3>Open the App in your Browser</h3>
<p>This is to ensure it&#8217;s working.  Enter the url for your Heroku instance, make sure you append on &#8216;/quote&#8217; so it routes to the right controller.  You should see a random quote:</p>
<p><img src="/images/2011-02/browse-the-heroku-app-to-test-it.png" alt="" /></p>
<h3>Sign up for the Twilio free trial.</h3>
<p><a href="http://twilio.com/">Click Here</a> to head to their main page.</p>
<p><img src="/images/2011-02/twilio-signup-1.png" alt="" /></p>
<p><img src="/images/2011-02/twilio-signup-2.png" alt="" /></p>
<h3>Configure Twilio&#8217;s Voice <span class="caps">URL</span></h3>
<p><img src="/images/2011-02/twilio-config-voice-url.png" alt="" /></p>
<h2>Quick!  Call Your Application!</h2>
<p>You&#8217;ve now got an application deployed on <a href="http://heroku.com/">Heroku</a>, and have integrated it with <a href="http://twilio.com/">Twilio</a>.  When you call The number at Twilio, it will make a call to your applicaiton at Heroku, which will tell it what to say.</p>
<div class="pre-requisite shadow"><img src="/images/2011-02/goal.png" class="pre-req-img" alt="" />  Grab your phone and call your app.  Call the phone number that was on your Twilio account page, enter the <span class="caps">PIN</span> (from the same page) and you should hear your very own application read a random quotation to you.</div>
<h1>Conclusion</h1>
<p>Hopefuly there were no kinks and you have your first application deployed.  In the next post I&#8217;ll walk through how to make changes to the application.</p>
<p class="meta">Kyle Burton, 20 Feb 2011 &#8211; Philadelphia PA</p>]]></description>
      <content:encoded><![CDATA[<link rel="stylesheet" href="/css/guide.css" />
<h1>An Interactive Voice Response System in 10 Minutes</h1>
<p>In this post I&#8217;m going to walk you through deploying a telephony application.  If you&#8217;ve ever called an automated system, listened to a menu and then pressed 1 to continue then you&#8217;ve interacted with a telephony application.</p>
<p>By following this guide you&#8217;ll deploy an application that you can call from your own phone that will read a random quote to you, allow you to repeat repeat the quote (by pressing 1) then disconnect (by pressing 2).</p>
<p>I must make many assumptions about you, the reader of this guide, in order to achieve the goal set by the title of this guide.  If you meet my assumptions then I hope that you&#8217;ll be able to get your first applicaiton up and running in a very, very short time.</p>
<p>If you&#8217;re a developer and you have a Ruby on Rails environment set up, you should be good to go.</p>
<p>If you don&#8217;t, don&#8217;t worry.  I will provide more details about what to do in subsequent posts.  So if you can&#8217;t get your app deployed in 10 min, don&#8217;t despair!  You&#8217;re probably still only a few steps away, look for more details in future posts.  Failing that, drop me (<a href="mailto:kyle.burton@gmail.com">Kyle Burton</a>) a line and I&#8217;ll help you work through things.</p>
<p>Anxious to pick up your phone and call your application?  Then lets get &#8217;er done!</p>
<h1>Deploing your First Application</h1>
<div class="pre-requisite shadow">Get Your App Deployed and Call it! <img src="/images/2011-02/goal.png" class="pre-req-img" alt="" /></div>
<p>We&#8217;re going to make and deploy an application that you can call with your phone and it will speak to you.  All the parts string together something like this:</p>
<div class="diagram shadow"><img src="/images/2011-02/twilio-to-heroku.png" alt="" /></div>
<h3>1. Sign up for Heroku</h3>
<p><a href="http://heroku.com/">Heroku</a> is a PaaS (<a href="http://en.wikipedia.org/wiki/Platform_as_a_service">Platform as a Service</a>) provider.  They graciously allow you to create an deploy an application for free (as long as it doesn&#8217;t take up many of their resources &#8211; and what you&#8217;re about to do fits that bill).</p>
<p><a href="http://heroku.com/">Click Here</a> to head to their home page and start the process.</p>
<p><img src="/images/2011-02/heroku-1-signup.png" class="shadow" alt="" /></p>
<p><img src="/images/2011-02/heroku-3-signup.png" class="shadow" alt="" /></p>
<p>You should then be shown your &#8216;applications page&#8217;.</p>
<p><img src="/images/2011-02/heroku-4-myapps.png" class="shadow" alt="" /></p>
<h3>Grab The Source Code For This Guide</h3>
<div class="pre-requisite shadow"><img src="/images/2011-02/pre-req.png" class="pre-req-img" alt="" /> You will need Git installed and have a connection to the Internet.</div>
<p><img src="/images/2011-02/git-clone-terminal.png" alt="" /></p>
<p>The <span class="caps">URL</span> to the git repository is: <a href="https://github.com/kyleburton/twilio-in-ten-minutes.git">https://github.com/kyleburton/twilio-in-ten-minutes.git</a></p>
<h3>Install the bundler gem</h3>
<p><img src="/images/2011-02/terminal-install-bundler-gem.png" alt="" /></p>
<h3>Run <code>bundle install</code></h3>
<p><img src="/images/2011-02/terminal-run-bundle-install.png" alt="" /></p>
<h3>Run <code>heroku create</code></h3>
<p>When prompted, enter the credentials you created when you signed up in the earlier step:</p>
<p><img src="/images/2011-02/terminal-run-heroku-create.png" alt="" /></p>
<p>Note your application&#8217;s url, this will be vital for when you sign up for Twilio.  For my example application, as seen in the screenshot above, it is <code>http://warm-wind-609.heroku.com/</code>.  Yours will be different.</p>
<p>Heroku automatically added your application&#8217;s git remote to your local git repository.</p>
<h3>Push the application code to heroku:</h3>
<p><img src="/images/2011-02/terminal-push-to-heroku.png" alt="" /></p>
<h3>Open the App in your Browser</h3>
<p>This is to ensure it&#8217;s working.  Enter the url for your Heroku instance, make sure you append on &#8216;/quote&#8217; so it routes to the right controller.  You should see a random quote:</p>
<p><img src="/images/2011-02/browse-the-heroku-app-to-test-it.png" alt="" /></p>
<h3>Sign up for the Twilio free trial.</h3>
<p><a href="http://twilio.com/">Click Here</a> to head to their main page.</p>
<p><img src="/images/2011-02/twilio-signup-1.png" alt="" /></p>
<p><img src="/images/2011-02/twilio-signup-2.png" alt="" /></p>
<h3>Configure Twilio&#8217;s Voice <span class="caps">URL</span></h3>
<p><img src="/images/2011-02/twilio-config-voice-url.png" alt="" /></p>
<h2>Quick!  Call Your Application!</h2>
<p>You&#8217;ve now got an application deployed on <a href="http://heroku.com/">Heroku</a>, and have integrated it with <a href="http://twilio.com/">Twilio</a>.  When you call The number at Twilio, it will make a call to your applicaiton at Heroku, which will tell it what to say.</p>
<div class="pre-requisite shadow"><img src="/images/2011-02/goal.png" class="pre-req-img" alt="" />  Grab your phone and call your app.  Call the phone number that was on your Twilio account page, enter the <span class="caps">PIN</span> (from the same page) and you should hear your very own application read a random quotation to you.</div>
<h1>Conclusion</h1>
<p>Hopefuly there were no kinks and you have your first application deployed.  In the next post I&#8217;ll walk through how to make changes to the application.</p>
<p class="meta">Kyle Burton, 20 Feb 2011 &#8211; Philadelphia PA</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Upcoming Talk: Large Data and Clojure</title>
      <link>http://asymmetrical-view.com/2010/10/19/upcoming-talk.html</link>
      <comments>http://asymmetrical-view.com/2010/10/19/upcoming-talk.html#comments</comments>

      <pubDate>2010-10-19T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2010/10/19/upcoming-talk.html</guid>

      <id>http://asymmetrical-view.com/2010/10/19/upcoming-talk</id>
      <description><![CDATA[<h1>Upcoming Talk: Large Data and Clojure</h1>
<p>I&#8217;ll be giving my <a href="https://github.com/kyleburton/large-data-and-clojure">Large Data and Clojure: the middle ground between <span class="caps">RAM</span> and EC2</a> talk at <a href="http://www.phillylambda.org/">Philly Lambda</a> on November 22nd.  The <span class="caps">RSVP</span> Link is <a href="http://www.doodle.com/k6pqcfmzw8umd8dw">here</a>.</p>
<p>This will be an updated verison of the talk I gave at <a href="http://www.barcampphilly.org/">Barcamp Philly 2010</a>.</p>]]></description>
      <content:encoded><![CDATA[<h1>Upcoming Talk: Large Data and Clojure</h1>
<p>I&#8217;ll be giving my <a href="https://github.com/kyleburton/large-data-and-clojure">Large Data and Clojure: the middle ground between <span class="caps">RAM</span> and EC2</a> talk at <a href="http://www.phillylambda.org/">Philly Lambda</a> on November 22nd.  The <span class="caps">RSVP</span> Link is <a href="http://www.doodle.com/k6pqcfmzw8umd8dw">here</a>.</p>
<p>This will be an updated verison of the talk I gave at <a href="http://www.barcampphilly.org/">Barcamp Philly 2010</a>.</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Sampling a Sequence with Clojure</title>
      <link>http://asymmetrical-view.com/2010/10/19/sampling-a-sequence-with-clojure.html</link>
      <comments>http://asymmetrical-view.com/2010/10/19/sampling-a-sequence-with-clojure.html#comments</comments>

      <pubDate>2010-10-19T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2010/10/19/sampling-a-sequence-with-clojure.html</guid>

      <id>http://asymmetrical-view.com/2010/10/19/sampling-a-sequence-with-clojure</id>
      <description><![CDATA[<h1>Sampling a Sequence with Clojure</h1>
<p>We needed to sample a data set that had around 392 million entries in it.  The first thing we thought of was using the database.  The second thing we thought of was by creating an array of the record IDs (or line numbers), shuffling the array and then selecting those records that matched (via the line number or record id).</p>
<h2><span class="caps">SQL</span></h2>
<p><span class="caps">SQL</span> Databases do support selecting random samples of records.  Looking at <a href="http://www.petefreitag.com/item/466.cfm"><span class="caps">SQL</span> to Select a random row from a database table</a>, most use a variation of the following:</p>
<script src="http://gist.github.com/635316.js"> </script><p>We asked PostgreSQL how expensive this would be on our data set and&#8230;it reported a cost in the hundreds of millions.  We weren&#8217;t too confident that this would execute in any reasonable time frame based on my (limited) understanding of what was required: to generate a random value for each row and then sort the entire set of random values before the sample set could be taken (which would admittedly be fast &#8211; given the sorting has completed).  Testing on a million rows, the database returned results after some time &#8211; thinking of having to scale that up by 2 orders of magnitude resulted in a lot of pessimism.</p>
<p>We started a query using this approach anyway, and then we started discussing and googling for other approaches.</p>
<h2>Shuffle</h2>
<p>If the database was going to be slow at it, would it be any faster if we took the same approach by hand?  Could we do it in memory in the <span class="caps">JVM</span>?</p>
<p>With a 2048M Heap, we tried allocating a long array with enough space to hold 392 million and it resulted in an <span class="caps">OOM</span>.  Going up to a 4096M heap and down to an array of ints, we were able to allocate an array and then populate it with the sequential line numbers in Clojure took about 80 seconds on the box we were working with.</p>
<p>There is a <a href="http://clojure.org/">Clojure</a> function <code>shuffle</code> which under the hood defers to <code>java.util.Collections/shuffle</code>, an optimized shuffle that is supplied with the <span class="caps">JRE</span>.  This version of shuffle would have required us to use non-native arrays and use the wrapper classes &#8211; at these sizes, it would seem, a non-starter.</p>
<p>A pure Java implementation of the array creation and sorting (<a href="http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher Yates / Knuth Shuffle</a>) was pretty easy to create:</p>
<script src="http://gist.github.com/635402.js"> </script><p>And it ran pretty quickly as well at just over a minute (78s).  That still left us with having to now use the result of that operation as a set in order to filter the records from the original data set.</p>
<p>We kept wondering if there wasn&#8217;t a way to do it in a single pass, so we kept googling.  Then we ran across an article that talked about an alternate approach that would allow the set to sampled while it was streamed in a single run: <a href="http://www.javamex.com/tutorials/random_numbers/random_sample.shtml">How to pick a random sample from a list</a></p>
<p>Based on that article we were able to craft an implementation in Clojure that could operate on any other sequence, randomly selecting records from a given prefix of the sequence to hit a target sample size:</p>
<script src="http://gist.github.com/635294.js"> </script><p>We ran it on our 19 Gigabyte file (the 390 million record file) and it ran in under ten minutes!  This didn&#8217;t feel much longer than it took to stream the file through Java&#8217;s IO.  We ended up implementing <code>make-periodic-invoker</code> as a &#8216;throbber&#8217; so we&#8217;d have a progress update &#8211; thanks to the way this approach works, it could estimate the amount completed (and could have estimated the total and time remaining).</p>
<p>The algorithm isn&#8217;t guaranteed to produce the target sample set, though it is very likely to.  As it gets closer to the number of items you wished the sample to be taken from (the <code>population-size</code>), it becomes more and more likely to select elements &#8211; finally reaching a probability of 1 at the last element of the population if it hasn&#8217;t completed the set at that point.</p>
<p>We did a quick analysis of the distribution of the values and things looked great.  We&#8217;re happy to have the new technique and the new library code, you can leverage it as part of the <a href="http://github.com/kyleburton/clj-etl-utils">clj-etl-utils</a> project.</p>
<p class="meta">Kyle Burton, 10 Jun 2010 &#8211; Philadelphia PA</p>
<p><br /></p>]]></description>
      <content:encoded><![CDATA[<h1>Sampling a Sequence with Clojure</h1>
<p>We needed to sample a data set that had around 392 million entries in it.  The first thing we thought of was using the database.  The second thing we thought of was by creating an array of the record IDs (or line numbers), shuffling the array and then selecting those records that matched (via the line number or record id).</p>
<h2><span class="caps">SQL</span></h2>
<p><span class="caps">SQL</span> Databases do support selecting random samples of records.  Looking at <a href="http://www.petefreitag.com/item/466.cfm"><span class="caps">SQL</span> to Select a random row from a database table</a>, most use a variation of the following:</p>
<script src="http://gist.github.com/635316.js"> </script><p>We asked PostgreSQL how expensive this would be on our data set and&#8230;it reported a cost in the hundreds of millions.  We weren&#8217;t too confident that this would execute in any reasonable time frame based on my (limited) understanding of what was required: to generate a random value for each row and then sort the entire set of random values before the sample set could be taken (which would admittedly be fast &#8211; given the sorting has completed).  Testing on a million rows, the database returned results after some time &#8211; thinking of having to scale that up by 2 orders of magnitude resulted in a lot of pessimism.</p>
<p>We started a query using this approach anyway, and then we started discussing and googling for other approaches.</p>
<h2>Shuffle</h2>
<p>If the database was going to be slow at it, would it be any faster if we took the same approach by hand?  Could we do it in memory in the <span class="caps">JVM</span>?</p>
<p>With a 2048M Heap, we tried allocating a long array with enough space to hold 392 million and it resulted in an <span class="caps">OOM</span>.  Going up to a 4096M heap and down to an array of ints, we were able to allocate an array and then populate it with the sequential line numbers in Clojure took about 80 seconds on the box we were working with.</p>
<p>There is a <a href="http://clojure.org/">Clojure</a> function <code>shuffle</code> which under the hood defers to <code>java.util.Collections/shuffle</code>, an optimized shuffle that is supplied with the <span class="caps">JRE</span>.  This version of shuffle would have required us to use non-native arrays and use the wrapper classes &#8211; at these sizes, it would seem, a non-starter.</p>
<p>A pure Java implementation of the array creation and sorting (<a href="http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher Yates / Knuth Shuffle</a>) was pretty easy to create:</p>
<script src="http://gist.github.com/635402.js"> </script><p>And it ran pretty quickly as well at just over a minute (78s).  That still left us with having to now use the result of that operation as a set in order to filter the records from the original data set.</p>
<p>We kept wondering if there wasn&#8217;t a way to do it in a single pass, so we kept googling.  Then we ran across an article that talked about an alternate approach that would allow the set to sampled while it was streamed in a single run: <a href="http://www.javamex.com/tutorials/random_numbers/random_sample.shtml">How to pick a random sample from a list</a></p>
<p>Based on that article we were able to craft an implementation in Clojure that could operate on any other sequence, randomly selecting records from a given prefix of the sequence to hit a target sample size:</p>
<script src="http://gist.github.com/635294.js"> </script><p>We ran it on our 19 Gigabyte file (the 390 million record file) and it ran in under ten minutes!  This didn&#8217;t feel much longer than it took to stream the file through Java&#8217;s IO.  We ended up implementing <code>make-periodic-invoker</code> as a &#8216;throbber&#8217; so we&#8217;d have a progress update &#8211; thanks to the way this approach works, it could estimate the amount completed (and could have estimated the total and time remaining).</p>
<p>The algorithm isn&#8217;t guaranteed to produce the target sample set, though it is very likely to.  As it gets closer to the number of items you wished the sample to be taken from (the <code>population-size</code>), it becomes more and more likely to select elements &#8211; finally reaching a probability of 1 at the last element of the population if it hasn&#8217;t completed the set at that point.</p>
<p>We did a quick analysis of the distribution of the values and things looked great.  We&#8217;re happy to have the new technique and the new library code, you can leverage it as part of the <a href="http://github.com/kyleburton/clj-etl-utils">clj-etl-utils</a> project.</p>
<p class="meta">Kyle Burton, 10 Jun 2010 &#8211; Philadelphia PA</p>
<p><br /></p>]]></content:encoded>
    </item>
    
    <item>
      <title>Clojure and Large Result Sets</title>
      <link>http://asymmetrical-view.com/2010/10/14/clojure-and-large-result-sets.html</link>
      <comments>http://asymmetrical-view.com/2010/10/14/clojure-and-large-result-sets.html#comments</comments>

      <pubDate>2010-10-14T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2010/10/14/clojure-and-large-result-sets.html</guid>

      <id>http://asymmetrical-view.com/2010/10/14/clojure-and-large-result-sets</id>
      <description><![CDATA[<h1>Clojure and Large Result Sets</h1>
<p>I&#8217;ve been working with the very useful <a href="http://richhickey.github.com/clojure-contrib/sql-api.html">clojure.contrib.sql</a>  package.  One wrinkle I&#8217;ve encountered, in an otherwise lazy language, is that the <span class="caps">SQL</span> connections typically are not lazy.  By default they load the entire result set at once &#8211; even if the <code>java.sql.ResultSet</code> is lazily accessed.  This isn&#8217;t an issue with <code>clojure.contrib.sql</code> inasmuch as it is with how the <a href="http://en.wikipedia.org/wiki/Java_Database_Connectivity"><span class="caps">JDBC</span></a> classes are being used.</p>
<p>For many use cases, fetching a handful of rows, a user profile, etc., this a perfectly reasonable default.  When you&#8217;re working with result sets that are larger than will fit into memory this default behavior isn&#8217;t so desirable.</p>
<h2>First Attempt: <code>LIMIT</code> using an Offset</h2>
<p>I like the interface that the contrib library offers &#8211; a lazy sequence of the result set. Since PostgreSQL supports ranges as part of it&#8217;s <span class="caps">SQL</span> (via <code>LIMIT</code>) it would seem that you could just write up a quick chunking function that pulls ranges of records from the table using a lazy approach, while still presenting things as a single stream of records from a single result set.</p>
<script src="http://gist.github.com/626979.js"> </script><p>The first function, <code>get-record-range</code>, simply takes a table name a starting offset and a record count.  It executes a select for the given range and offset.  The second function uses the first to create a lazy sequence, generating the next block of records when the previous block was exhausted.  It includes a check to ensure it terminates when there are no more records.</p>
<p>The only piece missing from the above is our <code>db/exec-sql</code>, which is just a convenience wrapper around <code>clojure.contrib.sql/with-query-results</code> that forces the lazy record sequence (this was not the source of our memory troubles).  <code>db/exec-sql</code> is something I often use to quickly grab the entirety of a result set.</p>
<script src="http://gist.github.com/626997.js"> </script><p>The problem with this approach though, is that using a <code>SELECT *</code> and a <code>LIMIT</code> without an <code>ORDER BY</code> clause doesn&#8217;t guarantee the ordering of the records.  The database (for an example, see <a href="http://www.postgresql.org/docs/9.0/interactive/queries-limit.html">PostgreSQL</a>) is free to return rows in whatever order it pleases.  The impact of this is that the rows you get back will not be consistent &#8211; you are not guaranteed to get all of the rows through this approach, nor are you guaranteed to not get duplicate rows!  For a table where we tested this approach, with approximately 600k records, we got about 400k unique rows back.</p>
<p>Adding an <code>ORDER BY id</code> (since most of our tables contain an <code>id</code> column) resolves these issues, only to incur a large performance penalty while the database computes an ordered list of <code>ids</code> so that it can return the requested block of records.</p>
<h2>Back to the drawing board: Try Database Cursors</h2>
<p>Databases have long had a way of supporting this use case via <a href="http://en.wikipedia.org/wiki/Cursor_(databases)">Cursors</a>.  <span class="caps">JDBC</span>, and specifically the <code>ResultSet</code> interface, was designed to support them.</p>
<p>It turns out that the default settings on the <code>java.sql.Connection</code> configured by <code>clojure.contrib.sql</code> are not set to use a Cursor.   According to &#8216;<a href="http://jdbc.postgresql.org/documentation/84/query.html">PostgreSQL <span class="caps">JDBC</span> Driver: Getting results based on a cursor</a>&#8217; there are several settings that need to be in place for the result set to use a cursor:</p>
<ul>
	<li>Auto Commit must be turned off</li>
	<li>The <code>java.sql.ResultSet</code> must be created with a <code>ResultSet</code> type of: <code>ResultSet.TYPE_FORWARD_ONLY</code></li>
	<li>The Query must be a single statement, meaning it must not contain semi-colons joining together multiple statements.</li>
	<li>You must use a <code>java.sql.Statement</code> and set the <code>FetchSize</code> on the statement to a non-zero value.</li>
</ul>
<p>It turns out that <code>clojure.contrib.sql</code> has a handy form that will turn off <code>AutoCommit</code> and ensure it will be set back to its previous value so you don&#8217;t put the <code>Connection</code> into an inconsistent state (and so that you join any transactions that are in progress).  That form is <code>transaction</code>, and trying it out:</p>
<script src="http://gist.github.com/630340.js"> </script><p>The output shows that the <code>AutoCommit</code> is indeed off, but we&#8217;ll still need to set a <code>FetchSize</code> ourselves.</p>
<p>The default <code>ResultSet</code> type is <code>ResultSet.TYPE_FORWARD_ONLY, which is what we needed.  Adding in @setFetchSize</code> is straightforward, so, wrapping it all up into a helper function (following the conventions in the <code>sql</code> package) I end up with:</p>
<script src="http://gist.github.com/630351.js"> </script><p>This brings me back to my goal: being able to wield very large result sets.</p>
<p class="meta">Kyle Burton, 14 Oct 2010 &#8211; Philadelphia PA</p>
<h3>See Also</h3>
<ul>
	<li><a href="http://jdbc.postgresql.org/">PostgreSQL <span class="caps">JDBC</span> Driver</a></li>
</ul>
<p><br /></p>]]></description>
      <content:encoded><![CDATA[<h1>Clojure and Large Result Sets</h1>
<p>I&#8217;ve been working with the very useful <a href="http://richhickey.github.com/clojure-contrib/sql-api.html">clojure.contrib.sql</a>  package.  One wrinkle I&#8217;ve encountered, in an otherwise lazy language, is that the <span class="caps">SQL</span> connections typically are not lazy.  By default they load the entire result set at once &#8211; even if the <code>java.sql.ResultSet</code> is lazily accessed.  This isn&#8217;t an issue with <code>clojure.contrib.sql</code> inasmuch as it is with how the <a href="http://en.wikipedia.org/wiki/Java_Database_Connectivity"><span class="caps">JDBC</span></a> classes are being used.</p>
<p>For many use cases, fetching a handful of rows, a user profile, etc., this a perfectly reasonable default.  When you&#8217;re working with result sets that are larger than will fit into memory this default behavior isn&#8217;t so desirable.</p>
<h2>First Attempt: <code>LIMIT</code> using an Offset</h2>
<p>I like the interface that the contrib library offers &#8211; a lazy sequence of the result set. Since PostgreSQL supports ranges as part of it&#8217;s <span class="caps">SQL</span> (via <code>LIMIT</code>) it would seem that you could just write up a quick chunking function that pulls ranges of records from the table using a lazy approach, while still presenting things as a single stream of records from a single result set.</p>
<script src="http://gist.github.com/626979.js"> </script><p>The first function, <code>get-record-range</code>, simply takes a table name a starting offset and a record count.  It executes a select for the given range and offset.  The second function uses the first to create a lazy sequence, generating the next block of records when the previous block was exhausted.  It includes a check to ensure it terminates when there are no more records.</p>
<p>The only piece missing from the above is our <code>db/exec-sql</code>, which is just a convenience wrapper around <code>clojure.contrib.sql/with-query-results</code> that forces the lazy record sequence (this was not the source of our memory troubles).  <code>db/exec-sql</code> is something I often use to quickly grab the entirety of a result set.</p>
<script src="http://gist.github.com/626997.js"> </script><p>The problem with this approach though, is that using a <code>SELECT *</code> and a <code>LIMIT</code> without an <code>ORDER BY</code> clause doesn&#8217;t guarantee the ordering of the records.  The database (for an example, see <a href="http://www.postgresql.org/docs/9.0/interactive/queries-limit.html">PostgreSQL</a>) is free to return rows in whatever order it pleases.  The impact of this is that the rows you get back will not be consistent &#8211; you are not guaranteed to get all of the rows through this approach, nor are you guaranteed to not get duplicate rows!  For a table where we tested this approach, with approximately 600k records, we got about 400k unique rows back.</p>
<p>Adding an <code>ORDER BY id</code> (since most of our tables contain an <code>id</code> column) resolves these issues, only to incur a large performance penalty while the database computes an ordered list of <code>ids</code> so that it can return the requested block of records.</p>
<h2>Back to the drawing board: Try Database Cursors</h2>
<p>Databases have long had a way of supporting this use case via <a href="http://en.wikipedia.org/wiki/Cursor_(databases)">Cursors</a>.  <span class="caps">JDBC</span>, and specifically the <code>ResultSet</code> interface, was designed to support them.</p>
<p>It turns out that the default settings on the <code>java.sql.Connection</code> configured by <code>clojure.contrib.sql</code> are not set to use a Cursor.   According to &#8216;<a href="http://jdbc.postgresql.org/documentation/84/query.html">PostgreSQL <span class="caps">JDBC</span> Driver: Getting results based on a cursor</a>&#8217; there are several settings that need to be in place for the result set to use a cursor:</p>
<ul>
	<li>Auto Commit must be turned off</li>
	<li>The <code>java.sql.ResultSet</code> must be created with a <code>ResultSet</code> type of: <code>ResultSet.TYPE_FORWARD_ONLY</code></li>
	<li>The Query must be a single statement, meaning it must not contain semi-colons joining together multiple statements.</li>
	<li>You must use a <code>java.sql.Statement</code> and set the <code>FetchSize</code> on the statement to a non-zero value.</li>
</ul>
<p>It turns out that <code>clojure.contrib.sql</code> has a handy form that will turn off <code>AutoCommit</code> and ensure it will be set back to its previous value so you don&#8217;t put the <code>Connection</code> into an inconsistent state (and so that you join any transactions that are in progress).  That form is <code>transaction</code>, and trying it out:</p>
<script src="http://gist.github.com/630340.js"> </script><p>The output shows that the <code>AutoCommit</code> is indeed off, but we&#8217;ll still need to set a <code>FetchSize</code> ourselves.</p>
<p>The default <code>ResultSet</code> type is <code>ResultSet.TYPE_FORWARD_ONLY, which is what we needed.  Adding in @setFetchSize</code> is straightforward, so, wrapping it all up into a helper function (following the conventions in the <code>sql</code> package) I end up with:</p>
<script src="http://gist.github.com/630351.js"> </script><p>This brings me back to my goal: being able to wield very large result sets.</p>
<p class="meta">Kyle Burton, 14 Oct 2010 &#8211; Philadelphia PA</p>
<h3>See Also</h3>
<ul>
	<li><a href="http://jdbc.postgresql.org/">PostgreSQL <span class="caps">JDBC</span> Driver</a></li>
</ul>
<p><br /></p>]]></content:encoded>
    </item>
    
    <item>
      <title>How We Deploy Our Clojure Services</title>
      <link>http://asymmetrical-view.com/2010/08/26/how-were-deploying-our-clojure-applications.html</link>
      <comments>http://asymmetrical-view.com/2010/08/26/how-were-deploying-our-clojure-applications.html#comments</comments>

      <pubDate>2010-08-26T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2010/08/26/how-were-deploying-our-clojure-applications.html</guid>

      <id>http://asymmetrical-view.com/2010/08/26/how-were-deploying-our-clojure-applications</id>
      <description><![CDATA[<h1>How We Deploy Our Clojure Services</h1>
<p>We&#8217;re using <a href="http://clojure.org">Clojure</a> as a core development technology at my company.  We have a basic web service implemented in Clojure running inside <a href="http://jetty.codehaus.org/jetty/">Jetty</a>.  I&#8217;m not using a full J2EE container, I just wanted a fairly simple strategy for running the Jetty based service.  We&#8217;re already using <a href="http://wiki.opscode.com/display/chef/Home">Chef</a> for provisioning our servers, for installing base dependencies, so that&#8217;s what I started with.</p>
<p>The main components are:</p>
<ul>
	<li>chef recipe to install the foundation</li>
	<li>init script for controlling the service</li>
	<li>ruby based, <a href="http://capify.org">capistrano</a>-esque deployer.</li>
	<li>maven based project using the <a href="http://github.com/talios/clojure-maven-plugin">clojure-maven-plugin</a></li>
</ul>
<h2>Chef</h2>
<h4>recipes/default.rb</h4>
<p>The first part of our deployment is a Chef recipe to install our base components for the service.  We set up an unprivileged user for the service to be run as, set up <code>/var/lib</code> and <code>/var/log</code> directories to act as its install target and for its log files, set the correct permissions and install the init and start scripts for the service.</p>
<script src="http://gist.github.com/551473.js"> </script><h4>templates/default/the-clj-serviced.init</h4>
<p>The init script is a standard <span class="caps">LSB</span> style init script that I copied from another daemon already in <code>/etc/init.d</code> and then trimmed down and modified for our needs.  The init script manages the running process via its pid (process id), which it expects to be stored in the file identified by <code>$PIDFILE</code>.  It uses <code>the-clj-service.sh</code> to start the service &#8211; stopping the service is done by sending a signal to the <span class="caps">PID</span> of the <span class="caps">JVM</span> process.  I&#8217;d like to introduce a more graceful shutdown procedure by asking our service to exit, this serves our needs for now.</p>
<script src="http://gist.github.com/551475.js"> </script><h4>/var/lib/the-clj-service/the-clj-service.sh</h4>
<p>The <span class="caps">JVM</span> isn&#8217;t really able to fork and background itself.  The <code>start-stop-daemon</code> utility can do this on behalf of the daemon, but according to its man page, that&#8217;s not recommended.  This shell script represents that bridge between the init script controlling the daemon and the actual daemon, the <span class="caps">JVM</span>.  It provides a simple runner that forks itself, writes out the child&#8217;s <span class="caps">PID</span> and then exits.  This is one spot I&#8217;m not yet satisfied with: there is a hole here, where if the Jetty application fails to start or crashes, the init script will think it started when it in fact did not.</p>
<script src="http://gist.github.com/551476.js"> </script><h4>deploy.rb</h4>
<p>Finally we have our deployer, modeled after Ruby&#8217;s capistrano, for pushing the application up to the boxes where we&#8217;re going to run the service.  I&#8217;ve left out the <code>ServiceUtils</code> class because in our environment it contains some system configuration information, what you see below contains all the actual steps sans the configuration and credentials information for those hosts.  <code>install_path</code> matches the location you saw above in the init and service scripts.</p>
<p>The deployer builds the service using <a href="http://maven.apache.org/">maven</a>, using the <a href="http://maven.apache.org/plugins/maven-assembly-plugin/">assembly</a> plugin to build a stand-alone Jar file that contains our application along with all of its dependencies.  This produces a larger artifact than if it just contained our application code, but has some advantages: it freezes the dependencies into 1 archive; it is easily relocatable; we don&#8217;t have to perform a build or manage dependencies on the systems where we run the application.</p>
<p>As part of the deploy process we also create a few configuration files: a logging configuration, which for now we just copy the file appropriate for the environment from our project&#8217;s; a database configuration file and a service configuration file.  The service properties file is built dynamically and is available via a special api call that allows us to monitor and validate that the version of the service that we think is installed is installed on a given server.</p>
<script src="http://gist.github.com/551478.js"> </script><p>I&#8217;d love to hear how others are deploying their Clojure applications and about what we could improve.  I&#8217;m happy with this as a starting point, but will definitely focus on improving it as we move forward.</p>
<p class="meta">Kyle Burton, 26 Aug 2010 &#8211; Radnor PA</p>
<p><br /></p>]]></description>
      <content:encoded><![CDATA[<h1>How We Deploy Our Clojure Services</h1>
<p>We&#8217;re using <a href="http://clojure.org">Clojure</a> as a core development technology at my company.  We have a basic web service implemented in Clojure running inside <a href="http://jetty.codehaus.org/jetty/">Jetty</a>.  I&#8217;m not using a full J2EE container, I just wanted a fairly simple strategy for running the Jetty based service.  We&#8217;re already using <a href="http://wiki.opscode.com/display/chef/Home">Chef</a> for provisioning our servers, for installing base dependencies, so that&#8217;s what I started with.</p>
<p>The main components are:</p>
<ul>
	<li>chef recipe to install the foundation</li>
	<li>init script for controlling the service</li>
	<li>ruby based, <a href="http://capify.org">capistrano</a>-esque deployer.</li>
	<li>maven based project using the <a href="http://github.com/talios/clojure-maven-plugin">clojure-maven-plugin</a></li>
</ul>
<h2>Chef</h2>
<h4>recipes/default.rb</h4>
<p>The first part of our deployment is a Chef recipe to install our base components for the service.  We set up an unprivileged user for the service to be run as, set up <code>/var/lib</code> and <code>/var/log</code> directories to act as its install target and for its log files, set the correct permissions and install the init and start scripts for the service.</p>
<script src="http://gist.github.com/551473.js"> </script><h4>templates/default/the-clj-serviced.init</h4>
<p>The init script is a standard <span class="caps">LSB</span> style init script that I copied from another daemon already in <code>/etc/init.d</code> and then trimmed down and modified for our needs.  The init script manages the running process via its pid (process id), which it expects to be stored in the file identified by <code>$PIDFILE</code>.  It uses <code>the-clj-service.sh</code> to start the service &#8211; stopping the service is done by sending a signal to the <span class="caps">PID</span> of the <span class="caps">JVM</span> process.  I&#8217;d like to introduce a more graceful shutdown procedure by asking our service to exit, this serves our needs for now.</p>
<script src="http://gist.github.com/551475.js"> </script><h4>/var/lib/the-clj-service/the-clj-service.sh</h4>
<p>The <span class="caps">JVM</span> isn&#8217;t really able to fork and background itself.  The <code>start-stop-daemon</code> utility can do this on behalf of the daemon, but according to its man page, that&#8217;s not recommended.  This shell script represents that bridge between the init script controlling the daemon and the actual daemon, the <span class="caps">JVM</span>.  It provides a simple runner that forks itself, writes out the child&#8217;s <span class="caps">PID</span> and then exits.  This is one spot I&#8217;m not yet satisfied with: there is a hole here, where if the Jetty application fails to start or crashes, the init script will think it started when it in fact did not.</p>
<script src="http://gist.github.com/551476.js"> </script><h4>deploy.rb</h4>
<p>Finally we have our deployer, modeled after Ruby&#8217;s capistrano, for pushing the application up to the boxes where we&#8217;re going to run the service.  I&#8217;ve left out the <code>ServiceUtils</code> class because in our environment it contains some system configuration information, what you see below contains all the actual steps sans the configuration and credentials information for those hosts.  <code>install_path</code> matches the location you saw above in the init and service scripts.</p>
<p>The deployer builds the service using <a href="http://maven.apache.org/">maven</a>, using the <a href="http://maven.apache.org/plugins/maven-assembly-plugin/">assembly</a> plugin to build a stand-alone Jar file that contains our application along with all of its dependencies.  This produces a larger artifact than if it just contained our application code, but has some advantages: it freezes the dependencies into 1 archive; it is easily relocatable; we don&#8217;t have to perform a build or manage dependencies on the systems where we run the application.</p>
<p>As part of the deploy process we also create a few configuration files: a logging configuration, which for now we just copy the file appropriate for the environment from our project&#8217;s; a database configuration file and a service configuration file.  The service properties file is built dynamically and is available via a special api call that allows us to monitor and validate that the version of the service that we think is installed is installed on a given server.</p>
<script src="http://gist.github.com/551478.js"> </script><p>I&#8217;d love to hear how others are deploying their Clojure applications and about what we could improve.  I&#8217;m happy with this as a starting point, but will definitely focus on improving it as we move forward.</p>
<p class="meta">Kyle Burton, 26 Aug 2010 &#8211; Radnor PA</p>
<p><br /></p>]]></content:encoded>
    </item>
    
    <item>
      <title>Automating Capistrano Password Prompts with Expect</title>
      <link>http://asymmetrical-view.com/2010/07/06/automate-capistrano-passwords.html</link>
      <comments>http://asymmetrical-view.com/2010/07/06/automate-capistrano-passwords.html#comments</comments>

      <pubDate>2010-07-06T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2010/07/06/automate-capistrano-passwords.html</guid>

      <id>http://asymmetrical-view.com/2010/07/06/automate-capistrano-passwords</id>
      <description><![CDATA[<h1>Automating Capistrano Password Prompts with Expect</h1>
<p>I just started using <a href="http://capify.org/">Capistrano</a> for deploying my <a href="http://rubyonrails.org/">Rails</a> applications (like <a href="http://snapclean.me/">Snapclean.me</a>&quot;).  I also just started using <a href="http://github.com/vigetlabs/capistrano_rsync_with_remote_cache">capistrano_rsync_with_remote_cache</a> to help push releases out faster than the <code>:copy</code> deploy strategy.</p>
<p>I&#8217;m very happy with how much faster it is than the a <code>:copy</code>, but I&#8217;m impatient and having to provide the password more than once per invocation is frustrating to me.  I know the old Unix standby <a href="http://en.wikipedia.org/wiki/Expect">Expect</a> can do this easily, my only problem is I don&#8217;t remember <a href="http://en.wikipedia.org/wiki/Tcl">Tcl</a> very well and every time I&#8217;ve done this I forget how / what I did.  This post is a write up so I know where to come back to the next time I need to do this (and I know I&#8217;ll run into it again).</p>
<h2>Spawn and Expect</h2>
<p>Conceptually the basic use of Expect is very straight forward.  You execute another program and you can register handlers that will be invoked when the program emits specific output.  In the case of executing capistrano, and it executing other commands, I&#8217;m looking for anything that looks like a password prompt.  When a password prompt is emitted I want to send the password.</p>
<p>The script below does exactly that, first asking the user for the password (disabling terminal echo) before spawning the capistrano command itself.</p>

<pre class="code">
#!/usr/bin/env expect
stty -echo
send_user -- "Login Password: "
expect_user -re "(.*)\n"
send_user "\n"
stty echo
set the_password $expect_out(1,string)

spawn cap deploy
expect {
  -re " *\[Pp\]assword: *" {
    send "$the_password\n"
    exp_continue
  }
}
</pre>
<p>I put the above script in a file called <code>wrap-cap</code>, and did a <code>chmod 755 ./wrap-cap</code> on the file.</p>
<p>The <code>exp_continue</code> is used to reset (or loop) expect so that it will continue to look for password prompts and provide the password as many times as it is requested &#8211; since there are various commands that may ask for it (rsync, ssh, sudo, etc.) and some of them are optional (especially sudo), this &#8216;looping&#8217; behavior is very handy.</p>
<p>Expect is a great Unix tool for developers and system administrators to have in their toolboxes.</p>
<p class="meta">Kyle Burton, 6 Jul 2010 &#8211; Philadelphia PA</p>
<p><br /></p>]]></description>
      <content:encoded><![CDATA[<h1>Automating Capistrano Password Prompts with Expect</h1>
<p>I just started using <a href="http://capify.org/">Capistrano</a> for deploying my <a href="http://rubyonrails.org/">Rails</a> applications (like <a href="http://snapclean.me/">Snapclean.me</a>&quot;).  I also just started using <a href="http://github.com/vigetlabs/capistrano_rsync_with_remote_cache">capistrano_rsync_with_remote_cache</a> to help push releases out faster than the <code>:copy</code> deploy strategy.</p>
<p>I&#8217;m very happy with how much faster it is than the a <code>:copy</code>, but I&#8217;m impatient and having to provide the password more than once per invocation is frustrating to me.  I know the old Unix standby <a href="http://en.wikipedia.org/wiki/Expect">Expect</a> can do this easily, my only problem is I don&#8217;t remember <a href="http://en.wikipedia.org/wiki/Tcl">Tcl</a> very well and every time I&#8217;ve done this I forget how / what I did.  This post is a write up so I know where to come back to the next time I need to do this (and I know I&#8217;ll run into it again).</p>
<h2>Spawn and Expect</h2>
<p>Conceptually the basic use of Expect is very straight forward.  You execute another program and you can register handlers that will be invoked when the program emits specific output.  In the case of executing capistrano, and it executing other commands, I&#8217;m looking for anything that looks like a password prompt.  When a password prompt is emitted I want to send the password.</p>
<p>The script below does exactly that, first asking the user for the password (disabling terminal echo) before spawning the capistrano command itself.</p>

<pre class="code">
#!/usr/bin/env expect
stty -echo
send_user -- "Login Password: "
expect_user -re "(.*)\n"
send_user "\n"
stty echo
set the_password $expect_out(1,string)

spawn cap deploy
expect {
  -re " *\[Pp\]assword: *" {
    send "$the_password\n"
    exp_continue
  }
}
</pre>
<p>I put the above script in a file called <code>wrap-cap</code>, and did a <code>chmod 755 ./wrap-cap</code> on the file.</p>
<p>The <code>exp_continue</code> is used to reset (or loop) expect so that it will continue to look for password prompts and provide the password as many times as it is requested &#8211; since there are various commands that may ask for it (rsync, ssh, sudo, etc.) and some of them are optional (especially sudo), this &#8216;looping&#8217; behavior is very handy.</p>
<p>Expect is a great Unix tool for developers and system administrators to have in their toolboxes.</p>
<p class="meta">Kyle Burton, 6 Jul 2010 &#8211; Philadelphia PA</p>
<p><br /></p>]]></content:encoded>
    </item>
    
    <item>
      <title>New Clojure Libraries: Bloom Filter and LFSR</title>
      <link>http://asymmetrical-view.com/2010/07/01/two-new-clojure-libs.html</link>
      <comments>http://asymmetrical-view.com/2010/07/01/two-new-clojure-libs.html#comments</comments>

      <pubDate>2010-07-01T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2010/07/01/two-new-clojure-libs.html</guid>

      <id>http://asymmetrical-view.com/2010/07/01/two-new-clojure-libs</id>
      <description><![CDATA[<h1>New Clojure Libraries: Bloom Filter and <span class="caps">LFSR</span></h1>
<p>I created two new clojure libraries as part of my continued study of all things computing related.  I was introduced to the <a href="http://en.wikipedia.org/wiki/Bloom_filter">Bloom Filter</a> through <a href="http://news.ycombinator.com/">Hacker News</a> and to the <a href="http://en.wikipedia.org/wiki/LFSR">Linear Feedback Shift Register [<span class="caps">LFSR</span>]</a> through <a href="http://codeslinger.posterous.com/">Toby DiPasquale</a>.  It turns out that each of these will have practical application for me in the near future.  They are the kind of thing I wish I had learned about sooner.</p>
<h2><a href="http://en.wikipedia.org/wiki/Bloom_filter">Bloom Filter</a></h2>
<p>You can download clj-bloom from <a href="http://github.com/kyleburton/clj-bloom">Gitub.com/kyleburton/clj-bloom</a>  The filter is &#8220;a probabilistic data structure for testing set membership&#8221;, they &#8220;sacrifice determinism in favor of significantly lower memory usage&#8221;.  They make this trade off at the cost of false positives &#8211; but you can tune the filter&#8217;s false positive probability.  They are useful in situations when you need to test for membership in a very large set of data and can&#8217;t (or don&#8217;t want to) hold the set members themselves in memory.  A common use case is with a large corpus of documents &#8211; being able to quickly check if a new document is not in the set, storing it if it&#8217;s not, or pulling the existing copy and comparing it if you do.  In this type of use, a false positive has little impact as you&#8217;d pull the document and compare it anyway.  You can save the cost of making the initial query by using the bloom filter.</p>
<h2><a href="http://en.wikipedia.org/wiki/LFSR">Linear Feedback Shift Register [<span class="caps">LFSR</span>]</a></h2>
<p>LFSRs are related to Pseudo Random Number Generators [PRNGs].  There is a very interesting special class of LFSRs that have maximal period length &#8211; these LFSRs can be used as binary numbering systems since they iterate through all (2^n) &#8211; 1 possible bit combinations.  Unlike counting up from 1 in binary (0, 1, 10, 11, 100, 101, 110, 111, 1000, &#8230;) they are much less deterministic looking in how they iterate through the values.  I am currently looking at using them in ID generation, so that the IDs generated are not adjacent numeric values, eg: look pseudo-random, but are still guaranteed to be unique.  LFSRs are also easily serializable, which makes it possible for you to use them as a kind of pseudo random unique sequence.   You can download the code from <a href="http://github.com/kyleburton/clj-lfsr">Gitub.com/kyleburton/clj-lfsr</a></p>
<p>I found these two constructs fascinating, I hope you find the implementations useful.</p>
<p class="meta">Kyle Burton, 1 Jul 2010 &#8211; Philadelphia PA</p>
<p><br /></p>]]></description>
      <content:encoded><![CDATA[<h1>New Clojure Libraries: Bloom Filter and <span class="caps">LFSR</span></h1>
<p>I created two new clojure libraries as part of my continued study of all things computing related.  I was introduced to the <a href="http://en.wikipedia.org/wiki/Bloom_filter">Bloom Filter</a> through <a href="http://news.ycombinator.com/">Hacker News</a> and to the <a href="http://en.wikipedia.org/wiki/LFSR">Linear Feedback Shift Register [<span class="caps">LFSR</span>]</a> through <a href="http://codeslinger.posterous.com/">Toby DiPasquale</a>.  It turns out that each of these will have practical application for me in the near future.  They are the kind of thing I wish I had learned about sooner.</p>
<h2><a href="http://en.wikipedia.org/wiki/Bloom_filter">Bloom Filter</a></h2>
<p>You can download clj-bloom from <a href="http://github.com/kyleburton/clj-bloom">Gitub.com/kyleburton/clj-bloom</a>  The filter is &#8220;a probabilistic data structure for testing set membership&#8221;, they &#8220;sacrifice determinism in favor of significantly lower memory usage&#8221;.  They make this trade off at the cost of false positives &#8211; but you can tune the filter&#8217;s false positive probability.  They are useful in situations when you need to test for membership in a very large set of data and can&#8217;t (or don&#8217;t want to) hold the set members themselves in memory.  A common use case is with a large corpus of documents &#8211; being able to quickly check if a new document is not in the set, storing it if it&#8217;s not, or pulling the existing copy and comparing it if you do.  In this type of use, a false positive has little impact as you&#8217;d pull the document and compare it anyway.  You can save the cost of making the initial query by using the bloom filter.</p>
<h2><a href="http://en.wikipedia.org/wiki/LFSR">Linear Feedback Shift Register [<span class="caps">LFSR</span>]</a></h2>
<p>LFSRs are related to Pseudo Random Number Generators [PRNGs].  There is a very interesting special class of LFSRs that have maximal period length &#8211; these LFSRs can be used as binary numbering systems since they iterate through all (2^n) &#8211; 1 possible bit combinations.  Unlike counting up from 1 in binary (0, 1, 10, 11, 100, 101, 110, 111, 1000, &#8230;) they are much less deterministic looking in how they iterate through the values.  I am currently looking at using them in ID generation, so that the IDs generated are not adjacent numeric values, eg: look pseudo-random, but are still guaranteed to be unique.  LFSRs are also easily serializable, which makes it possible for you to use them as a kind of pseudo random unique sequence.   You can download the code from <a href="http://github.com/kyleburton/clj-lfsr">Gitub.com/kyleburton/clj-lfsr</a></p>
<p>I found these two constructs fascinating, I hope you find the implementations useful.</p>
<p class="meta">Kyle Burton, 1 Jul 2010 &#8211; Philadelphia PA</p>
<p><br /></p>]]></content:encoded>
    </item>
    
    <item>
      <title>How We Run Cucumber</title>
      <link>http://asymmetrical-view.com/2010/06/10/how-we-run-cucumber.html</link>
      <comments>http://asymmetrical-view.com/2010/06/10/how-we-run-cucumber.html#comments</comments>

      <pubDate>2010-06-10T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2010/06/10/how-we-run-cucumber.html</guid>

      <id>http://asymmetrical-view.com/2010/06/10/how-we-run-cucumber</id>
      <description><![CDATA[<h1>How We Run Cucumber</h1>
<p><a href="http://cukes.info/">Cucumber</a> is a wonderful behavior driven development tool by <a href="http://github.com/aslakhellesoy/">Aslak Hellesøy</a>.  There is a <a href="http://wiki.github.com/aslakhellesoy/cucumber/">getting started</a> guide in the wiki at <a href="http://github.com/aslakhellesoy/cucumber">github</a> that describes how to get it set up and running.</p>
<p>We&#8217;ve written a wrapper around Cucumber to help make it easier to run along with our application and to make it less intrusive when it runs the browser (at least under Linux).</p>
<h2>Server Execution</h2>
<p>Most of our test driven development doesn&#8217;t require <code>script/server</code> to be running the web application, and we want it to run under either the <code>cucumber</code> or <code>test</code> rails environment when it does.  Stopping (if it&#8217;s running) the development server, starting it and then shutting it down again when the tests are done was a manual process that we automated.</p>
<h2>Xnest</h2>
<p>When we run Cucumber under X Windows, it often grabs focus and keeps us from doing anything else with the desktop while the tests are running.  This is annoying to say the least.  Thankfully X11 has a utility called Xnest which allows you to run a window which is a contained X desktop.  Running this and then telling the browser to run inside it keeps it out of our way and allows us to keep using the machine without being constantly interrupted by the browser constantly jumping to the foreground.</p>
<h2><code>script/server</code> Arguments</h2>
<p>To pass arguments (such as the port, or other options) through to <code>script/server</code>, put a <code>--</code> between the arguments to <code>script/cucumber-runner</code> and they will be passed on verbatim to <code>script/server</code>.  In this example, <code>-p 8080</code> will be passed to <code>script/server</code> instructing it to use port 8080.</p>
<pre class="code">
$ script/cucumber-runner -g 1024x768 -- -p 8080
</pre>
<h2><code>cucumber-runner</code></h2>


<pre class="code">
#!/usr/bin/env ruby
require 'optparse'

# Controller for running Cucumber feature tests on your Rails application.
# Supports stopping/starting WEBRick in cucumber or test rails environment and
# (on supporting systems, eg: Linux) running the browser under Xnest to keep it
# away from your other desktop activities.
#
#
# Author::     Kyle Burton &lt;kyle.burton@gmail.com&gt;
# Copyright::  Copyright (c) 2010 Kyle Burton
# License::    Distributes under the same terms as Ruby

#
# Command line runner.
#
class CucumberRunner

  # location of the rails scripts
  SCRIPT_ROOT = File.dirname(__FILE__)

  # Set up defaults, can be overridden with command line parameters.
  def initialize
    @opts = {
      :env             =&gt; 'cucumber',
      :geometry        =&gt; '1280x800',
      :display         =&gt; ENV['DISPLAY'],
      :xnest_display   =&gt; ':2',
      :control_webrick =&gt; true,
      :try_use_xnest   =&gt; true
    }
  end

  # Determine if Xnest is present, and if it should be used (Not on OS X).
  def use_xnest?
    return false unless @opts[:try_use_xnest]
    on_darwin = (`uname` =~ /Darwin/)
    has_xnest = !(`which Xnest`.empty?)
    !on_darwin &amp;&amp; has_xnest
  end

  # Start Xnest in the background, save off the pid so it can be stopped later.
  def start_xnest
    @opts[:display] = @opts[:xnest_display]
    cmd = "Xnest #{@opts[:xnest_display]} &amp; echo $!"
    @xnest_pid = `#{cmd}`.to_i
  end

  # Stop Xnest with a SIGTERM.
  def stop_xnest
    Process.kill("TERM", @xnest_pid) if @xnest_pid
  end

  # Stop the WEBRick server by looking for it in the process tree.
  def stop_webrick
    res = `ps aux | grep [r]uby | grep [s]cript/server`
    pid = res.split[1]
    return unless pid
    puts "#{$0} STOPPING WEBRick pid=#{pid}"
    Process.kill "KILL", pid.to_i
  end

  # Start WEBRick with the configured rails environment as a daemon (background).
  def start_webrick
    cmd = "#{SCRIPT_ROOT}/server -e #{@opts[:env]} -d"
    puts "#{$0} Starting WEBRick: #{cmd}"
    system cmd
  end

  # Process any command line arguments.
  def parse_opts
    OptionParser.new do |opts|
      opts.banner = "Usage: #{$0} [options]"

      opts.on("-h", "--help") do
        puts &lt;&lt;-EOH
       #{$0} [[opts]]

        -e ENV  --envrionment ENV   Rails environment to run under default=#{@opts[:env]}
        -g GEO  --geometry GEO      Xnest geometry to use default=#{@opts[:geometry]}
        -X      --no-xnest          Do not use Xnest (even if present)
        -d DSP  --display DSP       DISPLAY to use default=#{@opts[:display]}
        -x DSP  --xnest-display DSP Xnest's DISPLAY to use default=#{@opts[:xnest_display]}
        -W      --no-webrick        Don't start WEBRick (assume running) default=false
        EOH
        exit 0
      end

      opts.on("-e", "--envrionment ENV") do |env|
        @opts[:env] = env
      end

      opts.on("-g", "--geometry GEO") do |geo|
        @opts[:geometry] = geo
      end

      opts.on("-X", "--no-xnest") do
        options[:use_xnest] = false
      end

      opts.on("-d", "--display DSP") do |dsp|
        options[:display] = dsp
      end

      opts.on("-x", "--xnest-display DISP") do |disp|
        options[:xnest_display] = disp
      end

      opts.on("-W", "--no-webrick") do
        options[:control_webrick] = false
      end
    end.parse!
  end

  # Process options, start Xnest, [re]start WEBRick, execute the cucumber
  # suite, then stop Xnest and stop WEBrick
  def run
    parse_opts
    start_xnest if use_xnest?

    if @opts[:control_webrick]
      stop_webrick
      start_webrick
    end

    cmd = "#{SCRIPT_ROOT}/runner #{SCRIPT_ROOT}/cucumber #{ARGV}"
    ENV['DISPLAY']   = @opts[:display]
    ENV['RAILS_ENV'] = @opts[:env]
    puts "#{$0} using RAILS_ENV=#{ENV['RAILS_ENV']}"
    res = system cmd

  ensure
    stop_webrick  if @opts[:control_webrick]
    stop_xnest    if @xnest_pid
  end

  def self.main
    self.new.run
  end
end

CucumberRunner.main
</pre>
<p>You can download or check out <a href="http://github.com/kyleburton/cucumber-example/blob/master/cukeex/script/cucumber-runner">cucumber-runner</a> from my github <a href="http://github.com/kyleburton/cucumber-example/">cucumber-example project</a>.</p>
<p>Running Cucumber with this wrapper helps make it easier and less intrusive to use.  If anyone has suggestions for how to make it less intrusive while running under OS X, please <a href="mailto:kyle.burton@gmail.com">email me</a>, I&#8217;d love to hear your suggestions.</p>
<p class="meta">Kyle Burton, 10 Jun 2010 &#8211; Philadelphia PA</p>
<p><br /></p>]]></description>
      <content:encoded><![CDATA[<h1>How We Run Cucumber</h1>
<p><a href="http://cukes.info/">Cucumber</a> is a wonderful behavior driven development tool by <a href="http://github.com/aslakhellesoy/">Aslak Hellesøy</a>.  There is a <a href="http://wiki.github.com/aslakhellesoy/cucumber/">getting started</a> guide in the wiki at <a href="http://github.com/aslakhellesoy/cucumber">github</a> that describes how to get it set up and running.</p>
<p>We&#8217;ve written a wrapper around Cucumber to help make it easier to run along with our application and to make it less intrusive when it runs the browser (at least under Linux).</p>
<h2>Server Execution</h2>
<p>Most of our test driven development doesn&#8217;t require <code>script/server</code> to be running the web application, and we want it to run under either the <code>cucumber</code> or <code>test</code> rails environment when it does.  Stopping (if it&#8217;s running) the development server, starting it and then shutting it down again when the tests are done was a manual process that we automated.</p>
<h2>Xnest</h2>
<p>When we run Cucumber under X Windows, it often grabs focus and keeps us from doing anything else with the desktop while the tests are running.  This is annoying to say the least.  Thankfully X11 has a utility called Xnest which allows you to run a window which is a contained X desktop.  Running this and then telling the browser to run inside it keeps it out of our way and allows us to keep using the machine without being constantly interrupted by the browser constantly jumping to the foreground.</p>
<h2><code>script/server</code> Arguments</h2>
<p>To pass arguments (such as the port, or other options) through to <code>script/server</code>, put a <code>--</code> between the arguments to <code>script/cucumber-runner</code> and they will be passed on verbatim to <code>script/server</code>.  In this example, <code>-p 8080</code> will be passed to <code>script/server</code> instructing it to use port 8080.</p>
<pre class="code">
$ script/cucumber-runner -g 1024x768 -- -p 8080
</pre>
<h2><code>cucumber-runner</code></h2>


<pre class="code">
#!/usr/bin/env ruby
require 'optparse'

# Controller for running Cucumber feature tests on your Rails application.
# Supports stopping/starting WEBRick in cucumber or test rails environment and
# (on supporting systems, eg: Linux) running the browser under Xnest to keep it
# away from your other desktop activities.
#
#
# Author::     Kyle Burton &lt;kyle.burton@gmail.com&gt;
# Copyright::  Copyright (c) 2010 Kyle Burton
# License::    Distributes under the same terms as Ruby

#
# Command line runner.
#
class CucumberRunner

  # location of the rails scripts
  SCRIPT_ROOT = File.dirname(__FILE__)

  # Set up defaults, can be overridden with command line parameters.
  def initialize
    @opts = {
      :env             =&gt; 'cucumber',
      :geometry        =&gt; '1280x800',
      :display         =&gt; ENV['DISPLAY'],
      :xnest_display   =&gt; ':2',
      :control_webrick =&gt; true,
      :try_use_xnest   =&gt; true
    }
  end

  # Determine if Xnest is present, and if it should be used (Not on OS X).
  def use_xnest?
    return false unless @opts[:try_use_xnest]
    on_darwin = (`uname` =~ /Darwin/)
    has_xnest = !(`which Xnest`.empty?)
    !on_darwin &amp;&amp; has_xnest
  end

  # Start Xnest in the background, save off the pid so it can be stopped later.
  def start_xnest
    @opts[:display] = @opts[:xnest_display]
    cmd = "Xnest #{@opts[:xnest_display]} &amp; echo $!"
    @xnest_pid = `#{cmd}`.to_i
  end

  # Stop Xnest with a SIGTERM.
  def stop_xnest
    Process.kill("TERM", @xnest_pid) if @xnest_pid
  end

  # Stop the WEBRick server by looking for it in the process tree.
  def stop_webrick
    res = `ps aux | grep [r]uby | grep [s]cript/server`
    pid = res.split[1]
    return unless pid
    puts "#{$0} STOPPING WEBRick pid=#{pid}"
    Process.kill "KILL", pid.to_i
  end

  # Start WEBRick with the configured rails environment as a daemon (background).
  def start_webrick
    cmd = "#{SCRIPT_ROOT}/server -e #{@opts[:env]} -d"
    puts "#{$0} Starting WEBRick: #{cmd}"
    system cmd
  end

  # Process any command line arguments.
  def parse_opts
    OptionParser.new do |opts|
      opts.banner = "Usage: #{$0} [options]"

      opts.on("-h", "--help") do
        puts &lt;&lt;-EOH
       #{$0} [[opts]]

        -e ENV  --envrionment ENV   Rails environment to run under default=#{@opts[:env]}
        -g GEO  --geometry GEO      Xnest geometry to use default=#{@opts[:geometry]}
        -X      --no-xnest          Do not use Xnest (even if present)
        -d DSP  --display DSP       DISPLAY to use default=#{@opts[:display]}
        -x DSP  --xnest-display DSP Xnest's DISPLAY to use default=#{@opts[:xnest_display]}
        -W      --no-webrick        Don't start WEBRick (assume running) default=false
        EOH
        exit 0
      end

      opts.on("-e", "--envrionment ENV") do |env|
        @opts[:env] = env
      end

      opts.on("-g", "--geometry GEO") do |geo|
        @opts[:geometry] = geo
      end

      opts.on("-X", "--no-xnest") do
        options[:use_xnest] = false
      end

      opts.on("-d", "--display DSP") do |dsp|
        options[:display] = dsp
      end

      opts.on("-x", "--xnest-display DISP") do |disp|
        options[:xnest_display] = disp
      end

      opts.on("-W", "--no-webrick") do
        options[:control_webrick] = false
      end
    end.parse!
  end

  # Process options, start Xnest, [re]start WEBRick, execute the cucumber
  # suite, then stop Xnest and stop WEBrick
  def run
    parse_opts
    start_xnest if use_xnest?

    if @opts[:control_webrick]
      stop_webrick
      start_webrick
    end

    cmd = "#{SCRIPT_ROOT}/runner #{SCRIPT_ROOT}/cucumber #{ARGV}"
    ENV['DISPLAY']   = @opts[:display]
    ENV['RAILS_ENV'] = @opts[:env]
    puts "#{$0} using RAILS_ENV=#{ENV['RAILS_ENV']}"
    res = system cmd

  ensure
    stop_webrick  if @opts[:control_webrick]
    stop_xnest    if @xnest_pid
  end

  def self.main
    self.new.run
  end
end

CucumberRunner.main
</pre>
<p>You can download or check out <a href="http://github.com/kyleburton/cucumber-example/blob/master/cukeex/script/cucumber-runner">cucumber-runner</a> from my github <a href="http://github.com/kyleburton/cucumber-example/">cucumber-example project</a>.</p>
<p>Running Cucumber with this wrapper helps make it easier and less intrusive to use.  If anyone has suggestions for how to make it less intrusive while running under OS X, please <a href="mailto:kyle.burton@gmail.com">email me</a>, I&#8217;d love to hear your suggestions.</p>
<p class="meta">Kyle Burton, 10 Jun 2010 &#8211; Philadelphia PA</p>
<p><br /></p>]]></content:encoded>
    </item>
    
    <item>
      <title>Creating Standalone Java Applications with Leiningen</title>
      <link>http://asymmetrical-view.com/2010/06/08/building-standalone-jars-wtih-leiningen.html</link>
      <comments>http://asymmetrical-view.com/2010/06/08/building-standalone-jars-wtih-leiningen.html#comments</comments>

      <pubDate>2010-06-08T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2010/06/08/building-standalone-jars-wtih-leiningen.html</guid>

      <id>http://asymmetrical-view.com/2010/06/08/building-standalone-jars-wtih-leiningen</id>
      <description><![CDATA[<h1>Creating Standalone Java Applications with Leiningen</h1>
<p><a href="http://github.com/technomancy/leiningen">Leiningen</a> is a simpler build tool for <a href="http://clojure.org/">Clojure</a>.  <a href="/2010/06/03/leiningen.html">Previously</a> I covered a few basic aspects including how to run the <span class="caps">HEAD</span> version of Leiningen.  Leiningen can also build a standalone jars in the same way the <a href="http://maven.apache.org/plugins/maven-assembly-plugin/">maven assembly plug-in</a> does.  There are a few steps you need to follow, I&#8217;ll walk you through them here.  This example is available in my <a href="http://github.com/kyleburton/sandbox/tree/master/examples/clojure/leiningen/cljcsv/">sandbox</a>.</p>
<h2><code>project.clj</code></h2>
<p>For the example, I started by creating a new project (for testing a <a href="http://github.com/davidsantiago/clojure-csv">csv parsing library</a>) by running <code>lein new cljcsv</code>.  I added <code>clojure-csv</code> as a dependency, set <code>cljcsv.core</code> to be compiled, by specifying the name-space with the <code>:aot</code> parameter and specified <code>cljcsv.core</code> to be the main class invoked for the jar file by specifying it with <code>:main</code>.</p>
<pre class="code">
(defproject cljcsv "1.0.0-SNAPSHOT"
  :description "CSV Example."
  :dependencies
    [[org.clojure/clojure "1.1.0"]
     [org.clojure/clojure-contrib "1.1.0"]
     [clojure-csv/clojure-csv "1.0.0"]]
  :aot  [cljcsv.core]
  :main cljcsv.core)
</pre>
<h2><code>src/cljcsv/core.clj</code></h2>
<p>To have a Clojure program produce a class file with a <code>main</code> function, you need to ensure you have <code>:gen-class</code> specified in the name-space for your program and that you define a <code>-main</code> function to act as the main.</p>
<pre class="code">
(ns cljcsv.core
  (:require [com.davidsantiago.csv :as cdc]
            [clojure.contrib.pprint :as pp])
  (:gen-class))

(defn parse-cdc [file]
 (let [rs (cdc/parse-csv (slurp file))]
  (prn (str "rs=" rs))
  (prn (pp/cl-format nil "cdc: rows: ~a~&amp;" (count rs)))
  (prn (pp/cl-format nil "cdc: ~a~&amp;" rs))))

(defn -main [&amp; args]
  (prn (format "args=%s" args))
  (if (not (empty? args))
    (do
      (parse-cdc (first args)))))

</pre>
<p>Then to build and run the jar:</p>
<pre class="code">
$ lein compile
$ lein uberjar
$ java -jar cljcsv-standalone.jar input.csv
</pre>
<p>Leiningen makes creating and building Clojure projects quick and easy.  It makes creating an executable jar for your project, which may have many dependencies, about as easy as you can get.</p>
<p class="meta">Kyle Burton, 08 Jun 2010 &#8211; Philadelphia PA</p>
<h5>Special Thanks</h5>
<p>Special thanks to <a href="http://technomancy.us/">technomancy</a>, for creating Leiningen.</p>
<p><br /></p>]]></description>
      <content:encoded><![CDATA[<h1>Creating Standalone Java Applications with Leiningen</h1>
<p><a href="http://github.com/technomancy/leiningen">Leiningen</a> is a simpler build tool for <a href="http://clojure.org/">Clojure</a>.  <a href="/2010/06/03/leiningen.html">Previously</a> I covered a few basic aspects including how to run the <span class="caps">HEAD</span> version of Leiningen.  Leiningen can also build a standalone jars in the same way the <a href="http://maven.apache.org/plugins/maven-assembly-plugin/">maven assembly plug-in</a> does.  There are a few steps you need to follow, I&#8217;ll walk you through them here.  This example is available in my <a href="http://github.com/kyleburton/sandbox/tree/master/examples/clojure/leiningen/cljcsv/">sandbox</a>.</p>
<h2><code>project.clj</code></h2>
<p>For the example, I started by creating a new project (for testing a <a href="http://github.com/davidsantiago/clojure-csv">csv parsing library</a>) by running <code>lein new cljcsv</code>.  I added <code>clojure-csv</code> as a dependency, set <code>cljcsv.core</code> to be compiled, by specifying the name-space with the <code>:aot</code> parameter and specified <code>cljcsv.core</code> to be the main class invoked for the jar file by specifying it with <code>:main</code>.</p>
<pre class="code">
(defproject cljcsv "1.0.0-SNAPSHOT"
  :description "CSV Example."
  :dependencies
    [[org.clojure/clojure "1.1.0"]
     [org.clojure/clojure-contrib "1.1.0"]
     [clojure-csv/clojure-csv "1.0.0"]]
  :aot  [cljcsv.core]
  :main cljcsv.core)
</pre>
<h2><code>src/cljcsv/core.clj</code></h2>
<p>To have a Clojure program produce a class file with a <code>main</code> function, you need to ensure you have <code>:gen-class</code> specified in the name-space for your program and that you define a <code>-main</code> function to act as the main.</p>
<pre class="code">
(ns cljcsv.core
  (:require [com.davidsantiago.csv :as cdc]
            [clojure.contrib.pprint :as pp])
  (:gen-class))

(defn parse-cdc [file]
 (let [rs (cdc/parse-csv (slurp file))]
  (prn (str "rs=" rs))
  (prn (pp/cl-format nil "cdc: rows: ~a~&amp;" (count rs)))
  (prn (pp/cl-format nil "cdc: ~a~&amp;" rs))))

(defn -main [&amp; args]
  (prn (format "args=%s" args))
  (if (not (empty? args))
    (do
      (parse-cdc (first args)))))

</pre>
<p>Then to build and run the jar:</p>
<pre class="code">
$ lein compile
$ lein uberjar
$ java -jar cljcsv-standalone.jar input.csv
</pre>
<p>Leiningen makes creating and building Clojure projects quick and easy.  It makes creating an executable jar for your project, which may have many dependencies, about as easy as you can get.</p>
<p class="meta">Kyle Burton, 08 Jun 2010 &#8211; Philadelphia PA</p>
<h5>Special Thanks</h5>
<p>Special thanks to <a href="http://technomancy.us/">technomancy</a>, for creating Leiningen.</p>
<p><br /></p>]]></content:encoded>
    </item>
    
    <item>
      <title>Leiningen</title>
      <link>http://asymmetrical-view.com/2010/06/03/leiningen.html</link>
      <comments>http://asymmetrical-view.com/2010/06/03/leiningen.html#comments</comments>

      <pubDate>2010-06-03T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2010/06/03/leiningen.html</guid>

      <id>http://asymmetrical-view.com/2010/06/03/leiningen</id>
      <description><![CDATA[<h1>Leiningen</h1>
<p><a href="http://github.com/technomancy/leiningen">Leiningen</a> is a simpler build tool for <a href="http://clojure.org/">Clojure</a>.  It is easier to get started with than <a href="http://maven.apache.org/">Maven</a> (though you <a href="http://asymmetrical-view.com/2009/06/22/executable-clojure-jars.html">can do it</a>, as <a href="http://alexott.net/en/clojure/ClojureMaven.html">more than one</a> <a href="http://muckandbrass.com/web/display/~cemerick/2010/03/25/Why+using+Maven+for+Clojure+builds+is+a+no-brainer">post shows</a>), as well as <a href="http://ant.apache.org/">ant</a>.</p>
<p>Leiningen is, as maven is, rooted in convention over configuration to reduce the complexity of its build configuration.  Leiningen expects your Clojure source code to be in <code>&lt;project&gt;/src</code> and your tests to be in <code>&lt;project&gt;/test</code>.  These can be overridden with <code>:source-path</code> and <code>:test-path</code> respectively.</p>
<p>You create a <code>project.clj</code> in your project&#8217;s root directory to control how Leiningen builds your project.  Leiningen manages your dependencies in a brief syntax using the same dependency resolution system as maven, and it integrates with <a href="http://clojars.org/">Clojars</a>, a jar repository for Clojure projects (which is also a maven repository), both for pulling dependencies as well as allowing you to upload your own open source projects to the remote repository.</p>
<p>There is a full walk through for installing and getting started with Leiningen that is part of the <a href="http://github.com/technomancy/leiningen">Leiningen documentation</a>, so I am going to focus on what I found useful that isn&#8217;t already part of that guide and only show the basics of getting started &#8211; you should refer to <a href="http://github.com/technomancy/leiningen">that page</a> (or the <a href="http://groups.google.com/group/leiningen">google group</a>) for more information.</p>
<h2>Dependency Version Strings</h2>
<p>For those of you who have never used Maven, it is worth reading about <a href="http://github.com/technomancy/leiningen/blob/master/INTRO.md">maven version strings</a> to familiarize yourself with how they work and the effect that something like <code>SNAPSHOT</code> in the version string will have on your build.</p>
<h2><code>:warn-on-reflection</code></h2>
<p><code>:warn-on-reflection</code> is used to set the Clojure compiler option for warning on reflection.  This will point out where adding in Clojure (make this a link) type declarations will help speed up your code.</p>
<h2><code>:dependencies</code></h2>
<p><code>:dependencies</code> specifies a list of pairs of project and version string of the libraries you depend on.</p>
<h2><code>:dev-dependencies</code></h2>
<p><code>:dev-dependencies</code> is similar to <code>:dependencies</code>, but the dependencies are not considered to be run-time dependencies, they are only for use by Leiningen during the build.  The one I most commonly use is <code>swank-clojure</code>.</p>
<h2>Example project.clj</h2>
<p>This example is from the <a href="http://github.com/kyleburton/clj-bloom">clj-bloom</a> library</p>
<pre class="code">
(defproject com.github.kyleburton/clj-bloom "1.0.1"
  :description "Bloom Filter implementation in Clojure, see also: http://github.com/kyleburton/clj-bloom"
  :warn-on-reflection true
  :dependencies
  [[org.clojure/clojure "1.1.0"]
   [org.clojure/clojure-contrib "1.1.0"]]
  :dev-dependencies
  [[swank-clojure "1.2.1"]])
</pre>
<h2>Common Leiningen Commands</h2>
<h3><code>lein deps</code></h3>
<p>Prior to version 1.2 of Leiningen, it did not have a build life cycle.  With 1.2 it does, this means that it understands that <code>test</code> depends on <code>compile</code>, similar to how <a href="http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html">maven&#8217;s life-cycle works</a>.  If you&#8217;re using a version older than 1.2 and you get a message like: <code>"Exception in thread "main" java.lang.NoClassDefFoundError: clojure/main"</code> it is dues to the dependencies not yet having been pulled down.</p>
<p>This most often happened to me right after a <code>lein clean</code>.  Thankfully Leiningen uses the same caching strategy that Maven does so the second time you run <code>lein deps</code> it will be much quicker as all it needs to do is pull the dependencies from your <code>~/.m2/repository</code> directory.  Currently it copies the file, in the future my hope is that it will use a <a href="http://java.sun.com/docs/books/tutorial/essential/io/links.html#symLink">symlink</a>, which will be supported by <a href="http://java.sun.com/developer/technicalArticles/javase/nio/">Java7</a>.</p>
<h3><code>lein test</code></h3>
<p>You can run your <a href="http://richhickey.github.com/clojure/clojure.test-api.html"><code>clojure.test</code></a> based tests with <code>lein test</code>:</p>
<pre class="code">
kyle@indigo64 ~/personal/projects/clj-bloom[master]$ lein test
[null] Testing com.github.kyleburton.clj-bloom-test
[null] Ran 5 tests containing 21 assertions.
[null] 0 failures, 0 errors.
[null] --------------------
[null] Total:
[null] Ran 5 tests containing 21 assertions.
[null] 0 failures, 0 errors.
kyle@indigo64 ~/personal/projects/clj-bloom[master]$ echo $?
0
kyle@indigo64 ~/personal/projects/clj-bloom[master]$
</pre>
<p>As the example shows, a drawback of the pre 1.2 versions of Leiningen is that they do not set the exit code of the process on test or compilation failure to a non-zero value.  This makes those versions difficult to use from other software (like deployment or <a href="http://hudson-ci.org/">continuous integration tools</a>.</p>
<p>Thankfully this is one of the fixes in the 1.2 branch, among <a href="http://github.com/technomancy/leiningen/blob/master/NEWS">many others</a>.  You can run the 1.2 branch, or the <span class="caps">HEAD</span> pretty easily by first having a working stable release of Leiningen, building it and then either symlinking or aliasing <code>lein</code> to point to the checked out copy:</p>
<pre class="code">
kyle@indigo64 ~/personal/projects$ git clone http://github.com/technomancy/leiningen.git
kyle@indigo64 ~/personal/projects$ cd leiningen
kyle@indigo64 ~/personal/projects/leiningen[master]$ lein deps
kyle@indigo64 ~/personal/projects/leiningen[master]$ lein compile
kyle@indigo64 ~/personal/projects/leiningen[master]$ alias lein=~/personal/projects/leiningen/bin/lein
kyle@indigo64 ~/personal/projects/leiningen[master]$
</pre>
<p>After doing that, going back into the project directory, now <code>lein test</code> sets the exit code:</p>
<pre class="code">
kyle@indigo64 ~/personal/projects/clj-bloom[master]$ lein test
     [null] Testing com.github.kyleburton.clj-bloom-test
     [null] FAIL in (make-hash-fn-hash-code-test) (clj_bloom_test.clj:9)
     [null] test the hash-fn helper
     [null] expected: (not (= (.hashCode "foo1") ((bf/make-hash-fn-hash-code "1") "foo" 4294967295)))
     [null]   actual: (not (not true))
     [null] Ran 5 tests containing 21 assertions.
     [null] 1 failures, 0 errors.
     [null] --------------------
     [null] Total:
     [null] Ran 5 tests containing 21 assertions.
     [null] 1 failures, 0 errors.
kyle@indigo64 ~/personal/projects/clj-bloom[master]$ echo $?
1
kyle@indigo64 ~/personal/projects/clj-bloom[master]$
</pre>
<h2>Emacs + <span class="caps">SLIME</span> Integration</h2>
<p><img src="/images/2009-08/emacs-swank-clojure-1.png" style="float: right; padding: 1em;" /></p>
<p>Leiningen eases the integration with <a href="http://www.gnu.org/software/emacs/">Emacs</a> and <a href="http://common-lisp.net/project/slime/"><span class="caps">SLIME</span></a>.  <span class="caps">SLIME</span> provides a rich development environment for Clojure.  I&#8217;ve written previously about <span class="caps">SLIME</span> and Clojure (<a href="/2009/08/20/emacs-slime-remote-repl.html">Connecting to a remote <span class="caps">REPL</span></a>).  Leiningen provides the ability to run a swank server with the <a href="http://github.com/jochu/swank-clojure/blob/master/src/leiningen/swank.clj">lein-swank</a> plug-in which is part of <a href="http://github.com/jochu/swank-clojure">swank-clojure</a>.</p>
<p>See <a href="http://freegeek.in/blog/2009/08/setting-up-emacs-clojure-with-emacs-starter-kit/">Setting up Emacs &amp; Clojure with Emacs Starter Kit</a> or <a href="http://clojurous.posterous.com/setting-up-clojure-with-emacs-and-leiningen">Setting up Clojure with Emacs and Leiningen</a> for how to get Emacs configured for Clojure development.</p>
<p>The swank server is the back-end portion of <span class="caps">SLIME</span>.  It listens to a socket in the <span class="caps">JVM</span> where your Clojure code is running and allows Emacs to connect to and interact with it, compiling and executing code, inspecting values and providing services like code completion and documentation look-up.</p>
<p>The example <code>project.clj</code> above shows how to reference <code>swank-clojure</code> as a dev-dependency.</p>
<p>You can start a swank server for your project, with all your project&#8217;s dependencies by running:</p>
<pre class="code">
kyle@indigo64 ~/personal/projects/clj-bloom[master]$ lein swank
     [null] user=&gt; Connection opened on local port  4005
     [null] #&lt;ServerSocket ServerSocket[addr=localhost/127.0.0.1,port=0,localport=4005]&gt;
</pre>
<p>Then from Emacs, execute <code>M-x slime-connect</code> and accept the defaults (localhost and a port of 4005).</p>
<p>That runs the swank sever on the default port, 4005.  If you want to be able to run multiple swank servers on different ports (perhaps you&#8217;re working with multiple projects), just pass the additional arguments to the lein-swank plug-in, which are the port then the host (if your machine is known by more than one name or has more than one interface):</p>
<pre class="code">
kyle@indigo64 ~/personal/projects/clj-bloom[master]$ lein swank 4006
     [null] user=&gt; Connection opened on local port  4006
     [null] #&lt;ServerSocket ServerSocket[addr=localhost/127.0.0.1,port=0,localport=4006]&gt;
</pre>
<p>I&#8217;ve found Leiningen to be a simple, easy to use alternative to using Ant or Maven for building your code.</p>
<p class="meta">Kyle Burton, 03 Jun 2010 &#8211; Philadelphia PA</p>
<h5>Special Thanks</h5>
<p>Special thanks to <a href="http://technomancy.us/">technomancy</a>, for creating Leiningen.</p>
<p><br /></p>]]></description>
      <content:encoded><![CDATA[<h1>Leiningen</h1>
<p><a href="http://github.com/technomancy/leiningen">Leiningen</a> is a simpler build tool for <a href="http://clojure.org/">Clojure</a>.  It is easier to get started with than <a href="http://maven.apache.org/">Maven</a> (though you <a href="http://asymmetrical-view.com/2009/06/22/executable-clojure-jars.html">can do it</a>, as <a href="http://alexott.net/en/clojure/ClojureMaven.html">more than one</a> <a href="http://muckandbrass.com/web/display/~cemerick/2010/03/25/Why+using+Maven+for+Clojure+builds+is+a+no-brainer">post shows</a>), as well as <a href="http://ant.apache.org/">ant</a>.</p>
<p>Leiningen is, as maven is, rooted in convention over configuration to reduce the complexity of its build configuration.  Leiningen expects your Clojure source code to be in <code>&lt;project&gt;/src</code> and your tests to be in <code>&lt;project&gt;/test</code>.  These can be overridden with <code>:source-path</code> and <code>:test-path</code> respectively.</p>
<p>You create a <code>project.clj</code> in your project&#8217;s root directory to control how Leiningen builds your project.  Leiningen manages your dependencies in a brief syntax using the same dependency resolution system as maven, and it integrates with <a href="http://clojars.org/">Clojars</a>, a jar repository for Clojure projects (which is also a maven repository), both for pulling dependencies as well as allowing you to upload your own open source projects to the remote repository.</p>
<p>There is a full walk through for installing and getting started with Leiningen that is part of the <a href="http://github.com/technomancy/leiningen">Leiningen documentation</a>, so I am going to focus on what I found useful that isn&#8217;t already part of that guide and only show the basics of getting started &#8211; you should refer to <a href="http://github.com/technomancy/leiningen">that page</a> (or the <a href="http://groups.google.com/group/leiningen">google group</a>) for more information.</p>
<h2>Dependency Version Strings</h2>
<p>For those of you who have never used Maven, it is worth reading about <a href="http://github.com/technomancy/leiningen/blob/master/INTRO.md">maven version strings</a> to familiarize yourself with how they work and the effect that something like <code>SNAPSHOT</code> in the version string will have on your build.</p>
<h2><code>:warn-on-reflection</code></h2>
<p><code>:warn-on-reflection</code> is used to set the Clojure compiler option for warning on reflection.  This will point out where adding in Clojure (make this a link) type declarations will help speed up your code.</p>
<h2><code>:dependencies</code></h2>
<p><code>:dependencies</code> specifies a list of pairs of project and version string of the libraries you depend on.</p>
<h2><code>:dev-dependencies</code></h2>
<p><code>:dev-dependencies</code> is similar to <code>:dependencies</code>, but the dependencies are not considered to be run-time dependencies, they are only for use by Leiningen during the build.  The one I most commonly use is <code>swank-clojure</code>.</p>
<h2>Example project.clj</h2>
<p>This example is from the <a href="http://github.com/kyleburton/clj-bloom">clj-bloom</a> library</p>
<pre class="code">
(defproject com.github.kyleburton/clj-bloom "1.0.1"
  :description "Bloom Filter implementation in Clojure, see also: http://github.com/kyleburton/clj-bloom"
  :warn-on-reflection true
  :dependencies
  [[org.clojure/clojure "1.1.0"]
   [org.clojure/clojure-contrib "1.1.0"]]
  :dev-dependencies
  [[swank-clojure "1.2.1"]])
</pre>
<h2>Common Leiningen Commands</h2>
<h3><code>lein deps</code></h3>
<p>Prior to version 1.2 of Leiningen, it did not have a build life cycle.  With 1.2 it does, this means that it understands that <code>test</code> depends on <code>compile</code>, similar to how <a href="http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html">maven&#8217;s life-cycle works</a>.  If you&#8217;re using a version older than 1.2 and you get a message like: <code>"Exception in thread "main" java.lang.NoClassDefFoundError: clojure/main"</code> it is dues to the dependencies not yet having been pulled down.</p>
<p>This most often happened to me right after a <code>lein clean</code>.  Thankfully Leiningen uses the same caching strategy that Maven does so the second time you run <code>lein deps</code> it will be much quicker as all it needs to do is pull the dependencies from your <code>~/.m2/repository</code> directory.  Currently it copies the file, in the future my hope is that it will use a <a href="http://java.sun.com/docs/books/tutorial/essential/io/links.html#symLink">symlink</a>, which will be supported by <a href="http://java.sun.com/developer/technicalArticles/javase/nio/">Java7</a>.</p>
<h3><code>lein test</code></h3>
<p>You can run your <a href="http://richhickey.github.com/clojure/clojure.test-api.html"><code>clojure.test</code></a> based tests with <code>lein test</code>:</p>
<pre class="code">
kyle@indigo64 ~/personal/projects/clj-bloom[master]$ lein test
[null] Testing com.github.kyleburton.clj-bloom-test
[null] Ran 5 tests containing 21 assertions.
[null] 0 failures, 0 errors.
[null] --------------------
[null] Total:
[null] Ran 5 tests containing 21 assertions.
[null] 0 failures, 0 errors.
kyle@indigo64 ~/personal/projects/clj-bloom[master]$ echo $?
0
kyle@indigo64 ~/personal/projects/clj-bloom[master]$
</pre>
<p>As the example shows, a drawback of the pre 1.2 versions of Leiningen is that they do not set the exit code of the process on test or compilation failure to a non-zero value.  This makes those versions difficult to use from other software (like deployment or <a href="http://hudson-ci.org/">continuous integration tools</a>.</p>
<p>Thankfully this is one of the fixes in the 1.2 branch, among <a href="http://github.com/technomancy/leiningen/blob/master/NEWS">many others</a>.  You can run the 1.2 branch, or the <span class="caps">HEAD</span> pretty easily by first having a working stable release of Leiningen, building it and then either symlinking or aliasing <code>lein</code> to point to the checked out copy:</p>
<pre class="code">
kyle@indigo64 ~/personal/projects$ git clone http://github.com/technomancy/leiningen.git
kyle@indigo64 ~/personal/projects$ cd leiningen
kyle@indigo64 ~/personal/projects/leiningen[master]$ lein deps
kyle@indigo64 ~/personal/projects/leiningen[master]$ lein compile
kyle@indigo64 ~/personal/projects/leiningen[master]$ alias lein=~/personal/projects/leiningen/bin/lein
kyle@indigo64 ~/personal/projects/leiningen[master]$
</pre>
<p>After doing that, going back into the project directory, now <code>lein test</code> sets the exit code:</p>
<pre class="code">
kyle@indigo64 ~/personal/projects/clj-bloom[master]$ lein test
     [null] Testing com.github.kyleburton.clj-bloom-test
     [null] FAIL in (make-hash-fn-hash-code-test) (clj_bloom_test.clj:9)
     [null] test the hash-fn helper
     [null] expected: (not (= (.hashCode "foo1") ((bf/make-hash-fn-hash-code "1") "foo" 4294967295)))
     [null]   actual: (not (not true))
     [null] Ran 5 tests containing 21 assertions.
     [null] 1 failures, 0 errors.
     [null] --------------------
     [null] Total:
     [null] Ran 5 tests containing 21 assertions.
     [null] 1 failures, 0 errors.
kyle@indigo64 ~/personal/projects/clj-bloom[master]$ echo $?
1
kyle@indigo64 ~/personal/projects/clj-bloom[master]$
</pre>
<h2>Emacs + <span class="caps">SLIME</span> Integration</h2>
<p><img src="/images/2009-08/emacs-swank-clojure-1.png" style="float: right; padding: 1em;" /></p>
<p>Leiningen eases the integration with <a href="http://www.gnu.org/software/emacs/">Emacs</a> and <a href="http://common-lisp.net/project/slime/"><span class="caps">SLIME</span></a>.  <span class="caps">SLIME</span> provides a rich development environment for Clojure.  I&#8217;ve written previously about <span class="caps">SLIME</span> and Clojure (<a href="/2009/08/20/emacs-slime-remote-repl.html">Connecting to a remote <span class="caps">REPL</span></a>).  Leiningen provides the ability to run a swank server with the <a href="http://github.com/jochu/swank-clojure/blob/master/src/leiningen/swank.clj">lein-swank</a> plug-in which is part of <a href="http://github.com/jochu/swank-clojure">swank-clojure</a>.</p>
<p>See <a href="http://freegeek.in/blog/2009/08/setting-up-emacs-clojure-with-emacs-starter-kit/">Setting up Emacs &amp; Clojure with Emacs Starter Kit</a> or <a href="http://clojurous.posterous.com/setting-up-clojure-with-emacs-and-leiningen">Setting up Clojure with Emacs and Leiningen</a> for how to get Emacs configured for Clojure development.</p>
<p>The swank server is the back-end portion of <span class="caps">SLIME</span>.  It listens to a socket in the <span class="caps">JVM</span> where your Clojure code is running and allows Emacs to connect to and interact with it, compiling and executing code, inspecting values and providing services like code completion and documentation look-up.</p>
<p>The example <code>project.clj</code> above shows how to reference <code>swank-clojure</code> as a dev-dependency.</p>
<p>You can start a swank server for your project, with all your project&#8217;s dependencies by running:</p>
<pre class="code">
kyle@indigo64 ~/personal/projects/clj-bloom[master]$ lein swank
     [null] user=&gt; Connection opened on local port  4005
     [null] #&lt;ServerSocket ServerSocket[addr=localhost/127.0.0.1,port=0,localport=4005]&gt;
</pre>
<p>Then from Emacs, execute <code>M-x slime-connect</code> and accept the defaults (localhost and a port of 4005).</p>
<p>That runs the swank sever on the default port, 4005.  If you want to be able to run multiple swank servers on different ports (perhaps you&#8217;re working with multiple projects), just pass the additional arguments to the lein-swank plug-in, which are the port then the host (if your machine is known by more than one name or has more than one interface):</p>
<pre class="code">
kyle@indigo64 ~/personal/projects/clj-bloom[master]$ lein swank 4006
     [null] user=&gt; Connection opened on local port  4006
     [null] #&lt;ServerSocket ServerSocket[addr=localhost/127.0.0.1,port=0,localport=4006]&gt;
</pre>
<p>I&#8217;ve found Leiningen to be a simple, easy to use alternative to using Ant or Maven for building your code.</p>
<p class="meta">Kyle Burton, 03 Jun 2010 &#8211; Philadelphia PA</p>
<h5>Special Thanks</h5>
<p>Special thanks to <a href="http://technomancy.us/">technomancy</a>, for creating Leiningen.</p>
<p><br /></p>]]></content:encoded>
    </item>
    
    <item>
      <title>From the Agony of JUnit to the Ecstasy of RSpec</title>
      <link>http://asymmetrical-view.com/2010/02/19/maven-rspec.html</link>
      <comments>http://asymmetrical-view.com/2010/02/19/maven-rspec.html#comments</comments>

      <pubDate>2010-02-19T00:00:00-05:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2010/02/19/maven-rspec.html</guid>

      <id>http://asymmetrical-view.com/2010/02/19/maven-rspec</id>
      <description><![CDATA[<h1>From the Agony of JUnit to the Ecstasy of RSpec</h1>
<p><img src="/images/2010-02/boxer.gif" style="float: left; padding: 1em; " /></p>
<p>In the past I have had a love hate relationship with unit testing and testing tools in general.  I have had a long, healthy, even dreamy relationship with test driven development though.  Aahh how it improves design and prevents issues from reaching users!</p>
<p><img src="/images/2010-02/Gun-223x150.jpg" style="float: right; padding: 1em; " /></p>
<p>I am often unhappy with the amount of effort it takes to write tests using some of the tools and libraries out there.  I&#8217;ve been around the block from Perl to Lisp to Java, even C++ and C (I found using <a href="http://www.call-with-current-continuation.org/">Chicken</a> to be an easy way to write tests for C libraries, but I digress&#8230;)  I have found, both with myself and with teams I&#8217;ve worked with, that if the effort of writing tests is high enough, less (or no) tests will be written.  This is partly because test themselves do not represent business value or end-user features, so most things you can do to reduce the effort of writing or running tests will cause more tests to be written.  This includes not just the boilerplate set up and typing you have to do, but the amount of time it takes to run your tests (long running tests unfortunately re-introduce the flow destroying edit-compile-debug cycle back into modern dynamic application development).  Reducing effort is, of course, dependent on <span class="caps">ROI</span>, which is different for each person and team.</p>
<p>A good friend of mine, <a href="http://plpatterns.com/">Jon Tran</a>, pushes the idea that if you can make something abundant (nearly free) you haven&#8217;t just made something better, you&#8217;ve made something entirely different.  I love this idea and try to use it to guide process and tool improvements for myself and my team.</p>
<p><img src="/images/2010-02/BouncingDuke-small.gif" style="float: left; padding: 1em; " /></p>
<p>When I started working with <a href="http://rubyonrails.org/">Ruby on Rails</a> I found testing to be so well integrated into how you worked on your Rails project that it was, in fact, abundant.  It was so much easier to test your code that writing tests was no longer a chore, but it fit easily, even joyfully into the work-flow.  Working more recently with a Rails expert, <a href="http://trottercashion.com/">Trotter Cashion</a>, I was introduced to <a href="http://rspec.info/">RSpec</a>.  Our team was also blessed one fine day by a visit from <a href="http://apprentice.kfitz.me/">Kevin Fitzpatrick</a> who bootstrapped our use of <a href="http://cukes.info/">Cucumber</a> in a single afternoon pairing session.</p>
<p>These two tools were pure love.  They gave me the same kind of feelings that declarative and functional programming give me &#8211; you say what you want it to be, not just how you want it to get there.  RSpec made unit testing even more abundant, Cucumber made front end or integration testing abundant.  Those two tools went a long way to helping our team write more tests and more effective tests, improving the design of our code, applications and ultimately reducing the number of issues (especially regressions) that made it both to and past our excellent QA testers (we&#8217;re only human after all).</p>
<p>Writing unit tests for the Java portions of our systems I have really started to miss the clarity and abundance that RSpec provided.  Then I stumbled across the <a href="http://www.fnokd.com/2008/09/18/maven-java-and-rspec/">maven-rspec-plugin</a> which uses JRuby to execute rspec base tests during the test phase of the maven life cycle.</p>
<p>The storm clouds have parted and the sun is shining again.  This is exactly what I was looking for; I just hadn&#8217;t known it until I found it.</p>
<div><img src="/images/2010-02/testing-venn.png" style="padding: 1em; " /></div>
<p>We&#8217;re already using <a href="http://jruby.org/">JRuby</a> within the project and have been happy with the access to all of the <span class="caps">JVM</span> based libraries it provides to us (not to mention easy integration with our <a href="http://clojure.org/">Clojure</a> code, but that&#8217;s another post altogether).  The tools are a great fit for our team, we&#8217;re already familiar with Ruby, RSpec and writing those kinds of tests &#8211; just not yet in our Java portions of the application.</p>
<p>On your mark, get set&#8230;I followed the instructions in that post, but ended up with a NullPointerException when the plugin tried to write out the runner shell script.  I checked out the code from the CodeHaus svn repository and poked around until I found a work around, it seems that the plugin requires a <code>systemProperties</code> tag in its configuration, even if it&#8217;s not used, to prevent the <code>NPE</code>.  It just has to be present with at least one property present.</p>
<p><a href="http://www.innovationontherun.com/">Rob DiMarco</a> discovered that the plugin, rspec or something about this confluence of tools and libraries doesn&#8217;t work on JRuby 1.4 (see <a href="http://github.com/kyleburton/sandbox/issues/#issue/1">the stacktrace</a> for more information), so make sure you download and install JRuby 1.3.1 for now.</p>
<p>To get started you&#8217;ll need <a href="http://jruby.org/download">JRuby</a> installed, make sure you get <a href="http://jruby.kenai.com/downloads/1.3.1/jruby-bin-1.3.1.tar.gz">1.3.1</a> and you&#8217;ll have to set the <code>JRUBY_HOME</code> environment variable to point to your installation.  You&#8217;ll need <a href="http://maven.apache.org/">maven</a> of course as well.</p>
<p>The plugin configuration we were able to get working is the <code>pom.xml</code> fragment you see here:</p>
<pre class="code">
   &lt;plugin&gt;
     &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
     &lt;artifactId&gt;rspec-maven-plugin&lt;/artifactId&gt;
     &lt;configuration&gt;
       &lt;jrubyHome&gt;${env.JRUBY_HOME}&lt;/jrubyHome&gt;
       &lt;sourceDirectory&gt;${basedir}/src/test/specs&lt;/sourceDirectory&gt;
       &lt;outputDirectory&gt;${basedir}/target&lt;/outputDirectory&gt;
       &lt;systemProperties&gt;
         &lt;property&gt;&lt;name&gt;testProp&lt;/name&gt;&lt;value&gt;testValue&lt;/value&gt;&lt;/property&gt;
       &lt;/systemProperties&gt;
     &lt;/configuration&gt;
     &lt;executions&gt;
       &lt;execution&gt;
         &lt;id&gt;test&lt;/id&gt;
         &lt;phase&gt;test&lt;/phase&gt;
         &lt;goals&gt;
           &lt;goal&gt;spec&lt;/goal&gt;
         &lt;/goals&gt;
       &lt;/execution&gt;
     &lt;/executions&gt;
   &lt;/plugin&gt;
</pre>
<p><img src="/images/2010-02/Juggler-268x310.gif" style="float: right; padding: 1em; " /></p>
<p>This configures rspec to be run during the test phase of the maven build.  It also configures the plugin to look for spec tests within the src/test/specs directory.  When first executed, the plugin will create two helper scripts in the project&#8217;s <code>target/</code> directory: <code>rspec-runner.rb</code> and <code>run-rspecs.sh</code>.  The <code>run-rspecs.sh</code> can be used to run the tests more quickly and succinctly from the command line, as opposed to relying on <code>mvn test</code> to execute the tests.  The runner shell script passes its arguments through to rspec, so you can use all the <a href="http://rspec.info/documentation/tools/spec.html">features the rspec runner supports</a>, like running a single spec file or a single test within a spec (by line number or name).</p>
<h2>Example Maven Project</h2>
<p>I&#8217;ve created an example Maven project in my <a href="http://github.com/kyleburton/sandbox/tree/master/examples/maven/rspec/">github sandbox</a> that you should be able to use as a reference or starting point for your own project.  If it doesn&#8217;t work for you, after following the instructions, please let me know and I&#8217;ll try to work through any issues with you.</p>
<p>The sample project includes a single java class (<code>SomeClass</code>) and a single spec test which exercises it.  It is meant as a minimal working example at the moment, as I explore using RSpec for our Java testing I&#8217;ll try to keep it up to date with any new findings (and I hope to figure out how to get it working with JRuby 1.4).</p>
<p>The Java code is a simple class with a few members including a method to fetch a url:</p>
<pre class="code">

package com.github.kyleburton;

import org.apache.commons.io.IOUtils;

import java.net.*;
import java.io.*;

public class SomeClass {
  private String _userName;
  private String _remoteUrl;
  private String _theContent = null;
  private Downloader _downloader;

  public SomeClass() {
    _userName = "*a default*";
    _remoteUrl = "http://localhost/";
    _downloader = new Downloader(_remoteUrl);
  }

  public SomeClass(String name, String url) {
    _userName = name;
    _remoteUrl = url;
    _downloader = new Downloader(url);
  }

  public String getContent() throws IOException {
    if ( null == _theContent )
      _theContent = _downloader.download();

    return _theContent;
  }

  public String getUserName() {
    return _userName;
  }

  public void setUserName(String userName) {
    _userName = userName;
  }

  public String getRemoteUrl() {
    return _remoteUrl;
  }

  public void setRemoteUrl(String remoteUrl) {
    _remoteUrl = remoteUrl;
    _downloader = new Downloader(_remoteUrl);
  }

  public void setDownloader(Downloader downloader) {
    _downloader = downloader;
  }

  public static class Downloader {

    private String url;
    public Downloader(String url) {
      this.url = url;
    }

    public String download() throws IOException {
      return IOUtils.toString(new URL(url).openStream());
    }
  }

}
</pre>
<p>The rspec test exercises the class, including using <a href="http://mockito.org/">Mockito</a> to ensure that <code>getContent</code> actually delegates to the <code>Downloader</code> class to fetch the remote data (without it actually going out and hitting a website).</p>
<pre class="code">
import com.github.kyleburton.SomeClass
import org.mockito.Mockito

describe SomeClass do
  before(:each) do
    @the_name = "a user"
    @the_url = "http://asymmetrical-view.com/"
    @some_class = SomeClass.new @the_name, @the_url
  end

  it "should accept constructor parameters" do
    @some_class.user_name.should == @the_name
    @some_class.remote_url.should == @the_url
  end

  it "should download the conten when content is accessedt" do
    some_content = "this is some content"
    downloader = Mockito.mock(SomeClass::Downloader.java_class)
    Mockito.when(downloader.download()).then_return(some_content)
    @some_class.downloader = downloader
    @some_class.content.should_not be_empty
    @some_class.content.should == some_content
  end
end
</pre>
<p>Finally here is an exmaple of how you can run <code>irb</code> to get a Ruby <span class="caps">REPL</span> for your project with all of your project dependencies on the classpath and available in <code>irb</code> (assuming you&#8217;ve compiled it with maven first):</p>
<pre class="code">
# run-jirb.sh
CLASSPATH="target/test-classes:target/classes"
CLASSPATH="$CLASSPATH:`mvn -Dmdep.outputFile=/dev/stderr dependency:build-classpath 2&gt;&amp;1 &gt; /dev/null`"
export CLASSPATH

jirb "$@"
</pre>
<p><img src="/images/2010-02/jruby-rspec.png" style="float: right; padding: 1em; " /></p>
<h2>Conclusion</h2>
<p>Being able to use RSpec to test our Java and Clojure code-bases is going to help our team be more productive, it will bring the same sense of fun to working on these parts of our system &#8211; reduce the effort it takes and leading to more tests.  I am quite satisfied with the improvement in morale it has brought to the team when we&#8217;re working in these areas just in the first few days we&#8217;ve had it.</p>
<p><img src="/images/2010-02/NyaNya-240x273.jpg" style="right: left; padding: 1em; " /></p>
<p class="meta">Kyle Burton, 03 Feb 2010 &#8211; Philadelphia PA</p>
<h5>Special Thanks</h5>
<p>Special thanks to <a href="http://plpatterns.com/">Jon Tran</a> for reading drafts of this post.</p>
<h5>Image and Photo Credits</h5>
<ul>
	<li>&#8220;Duke&#8221; Pictures Courtesy of <a href="http://kenai.com/projects/duke/pages/Home">Project Kenai</a></li>
	<li><a href="http://asymmetrical-view.com/">Diagrams</a></li>
</ul>
<p><br /></p>]]></description>
      <content:encoded><![CDATA[<h1>From the Agony of JUnit to the Ecstasy of RSpec</h1>
<p><img src="/images/2010-02/boxer.gif" style="float: left; padding: 1em; " /></p>
<p>In the past I have had a love hate relationship with unit testing and testing tools in general.  I have had a long, healthy, even dreamy relationship with test driven development though.  Aahh how it improves design and prevents issues from reaching users!</p>
<p><img src="/images/2010-02/Gun-223x150.jpg" style="float: right; padding: 1em; " /></p>
<p>I am often unhappy with the amount of effort it takes to write tests using some of the tools and libraries out there.  I&#8217;ve been around the block from Perl to Lisp to Java, even C++ and C (I found using <a href="http://www.call-with-current-continuation.org/">Chicken</a> to be an easy way to write tests for C libraries, but I digress&#8230;)  I have found, both with myself and with teams I&#8217;ve worked with, that if the effort of writing tests is high enough, less (or no) tests will be written.  This is partly because test themselves do not represent business value or end-user features, so most things you can do to reduce the effort of writing or running tests will cause more tests to be written.  This includes not just the boilerplate set up and typing you have to do, but the amount of time it takes to run your tests (long running tests unfortunately re-introduce the flow destroying edit-compile-debug cycle back into modern dynamic application development).  Reducing effort is, of course, dependent on <span class="caps">ROI</span>, which is different for each person and team.</p>
<p>A good friend of mine, <a href="http://plpatterns.com/">Jon Tran</a>, pushes the idea that if you can make something abundant (nearly free) you haven&#8217;t just made something better, you&#8217;ve made something entirely different.  I love this idea and try to use it to guide process and tool improvements for myself and my team.</p>
<p><img src="/images/2010-02/BouncingDuke-small.gif" style="float: left; padding: 1em; " /></p>
<p>When I started working with <a href="http://rubyonrails.org/">Ruby on Rails</a> I found testing to be so well integrated into how you worked on your Rails project that it was, in fact, abundant.  It was so much easier to test your code that writing tests was no longer a chore, but it fit easily, even joyfully into the work-flow.  Working more recently with a Rails expert, <a href="http://trottercashion.com/">Trotter Cashion</a>, I was introduced to <a href="http://rspec.info/">RSpec</a>.  Our team was also blessed one fine day by a visit from <a href="http://apprentice.kfitz.me/">Kevin Fitzpatrick</a> who bootstrapped our use of <a href="http://cukes.info/">Cucumber</a> in a single afternoon pairing session.</p>
<p>These two tools were pure love.  They gave me the same kind of feelings that declarative and functional programming give me &#8211; you say what you want it to be, not just how you want it to get there.  RSpec made unit testing even more abundant, Cucumber made front end or integration testing abundant.  Those two tools went a long way to helping our team write more tests and more effective tests, improving the design of our code, applications and ultimately reducing the number of issues (especially regressions) that made it both to and past our excellent QA testers (we&#8217;re only human after all).</p>
<p>Writing unit tests for the Java portions of our systems I have really started to miss the clarity and abundance that RSpec provided.  Then I stumbled across the <a href="http://www.fnokd.com/2008/09/18/maven-java-and-rspec/">maven-rspec-plugin</a> which uses JRuby to execute rspec base tests during the test phase of the maven life cycle.</p>
<p>The storm clouds have parted and the sun is shining again.  This is exactly what I was looking for; I just hadn&#8217;t known it until I found it.</p>
<div><img src="/images/2010-02/testing-venn.png" style="padding: 1em; " /></div>
<p>We&#8217;re already using <a href="http://jruby.org/">JRuby</a> within the project and have been happy with the access to all of the <span class="caps">JVM</span> based libraries it provides to us (not to mention easy integration with our <a href="http://clojure.org/">Clojure</a> code, but that&#8217;s another post altogether).  The tools are a great fit for our team, we&#8217;re already familiar with Ruby, RSpec and writing those kinds of tests &#8211; just not yet in our Java portions of the application.</p>
<p>On your mark, get set&#8230;I followed the instructions in that post, but ended up with a NullPointerException when the plugin tried to write out the runner shell script.  I checked out the code from the CodeHaus svn repository and poked around until I found a work around, it seems that the plugin requires a <code>systemProperties</code> tag in its configuration, even if it&#8217;s not used, to prevent the <code>NPE</code>.  It just has to be present with at least one property present.</p>
<p><a href="http://www.innovationontherun.com/">Rob DiMarco</a> discovered that the plugin, rspec or something about this confluence of tools and libraries doesn&#8217;t work on JRuby 1.4 (see <a href="http://github.com/kyleburton/sandbox/issues/#issue/1">the stacktrace</a> for more information), so make sure you download and install JRuby 1.3.1 for now.</p>
<p>To get started you&#8217;ll need <a href="http://jruby.org/download">JRuby</a> installed, make sure you get <a href="http://jruby.kenai.com/downloads/1.3.1/jruby-bin-1.3.1.tar.gz">1.3.1</a> and you&#8217;ll have to set the <code>JRUBY_HOME</code> environment variable to point to your installation.  You&#8217;ll need <a href="http://maven.apache.org/">maven</a> of course as well.</p>
<p>The plugin configuration we were able to get working is the <code>pom.xml</code> fragment you see here:</p>
<pre class="code">
   &lt;plugin&gt;
     &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
     &lt;artifactId&gt;rspec-maven-plugin&lt;/artifactId&gt;
     &lt;configuration&gt;
       &lt;jrubyHome&gt;${env.JRUBY_HOME}&lt;/jrubyHome&gt;
       &lt;sourceDirectory&gt;${basedir}/src/test/specs&lt;/sourceDirectory&gt;
       &lt;outputDirectory&gt;${basedir}/target&lt;/outputDirectory&gt;
       &lt;systemProperties&gt;
         &lt;property&gt;&lt;name&gt;testProp&lt;/name&gt;&lt;value&gt;testValue&lt;/value&gt;&lt;/property&gt;
       &lt;/systemProperties&gt;
     &lt;/configuration&gt;
     &lt;executions&gt;
       &lt;execution&gt;
         &lt;id&gt;test&lt;/id&gt;
         &lt;phase&gt;test&lt;/phase&gt;
         &lt;goals&gt;
           &lt;goal&gt;spec&lt;/goal&gt;
         &lt;/goals&gt;
       &lt;/execution&gt;
     &lt;/executions&gt;
   &lt;/plugin&gt;
</pre>
<p><img src="/images/2010-02/Juggler-268x310.gif" style="float: right; padding: 1em; " /></p>
<p>This configures rspec to be run during the test phase of the maven build.  It also configures the plugin to look for spec tests within the src/test/specs directory.  When first executed, the plugin will create two helper scripts in the project&#8217;s <code>target/</code> directory: <code>rspec-runner.rb</code> and <code>run-rspecs.sh</code>.  The <code>run-rspecs.sh</code> can be used to run the tests more quickly and succinctly from the command line, as opposed to relying on <code>mvn test</code> to execute the tests.  The runner shell script passes its arguments through to rspec, so you can use all the <a href="http://rspec.info/documentation/tools/spec.html">features the rspec runner supports</a>, like running a single spec file or a single test within a spec (by line number or name).</p>
<h2>Example Maven Project</h2>
<p>I&#8217;ve created an example Maven project in my <a href="http://github.com/kyleburton/sandbox/tree/master/examples/maven/rspec/">github sandbox</a> that you should be able to use as a reference or starting point for your own project.  If it doesn&#8217;t work for you, after following the instructions, please let me know and I&#8217;ll try to work through any issues with you.</p>
<p>The sample project includes a single java class (<code>SomeClass</code>) and a single spec test which exercises it.  It is meant as a minimal working example at the moment, as I explore using RSpec for our Java testing I&#8217;ll try to keep it up to date with any new findings (and I hope to figure out how to get it working with JRuby 1.4).</p>
<p>The Java code is a simple class with a few members including a method to fetch a url:</p>
<pre class="code">

package com.github.kyleburton;

import org.apache.commons.io.IOUtils;

import java.net.*;
import java.io.*;

public class SomeClass {
  private String _userName;
  private String _remoteUrl;
  private String _theContent = null;
  private Downloader _downloader;

  public SomeClass() {
    _userName = "*a default*";
    _remoteUrl = "http://localhost/";
    _downloader = new Downloader(_remoteUrl);
  }

  public SomeClass(String name, String url) {
    _userName = name;
    _remoteUrl = url;
    _downloader = new Downloader(url);
  }

  public String getContent() throws IOException {
    if ( null == _theContent )
      _theContent = _downloader.download();

    return _theContent;
  }

  public String getUserName() {
    return _userName;
  }

  public void setUserName(String userName) {
    _userName = userName;
  }

  public String getRemoteUrl() {
    return _remoteUrl;
  }

  public void setRemoteUrl(String remoteUrl) {
    _remoteUrl = remoteUrl;
    _downloader = new Downloader(_remoteUrl);
  }

  public void setDownloader(Downloader downloader) {
    _downloader = downloader;
  }

  public static class Downloader {

    private String url;
    public Downloader(String url) {
      this.url = url;
    }

    public String download() throws IOException {
      return IOUtils.toString(new URL(url).openStream());
    }
  }

}
</pre>
<p>The rspec test exercises the class, including using <a href="http://mockito.org/">Mockito</a> to ensure that <code>getContent</code> actually delegates to the <code>Downloader</code> class to fetch the remote data (without it actually going out and hitting a website).</p>
<pre class="code">
import com.github.kyleburton.SomeClass
import org.mockito.Mockito

describe SomeClass do
  before(:each) do
    @the_name = "a user"
    @the_url = "http://asymmetrical-view.com/"
    @some_class = SomeClass.new @the_name, @the_url
  end

  it "should accept constructor parameters" do
    @some_class.user_name.should == @the_name
    @some_class.remote_url.should == @the_url
  end

  it "should download the conten when content is accessedt" do
    some_content = "this is some content"
    downloader = Mockito.mock(SomeClass::Downloader.java_class)
    Mockito.when(downloader.download()).then_return(some_content)
    @some_class.downloader = downloader
    @some_class.content.should_not be_empty
    @some_class.content.should == some_content
  end
end
</pre>
<p>Finally here is an exmaple of how you can run <code>irb</code> to get a Ruby <span class="caps">REPL</span> for your project with all of your project dependencies on the classpath and available in <code>irb</code> (assuming you&#8217;ve compiled it with maven first):</p>
<pre class="code">
# run-jirb.sh
CLASSPATH="target/test-classes:target/classes"
CLASSPATH="$CLASSPATH:`mvn -Dmdep.outputFile=/dev/stderr dependency:build-classpath 2&gt;&amp;1 &gt; /dev/null`"
export CLASSPATH

jirb "$@"
</pre>
<p><img src="/images/2010-02/jruby-rspec.png" style="float: right; padding: 1em; " /></p>
<h2>Conclusion</h2>
<p>Being able to use RSpec to test our Java and Clojure code-bases is going to help our team be more productive, it will bring the same sense of fun to working on these parts of our system &#8211; reduce the effort it takes and leading to more tests.  I am quite satisfied with the improvement in morale it has brought to the team when we&#8217;re working in these areas just in the first few days we&#8217;ve had it.</p>
<p><img src="/images/2010-02/NyaNya-240x273.jpg" style="right: left; padding: 1em; " /></p>
<p class="meta">Kyle Burton, 03 Feb 2010 &#8211; Philadelphia PA</p>
<h5>Special Thanks</h5>
<p>Special thanks to <a href="http://plpatterns.com/">Jon Tran</a> for reading drafts of this post.</p>
<h5>Image and Photo Credits</h5>
<ul>
	<li>&#8220;Duke&#8221; Pictures Courtesy of <a href="http://kenai.com/projects/duke/pages/Home">Project Kenai</a></li>
	<li><a href="http://asymmetrical-view.com/">Diagrams</a></li>
</ul>
<p><br /></p>]]></content:encoded>
    </item>
    
    <item>
      <title>Influential Books</title>
      <link>http://asymmetrical-view.com/2009/11/30/influenced-by-books.html</link>
      <comments>http://asymmetrical-view.com/2009/11/30/influenced-by-books.html#comments</comments>

      <pubDate>2009-11-30T00:00:00-05:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2009/11/30/influenced-by-books.html</guid>

      <id>http://asymmetrical-view.com/2009/11/30/influenced-by-books</id>
      <description><![CDATA[<h1>Influential Books</h1>
<p>I started with a new team in the middle of this year and as I get to know the other members of the team and share our skills and experiences, the books that each of us has found influential has come up.  This has given me the opportunity to reflect a bit on which ones I still find worthy of suggesting that others read.  Over my career, and as my family has grown, I have become acutely aware of the value of my free time and that of my co-workers.  With that in mind, I&#8217;m recommending and sharing a lot less than I used to, and since a coworker (Aaron Feng) recently made a point of thanking me for my recommendations I thought I&#8217;d journal what I&#8217;ve been pushing at this new team.</p>
<p><a href="/images/2009-11/bshelf-left1.jpg"><img src="/images/2009-11/bshelf-left1-400x300.jpg" style="float: left; padding: 1em; " /></a></p>
<p>My current bookshelf contains the books it does after several rounds of being distilled over the past ten years or so.  Even so, there is a mix of titles that have been there for years as well as some recent acquisitions that I suspect will have longevity.</p>
<h2><a href="http://www.amazon.com/gp/product/1558607013?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1558607013">Higher-Order Perl: Transforming Programs with Programs</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=1558607013" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by Mark Jason Dominus</h2>
<p>If you program in Java, C#, Python, Ruby or another imperative, stateful language, this is perhaps the best book you can pick up to learn several core fundamentals of functional programming.  It is a great introduction to performing functional programming in an imperative, stateful language.  Mark goes through the process of showing you how to implement things like Haskell&#8217;s infinite sequences, the use of higher order functions, and several other fundamental tenants of functional programming.</p>
<p>I lent my copy to Aaron and it was he that started to tell me where in the book he is seeing some of the techniques that I use on a regular basis.  Mark is a great developer and more than just functional programming comes across in the book, a lot of his skill and clarity of thought does as well.</p>
<p>I feel very sorry for any of you that can not get over the fact that this book&#8217;s code examples are in Perl.</p>
<p><a href="/images/2009-11/bshelf-right1.jpg"><img src="/images/2009-11/bshelf-right1-400x300.jpg" style="float: right; padding: 1em; " /></a></p>
<h2><a href="http://www.amazon.com/gp/product/1558601910?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1558601910">Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=1558601910" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /><br />
, by Peter Norvig</h2>
<p>I picked up <span class="caps">PAIP</span> along with <span class="caps">ANSI</span> Common Lisp (by Paul Graham) with the intention of learning Common Lisp.  I wasn&#8217;t prepared for what was in <span class="caps">PAIP</span> when I first struggled through the book.  I started with an expectation of learning about AI, with little expectation of picking up practical techniques that I&#8217;d be able to apply in my day job developing web applications.   What I got out of the book was much more than I anticipated.  I&#8217;ve gone back to it multiple times and it sits on the top shelf in my book case.  <span class="caps">PAIP</span> was my first introduction to how deep a subject search really was, it jump started my knowledge about lisp, continuations, functional programming, declarative programming, domain specific languages and teased me with <span class="caps">CLOS</span>.  Each of these topics is deep enough to warrant its own book, Dr. Norvig introduces each, often including implementations, in a single book.</p>
<h2><a href="http://www.xs4all.nl/~hipster/lib/scheme/gauche/define-syntax-primer.txt">JRM&#8217;s syntax-rules primer for the merely eccentric</a></h2>
<p>After being introduced to and exploring common lisp from <span class="caps">PAIP</span> and <span class="caps">ANSI</span> Common Lisp, I had started to use, but not completely understand Lisp macros.  I was only beginning to understand the implementation of, and recognize the appropriate application of the <code>with-gensyms</code> and <code>once-only</code> macros.  I had a fuzzy conception of hygiene with respect to what it meant for macros.  JRM&#8217;s syntax primer introduces R5RS&#8217;s alternate macro system: <code>define-syntax</code> and <code>syntax-rules</code>.  <code>syntax-rules</code> is based on pattern matching and recursive expansions, and it was <u>automatically</u> hygienic.  This seemed like magic and seemed to eliminate many of the hygiene problems that you encounter with the traditional Lisp style macros.  It forced me to think about code generation in a completely different light.  The primer is fairly short for the topic it introduces and the material helped me with some fundamental understanding.  The greatest influence this had was to introduce to me new ways to develop and maintain DSLs and code generators.</p>
<h2><a href="http://www.amazon.com/gp/product/193435600X?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=193435600X">Programming Erlang: Software for a Concurrent World</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=193435600X" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></h2>
<p>Joe Armstrong said that when Ericson was creating Erlang, they decided their primary concern was robustness, that to have robustness you needed at least two computers and that most of the rest of the features in Erlang flowed forth from there.  To me Erlang has come to embody what robustness really means: a platform that is capable of achieving nine 9&#8217;s, that concentrates on fail-fast or crash early so that you have more hope of recovery, supervision trees of processes so you know when things go awry and can handle them from a safe distance, the ability to update code live in a running system so that you never have to bring it down.  Erlang is the only platform and language that I&#8217;ve encountered that has internalized these principles into its core.</p>
<p>The book increased my exposure to pattern matching, introduced me to list comprehensions and message passing concurrency (gave me the name for the actors model of concurrency).</p>
<h2><a href="http://www.amazon.com/gp/product/0887306667?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0887306667">The 22 Immutable Laws of Marketing:  Violate Them at Your Own Risk!</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0887306667" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, and <a href="http://www.amazon.com/gp/product/0060007737?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0060007737">The 22 Immutable Laws of Branding</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0060007737" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by Al Reis</h2>
<p><a href="http://www.innovationontherun.com/">Rob Di Marco</a> recommended this to me when I had the privilege of working directly with him.  It was something that was outside my core area of expertise and interest (technology, software development in specific).  I keep seeing the principles they detail show up all around me &#8211; they gave me another model for observing interactions between people, the purpose of blogs, twitter, and how you can use all of communication and points of contact to help shape how people perceive you.  They made me realize, and gave me a starting guide, for how to market and brand myself.  Mostly as a developer and technologist, but also in a few other ways.  Given that IT folks tend to be introverted and not understand the power that how others perceive them has over their interactions, this is something I try to repeatedly recommend to those that I work with.</p>
<h2><a href="http://www.amazon.com/gp/product/0471117099?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0471117099">Applied Cryptography: Protocols, Algorithms, and Source Code in C, Second Edition</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0471117099" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by Bruce Schneier</h2>
<p>I read Applied Cryptography from cover to cover as fast as I could manage to.  At the time I read it there was a lot that was new to me: the historic context, some of the information theory, the idea that there were known best ways to attack the best known algorithms that reduced the effectiveness but did not outright invalidate the approaches, and it drove home the idea that security can not be absolute, that it is a balance between usability and restrictiveness.  This helped hone my sense of information leakage in my own development, from what is stored in files and databases, to log statements to what is exposed thorough error messages and stack traces, where user input comes from and goes to.</p>
<h2><a href="http://www.amazon.com/gp/product/0201633612?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0201633612">Design Patterns: Elements of Reusable Object-Oriented Software</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0201633612" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by the Gang of Four (Erich Gamma, Richard Helm, Ralph Johnson, John M. Vlissides)</h2>
<p>The gang of four book was at first a set of design guidelines, over the years its importance as a design guide has waned and, for me, it has shifted more towards being important because it establishes a shared vocabulary with other developers.  Having the vocabulary allows us to describe the systems and frameworks we&#8217;re using and creating in a way that increases understanding and minimizes misconceptions.</p>
<p><a href="/images/2009-11/bshelf-left2.jpg"><img src="/images/2009-11/bshelf-left2-400x300.jpg" style="float: left; padding: 1em; " /></a></p>
<h2><a href="http://www.amazon.com/gp/product/0201485672?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0201485672">Refactoring: Improving the Design of Existing Code</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0201485672" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by Martin Fowler</h2>
<p>This emphasized the importance of unit testing in the ability to effectively maintain and improve an existing codebase.  It introduced me to the ideas of test driven development along with the pragmatic programmer.</p>
<h2><a href="http://www.amazon.com/gp/product/0201633469?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0201633469"><span class="caps">TCP</span>/IP Illustrated, Volume 1: The Protocols</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0201633469" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, and <a href="http://www.amazon.com/gp/product/013490012X?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=013490012X"><span class="caps">UNIX</span> Network Programming: Networking APIs: Sockets and <span class="caps">XTI</span>; Volume 1</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=013490012X" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> by Richard Stevens</h2>
<p>Having read these books has served my career well over the years.  The introduction to the protocols, and the networking APIs, has been invaluable.  The single most important thing I took away from this book was how I/O Multiplexing (select/poll, non-blocking IO) worked and how efficient it could be.</p>
<h2><a href="http://www.amazon.com/gp/product/0596000278?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0596000278">Programming Perl (3rd Edition)</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0596000278" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by Larry Wall, Tom Christiansen, and Jon Orwant</h2>
<p>Perl was the first dynamic language I learned (having programmed only in compiled languages before it).  I think the camel book was my first O&#8217;Reilly title &#8211; many, many more followed.  O&#8217;Reilly as a publisher deserves a lot of credit for helping to bootstrap my programming career.  Programming Perl showed me that a language, its creators and practitioners, and especially its community could have character.  It emphasized that programming should be enjoyable and fun.   &#8220;Easy things should be easy and hard things should be possible&#8221; is a great slogan for a language &#8211; a language that had a slogan!</p>
<h2><a href="http://www.amazon.com/gp/product/0201350882?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0201350882">Algorithms in C++, Parts 1-4: Fundamentals, Data Structure, Sorting, Searching (3rd Edition) (Pts. 1-4)</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0201350882" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by Robert Sedgewick</h2>
<p>Sedgewick provided me with my first introduction to &#8216;Big Oh&#8217; notation.  His examples displayed an enormous amount of thrift, some of the best examples I&#8217;ve seen of using the minimum necessary to implement the chosen algorithm.  This was not minimalism to the point of terseness, it exemplified that with a clear understanding of the problem, the choice of an algorithm that closely fit the problem, implementations should be clear and uncluttered.  The aesthetic of using minimal language features so as to be as clear as possible was a clear influence on me.</p>
<h2><a href="http://www.amazon.com/gp/product/1565923987?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1565923987">Mastering Algorithms with Perl</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=1565923987" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></h2>
<p>I was first introduced to fuzzy string matching through this book, which turned out to be an interesting problem domain.  I spent about eight years working for a data integration company applying many of the things I first discovered from these algorithms books.</p>
<h2><a href="http://www.amazon.com/gp/product/020161622X?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=020161622X">The Pragmatic Programmer: From Journeyman to Master</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=020161622X" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by Andrew Hunt and David Thomas</h2>
<p>Continual improvement.  Keep questioning and seeking better processes, techniques, solutions.  Learning a new programming language on a regular basis was the single most memorable part of that book for me.  That particular advice has worked particularly well for me.  I believe that each programming language was created to address a core issue or difficulty that its creator was experiencing.  The language is a manifestation of their understanding of the issue and a simplified design that makes that issue easier to contend with.  Some address multiple issues.  My impression of C is that it made for more structured interaction with the hardware&#8217;s basic features (at a time when there was little).  C++ improved the expressiveness of C, introducing OO without moving too far away from the machine.  Java eliminated memory management and pointer manipulation mistakes that programmers were so often tripped up by in C and C++ applications, simplified platform dependency issues, and smoothed over some of the complexity of the OO features in C++.  Perl worked to integrate other tools, most often that produced or consumed text, it was an integration toolbox and grew from there towards a powerful and terse high level language.  Lisp removed all barriers to abstraction, it eliminated the sacred parts of the language and put all their power into the hands of the developer: to do their best, or their worst.</p>
<h2><a href="http://www.amazon.com/gp/product/020161586X?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=020161586X">The Practice of Programming</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=020161586X" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by Brian Khernagin and Rob Pike</h2>
<p>They tell you to continue to hone your skills, develop your craft, continually improve.  Develop your vocabulary and ability to name things clearly and concisely as it very much matters in the clarity of your software.  Learn your tools.  This is one of the books I have to thank for my never-ending stream of reading and continued exploration of this field.</p>
<p><a href="/images/2009-11/bshelf-right2.jpg"><img src="/images/2009-11/bshelf-right2-400x300.jpg" style="float: right; padding: 1em; " /></a></p>
<h2><a href="http://www.amazon.com/gp/product/0393316041?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0393316041">Surely You&#8217;re Joking, Mr. Feynman! (Adventures of a Curious Character)</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0393316041" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, Richard P. Feynman</h2>
<p>Intellectual curiosity.  Looking outside the box.  There is another way to view things.  Trust your intuition and be tenacious &#8211; if there are only 2 possibilities and the evidence is inconclusive, discover new evidence, don&#8217;t just discard the original axioms &#8211; this attitude has been a huge help in debugging.  In some ways it comes down to having faith in yourself.  I hope my children choose to read and are inspired by Feynman&#8217;s writing.</p>
<h2><a href="http://www.amazon.com/gp/product/0553380966?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0553380966">The Diamond Age: Or, a Young Lady&#8217;s Illustrated Primer (Bantam Spectra Book)</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0553380966" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, Neal Stephenson</h2>
<p>Though I enjoyed both Snow Crash and The Diamond Age, I was more inspired by his vision of a young lady&#8217;s illustrated primer.  You see the ideas he was exploring in the primer continuing to manifest themselves over time.  How the Internet is permeating all our devices and experiences, the collaborative nature of how Wikipedia and other crowd sourced assets are being created, Amazon&#8217;s Kindle ebook reader (with on-line access to new content) and discritized task sites like the Mechanical Turk.  I want to be able to gift my own children with their own primers.</p>
<h2><a href="http://www.amazon.com/gp/product/0679743111?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0679743111">Penn and Teller&#8217;s How to Play with Your Food</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0679743111" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, Penn Jillette and Teller</h2>
<p>Thinking outside the box.  Looking at things for what they are, not just for what they seem.  Seeing alternate, unexpected, uses for common things.  In showing how effectively you can deceive your senses, the book helped give me a good sense of skepticism &#8211; not taking something at face value if it didn&#8217;t seem right (I tie this to debugging believe it or not).</p>
<h1>Other Lists of Influential Books</h1>
<p>Since the time I wrote this post I&#8217;ve been contacted by others (one at this time) with their lists.  I&#8217;ll update this periodically with those where I find new books:</p>
<ul>
	<li><a href="http://tpanzarella.wordpress.com/2011/03/09/influential-books/">Tom Panzarella: Influential Books</a></li>
</ul>
<h1>Conclusion</h1>
<p>These are books that have had staying power in my bookshelf.  I&#8217;d love to hear your own thoughts if you do decide to pick any of these up, or even if you&#8217;ve already been through their pages.  I always ask people what books they&#8217;ve found influential as a standard question when I interview developers.  What do you recommend?</p>
<p class="meta">Kyle Burton, 30th November 2009 &#8211; Philadelphia PA</p>
<h3>Thanks</h3>
<p>Special thanks to <a href="http://plpatterns.com/">Jonathan Tran</a>, <a href="http://www.leftrightfold.com/">Aaron Feng</a>, <a href="http://www.innovationontherun.com/">Rob Di Marco</a> and others who have lent and recommended books to me over the years.  A second thanks to both Jonathan and Aaron for reading drafts of this post.</p>]]></description>
      <content:encoded><![CDATA[<h1>Influential Books</h1>
<p>I started with a new team in the middle of this year and as I get to know the other members of the team and share our skills and experiences, the books that each of us has found influential has come up.  This has given me the opportunity to reflect a bit on which ones I still find worthy of suggesting that others read.  Over my career, and as my family has grown, I have become acutely aware of the value of my free time and that of my co-workers.  With that in mind, I&#8217;m recommending and sharing a lot less than I used to, and since a coworker (Aaron Feng) recently made a point of thanking me for my recommendations I thought I&#8217;d journal what I&#8217;ve been pushing at this new team.</p>
<p><a href="/images/2009-11/bshelf-left1.jpg"><img src="/images/2009-11/bshelf-left1-400x300.jpg" style="float: left; padding: 1em; " /></a></p>
<p>My current bookshelf contains the books it does after several rounds of being distilled over the past ten years or so.  Even so, there is a mix of titles that have been there for years as well as some recent acquisitions that I suspect will have longevity.</p>
<h2><a href="http://www.amazon.com/gp/product/1558607013?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1558607013">Higher-Order Perl: Transforming Programs with Programs</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=1558607013" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by Mark Jason Dominus</h2>
<p>If you program in Java, C#, Python, Ruby or another imperative, stateful language, this is perhaps the best book you can pick up to learn several core fundamentals of functional programming.  It is a great introduction to performing functional programming in an imperative, stateful language.  Mark goes through the process of showing you how to implement things like Haskell&#8217;s infinite sequences, the use of higher order functions, and several other fundamental tenants of functional programming.</p>
<p>I lent my copy to Aaron and it was he that started to tell me where in the book he is seeing some of the techniques that I use on a regular basis.  Mark is a great developer and more than just functional programming comes across in the book, a lot of his skill and clarity of thought does as well.</p>
<p>I feel very sorry for any of you that can not get over the fact that this book&#8217;s code examples are in Perl.</p>
<p><a href="/images/2009-11/bshelf-right1.jpg"><img src="/images/2009-11/bshelf-right1-400x300.jpg" style="float: right; padding: 1em; " /></a></p>
<h2><a href="http://www.amazon.com/gp/product/1558601910?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1558601910">Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=1558601910" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /><br />
, by Peter Norvig</h2>
<p>I picked up <span class="caps">PAIP</span> along with <span class="caps">ANSI</span> Common Lisp (by Paul Graham) with the intention of learning Common Lisp.  I wasn&#8217;t prepared for what was in <span class="caps">PAIP</span> when I first struggled through the book.  I started with an expectation of learning about AI, with little expectation of picking up practical techniques that I&#8217;d be able to apply in my day job developing web applications.   What I got out of the book was much more than I anticipated.  I&#8217;ve gone back to it multiple times and it sits on the top shelf in my book case.  <span class="caps">PAIP</span> was my first introduction to how deep a subject search really was, it jump started my knowledge about lisp, continuations, functional programming, declarative programming, domain specific languages and teased me with <span class="caps">CLOS</span>.  Each of these topics is deep enough to warrant its own book, Dr. Norvig introduces each, often including implementations, in a single book.</p>
<h2><a href="http://www.xs4all.nl/~hipster/lib/scheme/gauche/define-syntax-primer.txt">JRM&#8217;s syntax-rules primer for the merely eccentric</a></h2>
<p>After being introduced to and exploring common lisp from <span class="caps">PAIP</span> and <span class="caps">ANSI</span> Common Lisp, I had started to use, but not completely understand Lisp macros.  I was only beginning to understand the implementation of, and recognize the appropriate application of the <code>with-gensyms</code> and <code>once-only</code> macros.  I had a fuzzy conception of hygiene with respect to what it meant for macros.  JRM&#8217;s syntax primer introduces R5RS&#8217;s alternate macro system: <code>define-syntax</code> and <code>syntax-rules</code>.  <code>syntax-rules</code> is based on pattern matching and recursive expansions, and it was <u>automatically</u> hygienic.  This seemed like magic and seemed to eliminate many of the hygiene problems that you encounter with the traditional Lisp style macros.  It forced me to think about code generation in a completely different light.  The primer is fairly short for the topic it introduces and the material helped me with some fundamental understanding.  The greatest influence this had was to introduce to me new ways to develop and maintain DSLs and code generators.</p>
<h2><a href="http://www.amazon.com/gp/product/193435600X?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=193435600X">Programming Erlang: Software for a Concurrent World</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=193435600X" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></h2>
<p>Joe Armstrong said that when Ericson was creating Erlang, they decided their primary concern was robustness, that to have robustness you needed at least two computers and that most of the rest of the features in Erlang flowed forth from there.  To me Erlang has come to embody what robustness really means: a platform that is capable of achieving nine 9&#8217;s, that concentrates on fail-fast or crash early so that you have more hope of recovery, supervision trees of processes so you know when things go awry and can handle them from a safe distance, the ability to update code live in a running system so that you never have to bring it down.  Erlang is the only platform and language that I&#8217;ve encountered that has internalized these principles into its core.</p>
<p>The book increased my exposure to pattern matching, introduced me to list comprehensions and message passing concurrency (gave me the name for the actors model of concurrency).</p>
<h2><a href="http://www.amazon.com/gp/product/0887306667?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0887306667">The 22 Immutable Laws of Marketing:  Violate Them at Your Own Risk!</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0887306667" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, and <a href="http://www.amazon.com/gp/product/0060007737?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0060007737">The 22 Immutable Laws of Branding</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0060007737" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by Al Reis</h2>
<p><a href="http://www.innovationontherun.com/">Rob Di Marco</a> recommended this to me when I had the privilege of working directly with him.  It was something that was outside my core area of expertise and interest (technology, software development in specific).  I keep seeing the principles they detail show up all around me &#8211; they gave me another model for observing interactions between people, the purpose of blogs, twitter, and how you can use all of communication and points of contact to help shape how people perceive you.  They made me realize, and gave me a starting guide, for how to market and brand myself.  Mostly as a developer and technologist, but also in a few other ways.  Given that IT folks tend to be introverted and not understand the power that how others perceive them has over their interactions, this is something I try to repeatedly recommend to those that I work with.</p>
<h2><a href="http://www.amazon.com/gp/product/0471117099?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0471117099">Applied Cryptography: Protocols, Algorithms, and Source Code in C, Second Edition</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0471117099" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by Bruce Schneier</h2>
<p>I read Applied Cryptography from cover to cover as fast as I could manage to.  At the time I read it there was a lot that was new to me: the historic context, some of the information theory, the idea that there were known best ways to attack the best known algorithms that reduced the effectiveness but did not outright invalidate the approaches, and it drove home the idea that security can not be absolute, that it is a balance between usability and restrictiveness.  This helped hone my sense of information leakage in my own development, from what is stored in files and databases, to log statements to what is exposed thorough error messages and stack traces, where user input comes from and goes to.</p>
<h2><a href="http://www.amazon.com/gp/product/0201633612?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0201633612">Design Patterns: Elements of Reusable Object-Oriented Software</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0201633612" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by the Gang of Four (Erich Gamma, Richard Helm, Ralph Johnson, John M. Vlissides)</h2>
<p>The gang of four book was at first a set of design guidelines, over the years its importance as a design guide has waned and, for me, it has shifted more towards being important because it establishes a shared vocabulary with other developers.  Having the vocabulary allows us to describe the systems and frameworks we&#8217;re using and creating in a way that increases understanding and minimizes misconceptions.</p>
<p><a href="/images/2009-11/bshelf-left2.jpg"><img src="/images/2009-11/bshelf-left2-400x300.jpg" style="float: left; padding: 1em; " /></a></p>
<h2><a href="http://www.amazon.com/gp/product/0201485672?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0201485672">Refactoring: Improving the Design of Existing Code</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0201485672" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by Martin Fowler</h2>
<p>This emphasized the importance of unit testing in the ability to effectively maintain and improve an existing codebase.  It introduced me to the ideas of test driven development along with the pragmatic programmer.</p>
<h2><a href="http://www.amazon.com/gp/product/0201633469?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0201633469"><span class="caps">TCP</span>/IP Illustrated, Volume 1: The Protocols</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0201633469" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, and <a href="http://www.amazon.com/gp/product/013490012X?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=013490012X"><span class="caps">UNIX</span> Network Programming: Networking APIs: Sockets and <span class="caps">XTI</span>; Volume 1</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=013490012X" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> by Richard Stevens</h2>
<p>Having read these books has served my career well over the years.  The introduction to the protocols, and the networking APIs, has been invaluable.  The single most important thing I took away from this book was how I/O Multiplexing (select/poll, non-blocking IO) worked and how efficient it could be.</p>
<h2><a href="http://www.amazon.com/gp/product/0596000278?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0596000278">Programming Perl (3rd Edition)</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0596000278" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by Larry Wall, Tom Christiansen, and Jon Orwant</h2>
<p>Perl was the first dynamic language I learned (having programmed only in compiled languages before it).  I think the camel book was my first O&#8217;Reilly title &#8211; many, many more followed.  O&#8217;Reilly as a publisher deserves a lot of credit for helping to bootstrap my programming career.  Programming Perl showed me that a language, its creators and practitioners, and especially its community could have character.  It emphasized that programming should be enjoyable and fun.   &#8220;Easy things should be easy and hard things should be possible&#8221; is a great slogan for a language &#8211; a language that had a slogan!</p>
<h2><a href="http://www.amazon.com/gp/product/0201350882?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0201350882">Algorithms in C++, Parts 1-4: Fundamentals, Data Structure, Sorting, Searching (3rd Edition) (Pts. 1-4)</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0201350882" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by Robert Sedgewick</h2>
<p>Sedgewick provided me with my first introduction to &#8216;Big Oh&#8217; notation.  His examples displayed an enormous amount of thrift, some of the best examples I&#8217;ve seen of using the minimum necessary to implement the chosen algorithm.  This was not minimalism to the point of terseness, it exemplified that with a clear understanding of the problem, the choice of an algorithm that closely fit the problem, implementations should be clear and uncluttered.  The aesthetic of using minimal language features so as to be as clear as possible was a clear influence on me.</p>
<h2><a href="http://www.amazon.com/gp/product/1565923987?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1565923987">Mastering Algorithms with Perl</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=1565923987" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></h2>
<p>I was first introduced to fuzzy string matching through this book, which turned out to be an interesting problem domain.  I spent about eight years working for a data integration company applying many of the things I first discovered from these algorithms books.</p>
<h2><a href="http://www.amazon.com/gp/product/020161622X?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=020161622X">The Pragmatic Programmer: From Journeyman to Master</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=020161622X" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by Andrew Hunt and David Thomas</h2>
<p>Continual improvement.  Keep questioning and seeking better processes, techniques, solutions.  Learning a new programming language on a regular basis was the single most memorable part of that book for me.  That particular advice has worked particularly well for me.  I believe that each programming language was created to address a core issue or difficulty that its creator was experiencing.  The language is a manifestation of their understanding of the issue and a simplified design that makes that issue easier to contend with.  Some address multiple issues.  My impression of C is that it made for more structured interaction with the hardware&#8217;s basic features (at a time when there was little).  C++ improved the expressiveness of C, introducing OO without moving too far away from the machine.  Java eliminated memory management and pointer manipulation mistakes that programmers were so often tripped up by in C and C++ applications, simplified platform dependency issues, and smoothed over some of the complexity of the OO features in C++.  Perl worked to integrate other tools, most often that produced or consumed text, it was an integration toolbox and grew from there towards a powerful and terse high level language.  Lisp removed all barriers to abstraction, it eliminated the sacred parts of the language and put all their power into the hands of the developer: to do their best, or their worst.</p>
<h2><a href="http://www.amazon.com/gp/product/020161586X?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=020161586X">The Practice of Programming</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=020161586X" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, by Brian Khernagin and Rob Pike</h2>
<p>They tell you to continue to hone your skills, develop your craft, continually improve.  Develop your vocabulary and ability to name things clearly and concisely as it very much matters in the clarity of your software.  Learn your tools.  This is one of the books I have to thank for my never-ending stream of reading and continued exploration of this field.</p>
<p><a href="/images/2009-11/bshelf-right2.jpg"><img src="/images/2009-11/bshelf-right2-400x300.jpg" style="float: right; padding: 1em; " /></a></p>
<h2><a href="http://www.amazon.com/gp/product/0393316041?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0393316041">Surely You&#8217;re Joking, Mr. Feynman! (Adventures of a Curious Character)</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0393316041" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, Richard P. Feynman</h2>
<p>Intellectual curiosity.  Looking outside the box.  There is another way to view things.  Trust your intuition and be tenacious &#8211; if there are only 2 possibilities and the evidence is inconclusive, discover new evidence, don&#8217;t just discard the original axioms &#8211; this attitude has been a huge help in debugging.  In some ways it comes down to having faith in yourself.  I hope my children choose to read and are inspired by Feynman&#8217;s writing.</p>
<h2><a href="http://www.amazon.com/gp/product/0553380966?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0553380966">The Diamond Age: Or, a Young Lady&#8217;s Illustrated Primer (Bantam Spectra Book)</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0553380966" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, Neal Stephenson</h2>
<p>Though I enjoyed both Snow Crash and The Diamond Age, I was more inspired by his vision of a young lady&#8217;s illustrated primer.  You see the ideas he was exploring in the primer continuing to manifest themselves over time.  How the Internet is permeating all our devices and experiences, the collaborative nature of how Wikipedia and other crowd sourced assets are being created, Amazon&#8217;s Kindle ebook reader (with on-line access to new content) and discritized task sites like the Mechanical Turk.  I want to be able to gift my own children with their own primers.</p>
<h2><a href="http://www.amazon.com/gp/product/0679743111?ie=UTF8&tag=asymmview-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0679743111">Penn and Teller&#8217;s How to Play with Your Food</a><img src="http://www.assoc-amazon.com/e/ir?t=asymmview-20&l=as2&o=1&a=0679743111" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, Penn Jillette and Teller</h2>
<p>Thinking outside the box.  Looking at things for what they are, not just for what they seem.  Seeing alternate, unexpected, uses for common things.  In showing how effectively you can deceive your senses, the book helped give me a good sense of skepticism &#8211; not taking something at face value if it didn&#8217;t seem right (I tie this to debugging believe it or not).</p>
<h1>Other Lists of Influential Books</h1>
<p>Since the time I wrote this post I&#8217;ve been contacted by others (one at this time) with their lists.  I&#8217;ll update this periodically with those where I find new books:</p>
<ul>
	<li><a href="http://tpanzarella.wordpress.com/2011/03/09/influential-books/">Tom Panzarella: Influential Books</a></li>
</ul>
<h1>Conclusion</h1>
<p>These are books that have had staying power in my bookshelf.  I&#8217;d love to hear your own thoughts if you do decide to pick any of these up, or even if you&#8217;ve already been through their pages.  I always ask people what books they&#8217;ve found influential as a standard question when I interview developers.  What do you recommend?</p>
<p class="meta">Kyle Burton, 30th November 2009 &#8211; Philadelphia PA</p>
<h3>Thanks</h3>
<p>Special thanks to <a href="http://plpatterns.com/">Jonathan Tran</a>, <a href="http://www.leftrightfold.com/">Aaron Feng</a>, <a href="http://www.innovationontherun.com/">Rob Di Marco</a> and others who have lent and recommended books to me over the years.  A second thanks to both Jonathan and Aaron for reading drafts of this post.</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Connecting SLIME to a remote Clojure Repl</title>
      <link>http://asymmetrical-view.com/2009/08/20/emacs-slime-remote-repl.html</link>
      <comments>http://asymmetrical-view.com/2009/08/20/emacs-slime-remote-repl.html#comments</comments>

      <pubDate>2009-08-20T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2009/08/20/emacs-slime-remote-repl.html</guid>

      <id>http://asymmetrical-view.com/2009/08/20/emacs-slime-remote-repl</id>
      <description><![CDATA[<p><img src="/images/2009-08/emacs-swank-clojure-1.png" style="float: left; padding: 1em; " /></p>
<h1>Connecting <span class="caps">SLIME</span> to a remote Clojure Repl</h1>
<p><a href="http://common-lisp.net/project/slime/"><span class="caps">SLIME</span></a> is a powerful extension for <a href="http://www.gnu.org/software/emacs/">Emacs</a> that transforms Emacs into an <span class="caps">IDE</span> for Lisp.  It sets up Emacs so that it can connect to and interact with a Lisp running as a separate process &#8211; even on a separate server.  This configuration allows you to connect to a running application with Emacs, allowing you to inspect the state of and debug a running application.  In this post I will walk you through how to set up and use this scenario using Emacs, <span class="caps">SLIME</span> and <a href="http://www.openssh.com/"><span class="caps">SSH</span></a> to connect to a remote <a href="http://en.wikipedia.org/wiki/Java_Virtual_Machine"><span class="caps">JVM</span></a> running <a href="http://clojure.org/">Clojure</a>.</p>
<h2><span class="caps">SLIME</span> and Swank</h2>
<p>Slime largely provides the &#8216;<span class="caps">IDE</span>&#8217; portion of the extension, where Swank provides the inter-process communication between Emacs and the running Lisp image.  Swank is broken into two parts, a layer run within Emacs and a server which runs within the Lisp image.  This provides Emacs the ability to execute forms (expressions) within the running Lisp instance, query it for information and otherwise interact with it in a structured manner.</p>
<h2>Clojure</h2>
<p>Slime was extended by <a href="http://github.com/jochu/">Jeffery Chu</a> to support Clojure through <a href="http://github.com/jochu/swank-clojure/tree/master">swank-clojure</a>.  Swank-clojure creates a server within the <span class="caps">JVM</span> running in its own thread to handle connections from the Emacs part of Swank.</p>
<p>Getting Emacs, <span class="caps">SLIME</span>, Clojure and clojure-swank set up is covered by others; <a href="http://technomancy.us/126">technomancy.us</a> has a good getting started guide.  My own configuration is available as an example in my <a href="http://github.com/kyleburton/krbemacs/tree/master">GitHub</a> account.</p>
<h2>Giving your <span class="caps">JVM</span> some Swank</h2>
<p>Before you can connect to your running image, you&#8217;ll first need to start up Clojure (the Repl) and run the swank-server.  You will need to ensure the <code>swank-clojure</code> directory is on your class-path as well as the clojure and clojure-contrib jar files.  I use a bash script like the following to run a Clojure Repl.  This script sets up a class-path that includes the clojure and clojure-contrib jar files as well as swank-clojure, which we&#8217;ll be using in a minute.  It also adds all of the files in my <code>$HOME/.clojure</code> directory.  I keep commonly used jar files in that directory so this is a convenient way to pull in multiple dependencies.</p>
<pre class="code">
CLOJURE_JAR="$HOME/.clojure/clojure.jar"
CONTRIB_JAR="$HOME/.clojure/clojure-contrib.jar"
CLASSPATH="$CLOJURE_JAR:$CONTRIB_JAR:$HOME/personal/projects/krbemacs/swank-clojure" 
for f in $HOME/.clojure/*; do CLASSPATH="$CLASSPATH:$f" done
java -server -cp "$CLASSPATH" clojure.lang.Repl "$@"
</pre>
<p>In addition to the above script, I have the following in a &#8216;run-swank.clj&#8217; file.  It requires swank, sets a required protocol version and finally starts swank in its own thread.</p>
<pre class="code">
(require 'swank.swank)
(swank.swank/ignore-protocol-version "2009-08-19")
(swank.swank/start-server "/tmp/slime.krb" 
                          :encoding "iso-latin-1-unix"
                          :port 4005)
</pre>
<p>The ignore-protocol-version is needed by swank-clojure to ensure that the swank-elisp and swank-clojure are in sync (I realize it is named confusingly).  The first argument to <code>start-server</code> is a path to which the port swank is listening on will be written to.  When you run Lisp from within Emacs these functions are executed by swank-elisp and this file is used so that both sides know what the port is.  I run this from either the clojure script or from a clojure repl (outside of Emacs) with <code>load-file</code>:</p>
<pre class="code">
kyle@indigo64 ~/personal/projects/krbemacs[master]$ clojure
Clojure 1.1.0-alpha-SNAPSHOT
user=&gt; (load-file "run-swank.clj")
Connection opened on local port  4005
4005
user=&gt; 
</pre>
<p><img src="/images/2009-08/emacs-slime-swank-internet.png" style="float: right; padding: 1em; " /></p>
<p>Swank is now running within this lisp image.</p>
<p>The current version of swank-clojure (as of August 20th 2009) does not bind to only localhost, allowing connections from external hosts.  Ensure you have either firewalled off the swank port (4005 is the default) or patch swank-clojure to bind only to localhost (there is a swank-clojure in my <a href="http://github.com/kyleburton/krbemacs">Emacs GitHub</a> repository with this modification).</p>
<p>Since I can&#8217;t connect directly to this remote-host (the port is not exposed to the network).  I need to use ssh to securely forward a port from my local workstation through an ssh-tunnel to the other machine:</p>
<pre class="code">
kyle@macbook ~/$ ssh -L1099:localhost:4005 indigo64
Linux indigo64 2.6.18.8-x86_64-ubuntu #1 SMP Thu Apr 10 11:20:13 EDT 2008 x86_64
Last login: Fri Aug 21 01:50:59 2009 from macbook
kyle@indigo64 ~$ 
</pre>
<p>I can now connect to this from my Emacs by executing <code>M-x slime-connect</code>, providing localhost or 127.0.0.1 as the Host-name and 1099 as the port. I chose 1099 arbitrarily, you can use any unused port &#8212; 4005 is a fine choice especially since it is the swank default.</p>
<p>At this point, with emacs connected, forms evaluated at the repl within Emacs, or from Clojure buffers will actually be run within the remote <span class="caps">JVM</span>.</p>
<p>Executing a print-line from Emacs running on my laptop:</p>
<p><img class="centered-img" src="/images/2009-08/emacs-slime-connected.png" style="padding: 1em; " /></p>
<p>Produces output on the remote Clojure image:</p>
<p><img class="centered-img" src="/images/2009-08/terminal-clojure-repl.png" style="padding: 1em; " /></p>
<h2>Conclusion</h2>
<p>Being able to connect to a remote running image can be useful &#8211; especially for times when you can&#8217;t have your development environment present on the remote server and still need to introspect the running process.</p>
<p class="meta">Kyle Burton, 20th August 2009 &#8211; Philadelphia PA</p>
<h3>Thanks</h3>
<p>Special thanks to <a href="http://plpatterns.com/">Jonathan Tran</a>, and <a href="http://innovationontherun.com/">Rob DiMarco</a> for reading drafts and providing valuable feedback and suggestions.</p>]]></description>
      <content:encoded><![CDATA[<p><img src="/images/2009-08/emacs-swank-clojure-1.png" style="float: left; padding: 1em; " /></p>
<h1>Connecting <span class="caps">SLIME</span> to a remote Clojure Repl</h1>
<p><a href="http://common-lisp.net/project/slime/"><span class="caps">SLIME</span></a> is a powerful extension for <a href="http://www.gnu.org/software/emacs/">Emacs</a> that transforms Emacs into an <span class="caps">IDE</span> for Lisp.  It sets up Emacs so that it can connect to and interact with a Lisp running as a separate process &#8211; even on a separate server.  This configuration allows you to connect to a running application with Emacs, allowing you to inspect the state of and debug a running application.  In this post I will walk you through how to set up and use this scenario using Emacs, <span class="caps">SLIME</span> and <a href="http://www.openssh.com/"><span class="caps">SSH</span></a> to connect to a remote <a href="http://en.wikipedia.org/wiki/Java_Virtual_Machine"><span class="caps">JVM</span></a> running <a href="http://clojure.org/">Clojure</a>.</p>
<h2><span class="caps">SLIME</span> and Swank</h2>
<p>Slime largely provides the &#8216;<span class="caps">IDE</span>&#8217; portion of the extension, where Swank provides the inter-process communication between Emacs and the running Lisp image.  Swank is broken into two parts, a layer run within Emacs and a server which runs within the Lisp image.  This provides Emacs the ability to execute forms (expressions) within the running Lisp instance, query it for information and otherwise interact with it in a structured manner.</p>
<h2>Clojure</h2>
<p>Slime was extended by <a href="http://github.com/jochu/">Jeffery Chu</a> to support Clojure through <a href="http://github.com/jochu/swank-clojure/tree/master">swank-clojure</a>.  Swank-clojure creates a server within the <span class="caps">JVM</span> running in its own thread to handle connections from the Emacs part of Swank.</p>
<p>Getting Emacs, <span class="caps">SLIME</span>, Clojure and clojure-swank set up is covered by others; <a href="http://technomancy.us/126">technomancy.us</a> has a good getting started guide.  My own configuration is available as an example in my <a href="http://github.com/kyleburton/krbemacs/tree/master">GitHub</a> account.</p>
<h2>Giving your <span class="caps">JVM</span> some Swank</h2>
<p>Before you can connect to your running image, you&#8217;ll first need to start up Clojure (the Repl) and run the swank-server.  You will need to ensure the <code>swank-clojure</code> directory is on your class-path as well as the clojure and clojure-contrib jar files.  I use a bash script like the following to run a Clojure Repl.  This script sets up a class-path that includes the clojure and clojure-contrib jar files as well as swank-clojure, which we&#8217;ll be using in a minute.  It also adds all of the files in my <code>$HOME/.clojure</code> directory.  I keep commonly used jar files in that directory so this is a convenient way to pull in multiple dependencies.</p>
<pre class="code">
CLOJURE_JAR="$HOME/.clojure/clojure.jar"
CONTRIB_JAR="$HOME/.clojure/clojure-contrib.jar"
CLASSPATH="$CLOJURE_JAR:$CONTRIB_JAR:$HOME/personal/projects/krbemacs/swank-clojure" 
for f in $HOME/.clojure/*; do CLASSPATH="$CLASSPATH:$f" done
java -server -cp "$CLASSPATH" clojure.lang.Repl "$@"
</pre>
<p>In addition to the above script, I have the following in a &#8216;run-swank.clj&#8217; file.  It requires swank, sets a required protocol version and finally starts swank in its own thread.</p>
<pre class="code">
(require 'swank.swank)
(swank.swank/ignore-protocol-version "2009-08-19")
(swank.swank/start-server "/tmp/slime.krb" 
                          :encoding "iso-latin-1-unix"
                          :port 4005)
</pre>
<p>The ignore-protocol-version is needed by swank-clojure to ensure that the swank-elisp and swank-clojure are in sync (I realize it is named confusingly).  The first argument to <code>start-server</code> is a path to which the port swank is listening on will be written to.  When you run Lisp from within Emacs these functions are executed by swank-elisp and this file is used so that both sides know what the port is.  I run this from either the clojure script or from a clojure repl (outside of Emacs) with <code>load-file</code>:</p>
<pre class="code">
kyle@indigo64 ~/personal/projects/krbemacs[master]$ clojure
Clojure 1.1.0-alpha-SNAPSHOT
user=&gt; (load-file "run-swank.clj")
Connection opened on local port  4005
4005
user=&gt; 
</pre>
<p><img src="/images/2009-08/emacs-slime-swank-internet.png" style="float: right; padding: 1em; " /></p>
<p>Swank is now running within this lisp image.</p>
<p>The current version of swank-clojure (as of August 20th 2009) does not bind to only localhost, allowing connections from external hosts.  Ensure you have either firewalled off the swank port (4005 is the default) or patch swank-clojure to bind only to localhost (there is a swank-clojure in my <a href="http://github.com/kyleburton/krbemacs">Emacs GitHub</a> repository with this modification).</p>
<p>Since I can&#8217;t connect directly to this remote-host (the port is not exposed to the network).  I need to use ssh to securely forward a port from my local workstation through an ssh-tunnel to the other machine:</p>
<pre class="code">
kyle@macbook ~/$ ssh -L1099:localhost:4005 indigo64
Linux indigo64 2.6.18.8-x86_64-ubuntu #1 SMP Thu Apr 10 11:20:13 EDT 2008 x86_64
Last login: Fri Aug 21 01:50:59 2009 from macbook
kyle@indigo64 ~$ 
</pre>
<p>I can now connect to this from my Emacs by executing <code>M-x slime-connect</code>, providing localhost or 127.0.0.1 as the Host-name and 1099 as the port. I chose 1099 arbitrarily, you can use any unused port &#8212; 4005 is a fine choice especially since it is the swank default.</p>
<p>At this point, with emacs connected, forms evaluated at the repl within Emacs, or from Clojure buffers will actually be run within the remote <span class="caps">JVM</span>.</p>
<p>Executing a print-line from Emacs running on my laptop:</p>
<p><img class="centered-img" src="/images/2009-08/emacs-slime-connected.png" style="padding: 1em; " /></p>
<p>Produces output on the remote Clojure image:</p>
<p><img class="centered-img" src="/images/2009-08/terminal-clojure-repl.png" style="padding: 1em; " /></p>
<h2>Conclusion</h2>
<p>Being able to connect to a remote running image can be useful &#8211; especially for times when you can&#8217;t have your development environment present on the remote server and still need to introspect the running process.</p>
<p class="meta">Kyle Burton, 20th August 2009 &#8211; Philadelphia PA</p>
<h3>Thanks</h3>
<p>Special thanks to <a href="http://plpatterns.com/">Jonathan Tran</a>, and <a href="http://innovationontherun.com/">Rob DiMarco</a> for reading drafts and providing valuable feedback and suggestions.</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Safer Bash Scripting</title>
      <link>http://asymmetrical-view.com/2009/08/07/bash-argument-handling.html</link>
      <comments>http://asymmetrical-view.com/2009/08/07/bash-argument-handling.html#comments</comments>

      <pubDate>2009-08-07T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2009/08/07/bash-argument-handling.html</guid>

      <id>http://asymmetrical-view.com/2009/08/07/bash-argument-handling</id>
      <description><![CDATA[<p><img src="/images/2009-08/B-2806644149_6cff9a07ee_b-scaled.jpg" style="float: left; padding: 1em; " /></p>
<h1>Safer Bash Scripting</h1>
<p>I was pairing with a colleague today writing a moderately sized <a href="http://en.wikipedia.org/wiki/Shell_script">shell script</a>, during the session some of the best practices I try to follow came up.  There are some best practices I try to follow when programming, be it in <a href="http://en.wikipedia.org/wiki/Shell_script">shell</a> or any other language.  We took a little time to talk about two of the habits I picked up which encouraged me to share them here.  The first has two parts: treating warnings as errors and logging what happens.  The second best practice has to do with clean argument and variable handling in Unix (<a href="http://www.gnu.org/software/bash/">bash</a>) shell scripts.</p>
<h2>Enable <i><b>All</b></i> Warnings</h2>
<p>This is a universal best practice for all my software development.  For <a href="http://gcc.gnu.org/">gcc</a> you can do this by adding <code>-Wall</code> and <code>-Werror</code> which enables all warnings and treats them as errors.  For <a href="http://www.perl.org/">perl</a> you use <code>-w</code>, or within the code, the <code>warnings</code> and <code>strict</code> pragmas.  The additional strictness is more work up front but pays off in not having to debug later.  gcc even goes so far as to ensure your <code>printf</code> format strings have corresponding arguments of the correct type!  As you learn what constitutes an error or warning to the compiler or run-time you will write cleaner code and it will no longer feel like a burden, and whole classes of errors will cease to happen in your software.</p>
<h3>&#8216;<code>set -e</code>&#8217;</h3>
<p><a href="http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html">Bash</a> supports a setting, enabled via <code>set -e</code>, that causes your shell-script to immediately cease if any of the commands you&#8217;ve called return a non-zero exit value back to the shell (a zero exit value is the standard indication of success for a program or command).  Enabling this feature is similar to exception handling, like getting a free &#8216;if this errors, abort the program&#8217;.</p>
<p>As pedagogical example, if you were writing a shell script to create a sub-directory and create a file with the current date and time as its contents, you could easily write:</p>
<pre class="code">
kyleburton@indigo64 ~/tmp$ rm -rf logs/
kyleburton@indigo64 ~/tmp$ cat dlog.sh 
mkdir logs
date &gt;&gt; logs/uptime.log
kyleburton@indigo64 ~/tmp$ bash dlog.sh 
kyleburton@indigo64 ~/tmp$ cat logs/uptime.log 
Fri Aug  7 22:30:18 EDT 2009
kyleburton@indigo64 ~/tmp$ bash dlog.sh 
mkdir: cannot create directory `logs': File exists
kyleburton@indigo64 ~/tmp$ cat logs/uptime.log 
Fri Aug  7 22:30:18 EDT 2009
Fri Aug  7 22:30:21 EDT 2009
kyleburton@indigo64 ~/tmp$ 
</pre>
<p>This would work every time it was run (permissions problems and insufficient disk space not withstanding).  The second time it was run though, and every subsequent time, the <code>mkdir</code> program will error informing you the logs directory already exists.  With the same script, with <code>set -e</code> set, this line will fail immediately, and not append the current date and time to the log file:</p>
<pre class="code">
kyleburton@indigo64 ~/tmp$ cat dlog.sh 
set -e
mkdir logs
date &gt;&gt; logs/uptime.log
kyleburton@indigo64 ~/tmp$ bash dlog.sh 
kyleburton@indigo64 ~/tmp$ cat logs/uptime.log 
Fri Aug  7 22:31:07 EDT 2009
kyleburton@indigo64 ~/tmp$ bash dlog.sh 
mkdir: cannot create directory `logs': File exists
kyleburton@indigo64 ~/tmp$ cat logs/uptime.log 
Fri Aug  7 22:31:07 EDT 2009
kyleburton@indigo64 ~/tmp$ 
</pre>
<p>This protects us against the script continuing and, depending on the behavior and goals of the script, potentially causing damage or corruption.  You could wrap each command in an if/else branch, exiting in the case when the command fails, but the <code>set -e</code> effectively inverts that from having to check for errors as the default behavior to errors aborting processing as the default behavior.</p>
<h3>&#8216;<code>set -x</code>&#8217;</h3>
<p>The second declaration I often use at the top of my scripts is <code>set -x</code>, which causes bash to echo each command that it executes:</p>
<pre class="code">
kyleburton@indigo64 ~/tmp$ cat dlog.sh 
set -x
set -e
mkdir logs
date &gt;&gt; logs/uptime.log
kyleburton@indigo64 ~/tmp$ bash dlog.sh 
+ set -e
+ mkdir logs
+ date
kyleburton@indigo64 ~/tmp$ 
</pre>
<p>Combined with the <a href="http://www.gnu.org/manual/gawk/html_node/Tee-Program.html">tee</a> command, <code>set -x</code> gives you a log of what your bash script (which is a program after all) was trying to do.  These are often invaluable in determining where and why failures have occurred.</p>
<h2>Safe-r Variable Handling</h2>
<p>Bash scripts, almost by definition, call other programs, some of them bash scripts.  With any but the most trivial bash scripts, you will also encounter variables.  The main gotcha with variables and the shell is the way argument parsing takes place.  The default is to use spaces to separate arguments, which if you&#8217;re not careful about how you handle your variables, can cause them to be parsed in unexpected ways.  You protect against this by wrapping your variable usage with double quotes.  You must be diligent about this, anywhere you see a dollar-sign, it should be wrapped in double quotes.</p>
<p><img src="/images/2009-08/shell.png" style="float: right; padding: 1em; " /></p>
<p>In the case of a bash script wanting to pass its arguments on to another program without modification (perhaps you&#8217;re writing a wrapper script to log timing information or log other information about the execution), you use <code>$@</code> to refer to all of the command line arguments.  To pass them on with no additional accidental parsing, you just surround it with double quotes (<code>"$@"</code>) as in the following example.  Here we have 2 scripts, the first calls the second, first without the double quotes and then again with the double quotes:</p>
<pre class="code">

kyleburton@indigo64 ~/tmp$ cat first.sh
set -e
bash second.sh not $@
bash second.sh with "$@"

kyleburton@indigo64 ~/tmp$ cat second.sh
set -e
echo 1 = $1
echo 2 = $2
echo 3 = $3
echo 4 = $4
echo 5 = $5
echo 6 = $6
echo 7 = $7
echo ""

kyleburton@indigo64 ~/tmp$ bash first.sh 1 2 "three for five"
1 = not
2 = 1
3 = 2
4 = three
5 = for
6 = five
7 =

1 = with
2 = 1
3 = 2
4 = three for five
5 =
6 =
7 =

kyleburton@indigo64 ~/tmp$
</pre>
<p><img src="/images/2009-08/J-2806802177_3c32cec9dc_b-scaled.jpg" style="float: right; padding: 1em; " /></p>
<p>The first invocation of second.sh from first.sh does not use the quotes, which causes bash to re-parse the arguments within the first.sh script.  Resulting in <code>"three four five"</code> being split into 3 distinct parameters to be passed to second.sh.  In the second case, using <code>"$@"</code>, the atomicity of the argument is preserved.</p>
<h2>Conclusion</h2>
<p>Writing robust bash shell scripts is helped significantly through the enabling of error checking as well as being diligent when using and passing command line arguments.  I hope these tips help you in your scripting.</p>
<p class="meta">Kyle Burton, 7th August 2009 &#8211; Wayne PA</p>
<h3>Thanks</h3>
<p>Special thanks to <a href="http://plpatterns.com/">Jonathan Tran</a>, and <a href="http://www.leftrightfold.com/">Aaron Feng</a> for reading drafts and providing feedback and suggestions.</p>
<h5>Photo Credits</h5>
<ul>
	<li><a href="http://www.flickr.com/photos/takomabibelot/2806644149/">B &#8216;Script&#8217;</a></li>
	<li><a href="http://www.flickr.com/photos/takomabibelot/2806802177/">J &#8216;Script&#8217;</a></li>
	<li><a href="http://asymmetrical-view.com/about/">shell</a></li>
</ul>]]></description>
      <content:encoded><![CDATA[<p><img src="/images/2009-08/B-2806644149_6cff9a07ee_b-scaled.jpg" style="float: left; padding: 1em; " /></p>
<h1>Safer Bash Scripting</h1>
<p>I was pairing with a colleague today writing a moderately sized <a href="http://en.wikipedia.org/wiki/Shell_script">shell script</a>, during the session some of the best practices I try to follow came up.  There are some best practices I try to follow when programming, be it in <a href="http://en.wikipedia.org/wiki/Shell_script">shell</a> or any other language.  We took a little time to talk about two of the habits I picked up which encouraged me to share them here.  The first has two parts: treating warnings as errors and logging what happens.  The second best practice has to do with clean argument and variable handling in Unix (<a href="http://www.gnu.org/software/bash/">bash</a>) shell scripts.</p>
<h2>Enable <i><b>All</b></i> Warnings</h2>
<p>This is a universal best practice for all my software development.  For <a href="http://gcc.gnu.org/">gcc</a> you can do this by adding <code>-Wall</code> and <code>-Werror</code> which enables all warnings and treats them as errors.  For <a href="http://www.perl.org/">perl</a> you use <code>-w</code>, or within the code, the <code>warnings</code> and <code>strict</code> pragmas.  The additional strictness is more work up front but pays off in not having to debug later.  gcc even goes so far as to ensure your <code>printf</code> format strings have corresponding arguments of the correct type!  As you learn what constitutes an error or warning to the compiler or run-time you will write cleaner code and it will no longer feel like a burden, and whole classes of errors will cease to happen in your software.</p>
<h3>&#8216;<code>set -e</code>&#8217;</h3>
<p><a href="http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html">Bash</a> supports a setting, enabled via <code>set -e</code>, that causes your shell-script to immediately cease if any of the commands you&#8217;ve called return a non-zero exit value back to the shell (a zero exit value is the standard indication of success for a program or command).  Enabling this feature is similar to exception handling, like getting a free &#8216;if this errors, abort the program&#8217;.</p>
<p>As pedagogical example, if you were writing a shell script to create a sub-directory and create a file with the current date and time as its contents, you could easily write:</p>
<pre class="code">
kyleburton@indigo64 ~/tmp$ rm -rf logs/
kyleburton@indigo64 ~/tmp$ cat dlog.sh 
mkdir logs
date &gt;&gt; logs/uptime.log
kyleburton@indigo64 ~/tmp$ bash dlog.sh 
kyleburton@indigo64 ~/tmp$ cat logs/uptime.log 
Fri Aug  7 22:30:18 EDT 2009
kyleburton@indigo64 ~/tmp$ bash dlog.sh 
mkdir: cannot create directory `logs': File exists
kyleburton@indigo64 ~/tmp$ cat logs/uptime.log 
Fri Aug  7 22:30:18 EDT 2009
Fri Aug  7 22:30:21 EDT 2009
kyleburton@indigo64 ~/tmp$ 
</pre>
<p>This would work every time it was run (permissions problems and insufficient disk space not withstanding).  The second time it was run though, and every subsequent time, the <code>mkdir</code> program will error informing you the logs directory already exists.  With the same script, with <code>set -e</code> set, this line will fail immediately, and not append the current date and time to the log file:</p>
<pre class="code">
kyleburton@indigo64 ~/tmp$ cat dlog.sh 
set -e
mkdir logs
date &gt;&gt; logs/uptime.log
kyleburton@indigo64 ~/tmp$ bash dlog.sh 
kyleburton@indigo64 ~/tmp$ cat logs/uptime.log 
Fri Aug  7 22:31:07 EDT 2009
kyleburton@indigo64 ~/tmp$ bash dlog.sh 
mkdir: cannot create directory `logs': File exists
kyleburton@indigo64 ~/tmp$ cat logs/uptime.log 
Fri Aug  7 22:31:07 EDT 2009
kyleburton@indigo64 ~/tmp$ 
</pre>
<p>This protects us against the script continuing and, depending on the behavior and goals of the script, potentially causing damage or corruption.  You could wrap each command in an if/else branch, exiting in the case when the command fails, but the <code>set -e</code> effectively inverts that from having to check for errors as the default behavior to errors aborting processing as the default behavior.</p>
<h3>&#8216;<code>set -x</code>&#8217;</h3>
<p>The second declaration I often use at the top of my scripts is <code>set -x</code>, which causes bash to echo each command that it executes:</p>
<pre class="code">
kyleburton@indigo64 ~/tmp$ cat dlog.sh 
set -x
set -e
mkdir logs
date &gt;&gt; logs/uptime.log
kyleburton@indigo64 ~/tmp$ bash dlog.sh 
+ set -e
+ mkdir logs
+ date
kyleburton@indigo64 ~/tmp$ 
</pre>
<p>Combined with the <a href="http://www.gnu.org/manual/gawk/html_node/Tee-Program.html">tee</a> command, <code>set -x</code> gives you a log of what your bash script (which is a program after all) was trying to do.  These are often invaluable in determining where and why failures have occurred.</p>
<h2>Safe-r Variable Handling</h2>
<p>Bash scripts, almost by definition, call other programs, some of them bash scripts.  With any but the most trivial bash scripts, you will also encounter variables.  The main gotcha with variables and the shell is the way argument parsing takes place.  The default is to use spaces to separate arguments, which if you&#8217;re not careful about how you handle your variables, can cause them to be parsed in unexpected ways.  You protect against this by wrapping your variable usage with double quotes.  You must be diligent about this, anywhere you see a dollar-sign, it should be wrapped in double quotes.</p>
<p><img src="/images/2009-08/shell.png" style="float: right; padding: 1em; " /></p>
<p>In the case of a bash script wanting to pass its arguments on to another program without modification (perhaps you&#8217;re writing a wrapper script to log timing information or log other information about the execution), you use <code>$@</code> to refer to all of the command line arguments.  To pass them on with no additional accidental parsing, you just surround it with double quotes (<code>"$@"</code>) as in the following example.  Here we have 2 scripts, the first calls the second, first without the double quotes and then again with the double quotes:</p>
<pre class="code">

kyleburton@indigo64 ~/tmp$ cat first.sh
set -e
bash second.sh not $@
bash second.sh with "$@"

kyleburton@indigo64 ~/tmp$ cat second.sh
set -e
echo 1 = $1
echo 2 = $2
echo 3 = $3
echo 4 = $4
echo 5 = $5
echo 6 = $6
echo 7 = $7
echo ""

kyleburton@indigo64 ~/tmp$ bash first.sh 1 2 "three for five"
1 = not
2 = 1
3 = 2
4 = three
5 = for
6 = five
7 =

1 = with
2 = 1
3 = 2
4 = three for five
5 =
6 =
7 =

kyleburton@indigo64 ~/tmp$
</pre>
<p><img src="/images/2009-08/J-2806802177_3c32cec9dc_b-scaled.jpg" style="float: right; padding: 1em; " /></p>
<p>The first invocation of second.sh from first.sh does not use the quotes, which causes bash to re-parse the arguments within the first.sh script.  Resulting in <code>"three four five"</code> being split into 3 distinct parameters to be passed to second.sh.  In the second case, using <code>"$@"</code>, the atomicity of the argument is preserved.</p>
<h2>Conclusion</h2>
<p>Writing robust bash shell scripts is helped significantly through the enabling of error checking as well as being diligent when using and passing command line arguments.  I hope these tips help you in your scripting.</p>
<p class="meta">Kyle Burton, 7th August 2009 &#8211; Wayne PA</p>
<h3>Thanks</h3>
<p>Special thanks to <a href="http://plpatterns.com/">Jonathan Tran</a>, and <a href="http://www.leftrightfold.com/">Aaron Feng</a> for reading drafts and providing feedback and suggestions.</p>
<h5>Photo Credits</h5>
<ul>
	<li><a href="http://www.flickr.com/photos/takomabibelot/2806644149/">B &#8216;Script&#8217;</a></li>
	<li><a href="http://www.flickr.com/photos/takomabibelot/2806802177/">J &#8216;Script&#8217;</a></li>
	<li><a href="http://asymmetrical-view.com/about/">shell</a></li>
</ul>]]></content:encoded>
    </item>
    
    <item>
      <title>Departure</title>
      <link>http://asymmetrical-view.com/2009/07/19/departure.html</link>
      <comments>http://asymmetrical-view.com/2009/07/19/departure.html#comments</comments>

      <pubDate>2009-07-19T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2009/07/19/departure.html</guid>

      <id>http://asymmetrical-view.com/2009/07/19/departure</id>
      <description><![CDATA[<h1>Departure</h1>
<p>I recently moved on from a company I was with for eight years (my longest time at any one company).  My experience at <span class="caps">HMS</span> was absolutely without equal.  I was given better opportunities than I could have reasonably asked for.  I grew both professionally and personally, and both of my children were born while I was with <span class="caps">HMS</span>.  I was presented with what I believe to be an unique situation and did not make the decision to leave lightly.  I know they will continue to do great things.  Based on some of the feedback I received from friends I&#8217;ve decided to share the email I sent to them as I departed.</p>
<p class="meta">Kyle Burton, 17th July 2009 &#8211; King of Prussia PA</p>
<h2>You&#8217;ll have to&#8230;</h2>
<p>&#8230;do the enthusiastic white boarding; come up with the snide nick names, and make bad puns.  I won&#8217;t be here to do it.</p>
<p>Don&#8217;t be afraid to fail.  Don&#8217;t be afraid that you might not know it all.  Try.</p>
<p>You are all phenomenal at the technical aspect of what you do for <span class="caps">HMS</span>.</p>
<p>If I could give you advice that you&#8217;d follow, it would be this:</p>
<p>Work hard at developing relationships with your peers in the other business units.  They&#8217;re in this as much as you are.  Work to understand the music they have to face standing in front of customers.  Appreciate that you&#8217;re shielded from this.</p>
<p>Learn about every role in the organization: find out what sales faces when presenting what you make; find out what the auditors are validating about the data your systems create.</p>
<p>If you do this, you will find that they will come understand you as you develop empathy for them.  You will be the one has to do it, no one else can do it for you or instead of you.  Do it even if no one else does it back.  If you keep doing it eventually you&#8217;ll see people start to take your lead.</p>
<p>Chaperone your peers across the building.  Walk with them.  Be the one who says lets do it now, lets go see if there over there now.</p>
<p>When you see something you sincerely believe to be exceptional, say so, out loud.  Tell their manager even if that manager is the <span class="caps">CIO</span> or <span class="caps">CEO</span>. You will gain more by doing this than I can possibly tell you.  You will also be surprised at how people will try to live up to the virtues you point out in them.</p>
<p>You are all living through a shared challenge right now.  Realize that what you are doing now is a story; it is a history, it is a rare shared experience.  You have an opportunity to develop deep respect and friendships.  Events like this do not come along often, you may not get the chance again for a long, long time.  You are seeing those around you prove themselves.  As busy as you are, make an effort to see what they are doing.  From what I am seeing it is incredible.</p>
<p>It has been my distinct pleasure working along side each and every one of you.  Thank you for helping me grow these past eight years.</p>
<p>Thank you for being who you are.</p>
<p>Kyle Burton</p>]]></description>
      <content:encoded><![CDATA[<h1>Departure</h1>
<p>I recently moved on from a company I was with for eight years (my longest time at any one company).  My experience at <span class="caps">HMS</span> was absolutely without equal.  I was given better opportunities than I could have reasonably asked for.  I grew both professionally and personally, and both of my children were born while I was with <span class="caps">HMS</span>.  I was presented with what I believe to be an unique situation and did not make the decision to leave lightly.  I know they will continue to do great things.  Based on some of the feedback I received from friends I&#8217;ve decided to share the email I sent to them as I departed.</p>
<p class="meta">Kyle Burton, 17th July 2009 &#8211; King of Prussia PA</p>
<h2>You&#8217;ll have to&#8230;</h2>
<p>&#8230;do the enthusiastic white boarding; come up with the snide nick names, and make bad puns.  I won&#8217;t be here to do it.</p>
<p>Don&#8217;t be afraid to fail.  Don&#8217;t be afraid that you might not know it all.  Try.</p>
<p>You are all phenomenal at the technical aspect of what you do for <span class="caps">HMS</span>.</p>
<p>If I could give you advice that you&#8217;d follow, it would be this:</p>
<p>Work hard at developing relationships with your peers in the other business units.  They&#8217;re in this as much as you are.  Work to understand the music they have to face standing in front of customers.  Appreciate that you&#8217;re shielded from this.</p>
<p>Learn about every role in the organization: find out what sales faces when presenting what you make; find out what the auditors are validating about the data your systems create.</p>
<p>If you do this, you will find that they will come understand you as you develop empathy for them.  You will be the one has to do it, no one else can do it for you or instead of you.  Do it even if no one else does it back.  If you keep doing it eventually you&#8217;ll see people start to take your lead.</p>
<p>Chaperone your peers across the building.  Walk with them.  Be the one who says lets do it now, lets go see if there over there now.</p>
<p>When you see something you sincerely believe to be exceptional, say so, out loud.  Tell their manager even if that manager is the <span class="caps">CIO</span> or <span class="caps">CEO</span>. You will gain more by doing this than I can possibly tell you.  You will also be surprised at how people will try to live up to the virtues you point out in them.</p>
<p>You are all living through a shared challenge right now.  Realize that what you are doing now is a story; it is a history, it is a rare shared experience.  You have an opportunity to develop deep respect and friendships.  Events like this do not come along often, you may not get the chance again for a long, long time.  You are seeing those around you prove themselves.  As busy as you are, make an effort to see what they are doing.  From what I am seeing it is incredible.</p>
<p>It has been my distinct pleasure working along side each and every one of you.  Thank you for helping me grow these past eight years.</p>
<p>Thank you for being who you are.</p>
<p>Kyle Burton</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Array Type Hints in Clojure</title>
      <link>http://asymmetrical-view.com/2009/07/02/clojure-primitive-arrays.html</link>
      <comments>http://asymmetrical-view.com/2009/07/02/clojure-primitive-arrays.html#comments</comments>

      <pubDate>2009-07-02T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2009/07/02/clojure-primitive-arrays.html</guid>

      <id>http://asymmetrical-view.com/2009/07/02/clojure-primitive-arrays</id>
      <description><![CDATA[<p><img src="/images/2009-07/numerical-types-115805043_c5dac1db3c_b.jpg" style="float: left; padding: 1em; " /></p>
<h1>Array Type Hints in Clojure</h1>
<p>How to encode type hints for Java array types came up recently in conversation with a friend and I found it difficult to <a href="http://gootle.com/">Google</a> for so I decided to write it up here.  This is because Java doesn&#8217;t have what you&#8217;d normally think of as a class name for its typed arrays, but first a brief explanation of type hints&#8230;</p>
<h2>Clojure Type Hints</h2>
<p><a href="http://clojure.org/">Clojure</a> allows you to use type declarations, or <a href="http://clojure.org/java_interop#toc35">hints</a>, in two ways.  The first are declarations to the <a href="http://clojure.org/">Clojure</a> compiler which aid in function signature checking.  Type-hinted code will be faster in many cases (when the type was otherwise ambiguous to the compiler) because the <a href="http://clojure.org/">Clojure</a> run-time doesn&#8217;t have to spend time using <a href="http://java.sun.com/docs/books/tutorial/reflect/index.html">Java&#8217;s Reflection <span class="caps">API</span></a> to figure out which underlying method is appropriate for the type of your arguments.  The second aspect of where types used in Clojure is in <a href="http://clojure.org/multimethods">multi-methods</a>, where the types of the arguments are typically used in determining how method resolution is performed.</p>
<div style="clear: left; padding-top: 10px;"></div>
<p>You can see Clojure doing reflective lookups by setting <code>*warn-on-reflection*</code> to <code>true</code>.  Having this set to true while you run your unit tests, or at the end of your development pushes, is a good habit to get into since the performance impact of all the default reflective look-ups is a good thing to eliminate out of your code once things are stable.</p>
<p>Enabling those warnings produces errors that look like this:</p>
<pre class="code">

user&gt; (set! *warn-on-reflection* true)
true
user&gt; (def x (StringBuilder.))
#'user/x
user&gt; (.append x "foo")
Reflection warning, NO_SOURCE_PATH:1 - call to append can't be resolved.
#&lt;StringBuilder foo&gt;
user&gt; (.append x 1)
Reflection warning, NO_SOURCE_PATH:1 - call to append can't be resolved.
#&lt;StringBuilder foo1&gt;
user&gt; 
user&gt; (defn second-ch [s]
        (.charAt s 1))
Reflection warning, NO_SOURCE_PATH:2 - call to charAt can't be resolved.
#'user/second-ch
user&gt; (second-ch "twenty")
\w
user&gt; 

</pre>
<p>Note that the warning happened at the time the function was compiled, not when it is called.  Clojure is warning us that it couldn&#8217;t generate code to call the method directly, but it had to generate code that used the reflection <span class="caps">API</span> to first find the proper method to call and then call it.   We can avoid the expensive reflective look-up and quiet warning by introducing a type-hint for the parameter, telling Clojure that it is a String:</p>
<pre class="code">
user&gt; (defn second-ch [#^String s]
        (.charAt s 1))
#'user/second-ch
user&gt; (second-ch "thirty")
\h
user&gt; 
</pre>
<p>This time there is no warning and the generated code will call <code>charAt</code> directly.</p>
<h2>Multimethods</h2>
<p>Multimethods are the other area where the annotations frequently come into play.  There are 2 steps to defining a basic multimethod.  The first is the <code>defmulti</code> declaration where you name the multi-method and you then provide a function which Clojure will use to dispatch the call to one of the multi-method instances you later declare.  One of the most common dispatch functions is <code>class</code>, which will match up the Java class of the argument to the one declared in the <code>defmethod</code>.</p>
<p>This example declares a multimethod that takes either a String or an Integer:</p>
<pre class="code">

user&gt; (defmulti bar class)
#'user/bar
user&gt; (defmethod bar String  [s] (str "the-str:" s))
#&lt;MultiFn clojure.lang.MultiFn@2e239525&gt;
user&gt; (defmethod bar Integer [s] (str "the-int:" s))
#&lt;MultiFn clojure.lang.MultiFn@2e239525&gt;
user&gt; (bar "this")
"the-str:this"
user&gt; (bar 123)
"the-int:123"
user&gt; 

</pre>
<p>And if you attempt a call with an argument that doesn&#8217;t match any of the declarations:</p>
<pre class="code">
user&gt; (bar 4.56)
; Evaluation aborted.
No method in multimethod 'bar' for dispatch value: class java.lang.Double
  [Thrown class java.lang.IllegalArgumentException]
...
</pre>
<p>That&#8217;s effectively what <a href="http://github.com/kyleburton/krbemacs/tree">Emacs, Slime and Clojure</a> report to me.</p>
<p>There are more nuances to multimethods, like specifying defaults, handling multiple arguments and using your own dispatch functions &#8211; for now, the <a href="http://clojure.org/multimethods">documentation</a> is probably the best place to find out more.</p>
<p><img src="/images/2009-07/led-array-2245492155_795395b056_o.jpg" style="float: right; padding: 1em; " /></p>
<h2>Arrays and Class Names</h2>
<p>So, back to why we&#8217;re here.  As you start using type hints you may (as I did) run into a situation where you want to use a hint for a situation where you have a typed array, or as a dispatching value in multimethods.  Javadoc presents these as <code>Type[]</code> and that is how you encode them in your Java source code.  The problem, though, is that that&#8217;s not what the byte-code or <span class="caps">JVM</span> calls it at run-time, and what it does call it is not syntatically valid in either your Java or Clojure source code.</p>
<div style="clear: both;">
<p>So what are typed arrays called in Java?  Lets ask Java what they&#8217;re called&#8230;you can find out what a String array is called with this bit of example code:</p>
</div>
<pre class="code">
kyleburton@indigo64 ~$ cat Test.java
public class Test {
  public static void main(String [] args) {
    System.out.println("String array: " + args.getClass());
    System.out.println("Byte Array: " + "foo".getBytes().getClass());
  }
}
kyleburton@indigo64 ~$ javac Test.java
kyleburton@indigo64 ~$ java Test
String array: class [Ljava.lang.String;
Byte Array: class [B
kyleburton@indigo64 ~$ 
</pre>
<p>You can get the same information from the Clojure <span class="caps">REPL</span> as well by using Clojure&#8217;s <code>into-array</code>:</p>
<pre class="code">
user&gt; (class (into-array ["a"]))
[Ljava.lang.String;
user&gt; (class (.getBytes "foo"))
[B
user&gt; 
</pre>
<p>So you now know how to ask for the class name of an array you have an instance of.  You can use this to ask <code>Class</code> for the class based on its name (as a String):</p>
<pre class="code">
user&gt; (Class/forName "[B")
[B
user&gt; (Class/forName "[Ljava.lang.String;")
[Ljava.lang.String;
user&gt; 
</pre>
<p>Of course Clojure supports this for primitive types by pluralizing the primitive type:</p>
<pre class="code">
user&gt; (defn foo [#^bytes b] (String. b))
</pre>
<p>That approach doesn&#8217;t work for non-primitive types (classes) though.</p>
<h2>Java Array Type Hints</h2>
<p>Putting these together we can now declare <code>defmethod</code>s using either of these techniques.  Asking the <span class="caps">JVM</span> what the the class is based on a hard-coded example value looks like this:</p>
<pre class="code">

user&gt; (defmethod bar (class (into-array String [])) [s]
        (str "the-string[]:" s))
#&lt;MultiFn clojure.lang.MultiFn@70e8fdc9&gt;
user&gt; (bar (into-array String ["a" "b"]))
"the-string[]:[Ljava.lang.String;@14f3cf72"

</pre>
<p>Using a hard-coded string of the class name as the <span class="caps">JVM</span> sees it (which also works for the primitive types) looks like the following:</p>
<pre class="code">

user&gt; (defmethod bar (Class/forName "[Ljava.lang.String;") [s]
        (str "the-string[]:" s))
#&lt;MultiFn clojure.lang.MultiFn@70e8fdc9&gt;
user&gt; (bar (into-array String ["b" "c"]))
"the-string[]:[Ljava.lang.String;@4597871d"
user&gt; 

user&gt; (defmethod bar (Class/forName "[B") [s] ;; same as #^bytes
        (str "the-bytes:" s))
#&lt;MultiFn clojure.lang.MultiFn@70e8fdc9&gt;
user&gt; (bar (.getBytes "foo"))
"the-bytes:[B@7eedec92"
user&gt; 

</pre>
<p>Even though this works, I recommend staying away from hard-coding the string representation and using <code>Class/forName</code>.  I worry that it might change in a future <span class="caps">JVM</span> release, breaking the code.</p>
<h2>Conclusion</h2>
<p>Even though Clojure does not have direct syntax support for hints for Java arrays, it&#8217;s still possible to use them.</p>
<p class="meta">Kyle Burton, 14th July 2009 &#8211; Wayne PA</p>
<h3>Thanks</h3>
<p>Special thanks to <a href="http://plpatterns.com/">Jonathan Tran</a>, and <a href="http://www.linkedin.com/pub/mike-delaurentis/a/847/b80">Mike DeLaurentis</a> for reading drafts and providing feedback and suggestions.</p>
<h5>Photo Credits</h5>
<ul>
	<li><a href="http://www.flickr.com/photos/threedots/115805043/">Numerical Types</a></li>
	<li><a href="http://www.flickr.com/photos/cibomahto/2245492155/"><span class="caps">LED</span> Array</a></li>
</ul>]]></description>
      <content:encoded><![CDATA[<p><img src="/images/2009-07/numerical-types-115805043_c5dac1db3c_b.jpg" style="float: left; padding: 1em; " /></p>
<h1>Array Type Hints in Clojure</h1>
<p>How to encode type hints for Java array types came up recently in conversation with a friend and I found it difficult to <a href="http://gootle.com/">Google</a> for so I decided to write it up here.  This is because Java doesn&#8217;t have what you&#8217;d normally think of as a class name for its typed arrays, but first a brief explanation of type hints&#8230;</p>
<h2>Clojure Type Hints</h2>
<p><a href="http://clojure.org/">Clojure</a> allows you to use type declarations, or <a href="http://clojure.org/java_interop#toc35">hints</a>, in two ways.  The first are declarations to the <a href="http://clojure.org/">Clojure</a> compiler which aid in function signature checking.  Type-hinted code will be faster in many cases (when the type was otherwise ambiguous to the compiler) because the <a href="http://clojure.org/">Clojure</a> run-time doesn&#8217;t have to spend time using <a href="http://java.sun.com/docs/books/tutorial/reflect/index.html">Java&#8217;s Reflection <span class="caps">API</span></a> to figure out which underlying method is appropriate for the type of your arguments.  The second aspect of where types used in Clojure is in <a href="http://clojure.org/multimethods">multi-methods</a>, where the types of the arguments are typically used in determining how method resolution is performed.</p>
<div style="clear: left; padding-top: 10px;"></div>
<p>You can see Clojure doing reflective lookups by setting <code>*warn-on-reflection*</code> to <code>true</code>.  Having this set to true while you run your unit tests, or at the end of your development pushes, is a good habit to get into since the performance impact of all the default reflective look-ups is a good thing to eliminate out of your code once things are stable.</p>
<p>Enabling those warnings produces errors that look like this:</p>
<pre class="code">

user&gt; (set! *warn-on-reflection* true)
true
user&gt; (def x (StringBuilder.))
#'user/x
user&gt; (.append x "foo")
Reflection warning, NO_SOURCE_PATH:1 - call to append can't be resolved.
#&lt;StringBuilder foo&gt;
user&gt; (.append x 1)
Reflection warning, NO_SOURCE_PATH:1 - call to append can't be resolved.
#&lt;StringBuilder foo1&gt;
user&gt; 
user&gt; (defn second-ch [s]
        (.charAt s 1))
Reflection warning, NO_SOURCE_PATH:2 - call to charAt can't be resolved.
#'user/second-ch
user&gt; (second-ch "twenty")
\w
user&gt; 

</pre>
<p>Note that the warning happened at the time the function was compiled, not when it is called.  Clojure is warning us that it couldn&#8217;t generate code to call the method directly, but it had to generate code that used the reflection <span class="caps">API</span> to first find the proper method to call and then call it.   We can avoid the expensive reflective look-up and quiet warning by introducing a type-hint for the parameter, telling Clojure that it is a String:</p>
<pre class="code">
user&gt; (defn second-ch [#^String s]
        (.charAt s 1))
#'user/second-ch
user&gt; (second-ch "thirty")
\h
user&gt; 
</pre>
<p>This time there is no warning and the generated code will call <code>charAt</code> directly.</p>
<h2>Multimethods</h2>
<p>Multimethods are the other area where the annotations frequently come into play.  There are 2 steps to defining a basic multimethod.  The first is the <code>defmulti</code> declaration where you name the multi-method and you then provide a function which Clojure will use to dispatch the call to one of the multi-method instances you later declare.  One of the most common dispatch functions is <code>class</code>, which will match up the Java class of the argument to the one declared in the <code>defmethod</code>.</p>
<p>This example declares a multimethod that takes either a String or an Integer:</p>
<pre class="code">

user&gt; (defmulti bar class)
#'user/bar
user&gt; (defmethod bar String  [s] (str "the-str:" s))
#&lt;MultiFn clojure.lang.MultiFn@2e239525&gt;
user&gt; (defmethod bar Integer [s] (str "the-int:" s))
#&lt;MultiFn clojure.lang.MultiFn@2e239525&gt;
user&gt; (bar "this")
"the-str:this"
user&gt; (bar 123)
"the-int:123"
user&gt; 

</pre>
<p>And if you attempt a call with an argument that doesn&#8217;t match any of the declarations:</p>
<pre class="code">
user&gt; (bar 4.56)
; Evaluation aborted.
No method in multimethod 'bar' for dispatch value: class java.lang.Double
  [Thrown class java.lang.IllegalArgumentException]
...
</pre>
<p>That&#8217;s effectively what <a href="http://github.com/kyleburton/krbemacs/tree">Emacs, Slime and Clojure</a> report to me.</p>
<p>There are more nuances to multimethods, like specifying defaults, handling multiple arguments and using your own dispatch functions &#8211; for now, the <a href="http://clojure.org/multimethods">documentation</a> is probably the best place to find out more.</p>
<p><img src="/images/2009-07/led-array-2245492155_795395b056_o.jpg" style="float: right; padding: 1em; " /></p>
<h2>Arrays and Class Names</h2>
<p>So, back to why we&#8217;re here.  As you start using type hints you may (as I did) run into a situation where you want to use a hint for a situation where you have a typed array, or as a dispatching value in multimethods.  Javadoc presents these as <code>Type[]</code> and that is how you encode them in your Java source code.  The problem, though, is that that&#8217;s not what the byte-code or <span class="caps">JVM</span> calls it at run-time, and what it does call it is not syntatically valid in either your Java or Clojure source code.</p>
<div style="clear: both;">
<p>So what are typed arrays called in Java?  Lets ask Java what they&#8217;re called&#8230;you can find out what a String array is called with this bit of example code:</p>
</div>
<pre class="code">
kyleburton@indigo64 ~$ cat Test.java
public class Test {
  public static void main(String [] args) {
    System.out.println("String array: " + args.getClass());
    System.out.println("Byte Array: " + "foo".getBytes().getClass());
  }
}
kyleburton@indigo64 ~$ javac Test.java
kyleburton@indigo64 ~$ java Test
String array: class [Ljava.lang.String;
Byte Array: class [B
kyleburton@indigo64 ~$ 
</pre>
<p>You can get the same information from the Clojure <span class="caps">REPL</span> as well by using Clojure&#8217;s <code>into-array</code>:</p>
<pre class="code">
user&gt; (class (into-array ["a"]))
[Ljava.lang.String;
user&gt; (class (.getBytes "foo"))
[B
user&gt; 
</pre>
<p>So you now know how to ask for the class name of an array you have an instance of.  You can use this to ask <code>Class</code> for the class based on its name (as a String):</p>
<pre class="code">
user&gt; (Class/forName "[B")
[B
user&gt; (Class/forName "[Ljava.lang.String;")
[Ljava.lang.String;
user&gt; 
</pre>
<p>Of course Clojure supports this for primitive types by pluralizing the primitive type:</p>
<pre class="code">
user&gt; (defn foo [#^bytes b] (String. b))
</pre>
<p>That approach doesn&#8217;t work for non-primitive types (classes) though.</p>
<h2>Java Array Type Hints</h2>
<p>Putting these together we can now declare <code>defmethod</code>s using either of these techniques.  Asking the <span class="caps">JVM</span> what the the class is based on a hard-coded example value looks like this:</p>
<pre class="code">

user&gt; (defmethod bar (class (into-array String [])) [s]
        (str "the-string[]:" s))
#&lt;MultiFn clojure.lang.MultiFn@70e8fdc9&gt;
user&gt; (bar (into-array String ["a" "b"]))
"the-string[]:[Ljava.lang.String;@14f3cf72"

</pre>
<p>Using a hard-coded string of the class name as the <span class="caps">JVM</span> sees it (which also works for the primitive types) looks like the following:</p>
<pre class="code">

user&gt; (defmethod bar (Class/forName "[Ljava.lang.String;") [s]
        (str "the-string[]:" s))
#&lt;MultiFn clojure.lang.MultiFn@70e8fdc9&gt;
user&gt; (bar (into-array String ["b" "c"]))
"the-string[]:[Ljava.lang.String;@4597871d"
user&gt; 

user&gt; (defmethod bar (Class/forName "[B") [s] ;; same as #^bytes
        (str "the-bytes:" s))
#&lt;MultiFn clojure.lang.MultiFn@70e8fdc9&gt;
user&gt; (bar (.getBytes "foo"))
"the-bytes:[B@7eedec92"
user&gt; 

</pre>
<p>Even though this works, I recommend staying away from hard-coding the string representation and using <code>Class/forName</code>.  I worry that it might change in a future <span class="caps">JVM</span> release, breaking the code.</p>
<h2>Conclusion</h2>
<p>Even though Clojure does not have direct syntax support for hints for Java arrays, it&#8217;s still possible to use them.</p>
<p class="meta">Kyle Burton, 14th July 2009 &#8211; Wayne PA</p>
<h3>Thanks</h3>
<p>Special thanks to <a href="http://plpatterns.com/">Jonathan Tran</a>, and <a href="http://www.linkedin.com/pub/mike-delaurentis/a/847/b80">Mike DeLaurentis</a> for reading drafts and providing feedback and suggestions.</p>
<h5>Photo Credits</h5>
<ul>
	<li><a href="http://www.flickr.com/photos/threedots/115805043/">Numerical Types</a></li>
	<li><a href="http://www.flickr.com/photos/cibomahto/2245492155/"><span class="caps">LED</span> Array</a></li>
</ul>]]></content:encoded>
    </item>
    
    <item>
      <title>Creating Executable Jars For Your Clojure Application</title>
      <link>http://asymmetrical-view.com/2009/06/22/executable-clojure-jars.html</link>
      <comments>http://asymmetrical-view.com/2009/06/22/executable-clojure-jars.html#comments</comments>

      <pubDate>2009-06-22T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2009/06/22/executable-clojure-jars.html</guid>

      <id>http://asymmetrical-view.com/2009/06/22/executable-clojure-jars</id>
      <description><![CDATA[<h1>Creating Executable Jars For Your Clojure Application</h1>
<p><img src="/images/2009-06/green-glowing-jar.jpg" style="float: left; margin-right: 1em; " /></p>
<p>It is possible to create stand alone executable <a href="http://en.wikipedia.org/wiki/JAR_(file_format%29">Jar</a> files for your <a href="http://clojure.org/">Clojure</a> programs.  In this post I walk you through the issues you need to keep in mind and the steps you need to take to create the jar.  You can download the example code this post walks through in its entirety from my <a href="http://github.com/kyleburton/sandbox/tree/master">GitHub</a> account (under examples/exec-jar).</p>
<p>I used <a href="http://ant.apache.org/">ant</a> to build the jar, other <a href="http://maven.apache.org/">Java development tools</a> can also do the task.</p>
<h3>Jar Files</h3>
<p>Jar files are <a href="http://en.wikipedia.org/wiki/ZIP_(file_format%29">Zip</a> files with a few conventions for what goes where and of their contents.  Jar files support a <a href="http://en.wikipedia.org/wiki/Manifest_file">Manifest File</a> file which tells Java what the archive contains.  The manifest file has a simple format of key/value pairs, very similar to an <span class="caps">HTTP</span> header.  This is manifest for the Clojure Jar:</p>
<pre class="code">
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.1
Created-By: 11.2-b01 (Sun Microsystems Inc.)
Main-Class: clojure.main
Class-Path: .
</pre>
<p>The important bit there is &#8216;Main-Class&#8217;.  The Main-Class specifies the Java class that will be executed by default when run as <code>java -jar clojure.jar</code>.  In <code>clojure.jar</code> the main class is <code>clojure.main</code>.</p>
<h3>Clojure Application</h3>
<p>The example application performs a <a href="http://google.com/">Google</a> search, printing each link and its text:</p>
<pre class="code">

(ns com.github.kyleburton.app
  (:gen-class)
  (:use [com.github.kyleburton.sandbox.web :as kweb]
        [com.github.kyleburton.sandbox.landmark-parser :as lp]
        [clojure.contrib.str-utils :as str-utils]))

(defn fetch-page [terms]
  (let [page (kweb/get-&gt;string (format "http://www.google.com/search?q=%s" (str-utils/str-join "+" terms)))]
    (doseq [link (filter #(.contains % "class=l") (lp/html-&gt;anchors page))]
      (let [href (lp/anchor-&gt;href link)
            text (kweb/strip-html (lp/anchor-&gt;body link))]
        (println text)
        (println href)
        (println "\n")))))

(defn show-help []
  (pritnln
   "app term [term2 [term3 ...]]

Performs a Google Search for the given terms

"))

(defn -main [&amp; terms]
  (cond (empty? terms)
        (show-help)
        true
        (fetch-page terms)))



</pre>
<h3>Compilation</h3>
<p>Java will only run Java byte code so we need to compile the application.  I&#8217;ve set up the <code>build.xml</code> to do so:</p>
<pre class="code">

  &lt;target name="compile" description="Run the Clojure Compiler"&gt;
    &lt;property name="cpath" refid="classpath" /&gt;
    &lt;echo message="cpath=${cpath}" /&gt;
    &lt;mkdir dir="${classes.dir}"/&gt;
    &lt;java classname="clojure.lang.Compile" fork="true"&gt;
      &lt;sysproperty key="clojure.compile.path" value="${classes.dir}" /&gt;
      &lt;classpath refid="classpath" /&gt;
      &lt;arg value="com.github.kyleburton.app" /&gt;
    &lt;/java&gt;
  &lt;/target&gt;

</pre>
<p>The <code>jar-with-manifest</code> then uses the compiled classes, generates a manifest file and uses <a href="http://ant.apache.org/">Ant&#8217;s</a> <code>jar</code> task with a series of <code>zipfileset</code>s to combine the clojure, clojure-contrib and other dependency&#8217;s jars into a single, executable, jar:</p>
<pre class="code">

  &lt;target name="jar-with-manifest" depends="compile" description="Build the JAR"&gt;
    &lt;manifest file="${target.dir}/MANIFEST.MF"&gt;
      &lt;attribute name="Built-By" value="${user.name}" /&gt;
      &lt;attribute name="Main-Class" value="com.github.kyleburton.app" /&gt;
    &lt;/manifest&gt;
    &lt;jar jarfile="${target.dir}/${jar.file.name}" manifest="${target.dir}/MANIFEST.MF"&gt;
      &lt;fileset dir="${classes.dir}" includes="**/*.class"/&gt;
      &lt;zipfileset src="${clojure.jar}" /&gt;
      &lt;zipfileset src="${clojure-contrib.jar}" /&gt;
      &lt;zipfileset src="${krb-utils.jar.repo}/commons-httpclient-3.1.jar" /&gt;
      &lt;zipfileset src="${krb-utils.jar.repo}/commons-codec-1.3.jar" /&gt;
      &lt;zipfileset src="${krb-utils.jar.repo}//commons-logging-1.1.1.jar" /&gt;
      &lt;zipfileset src="${krb-utils.jar.repo}//commons-logging-1.1.1-sources.jar" /&gt;
      &lt;zipfileset src="${krb-utils.jar.repo}//commons-logging-adapters-1.1.1.jar" /&gt;
      &lt;zipfileset src="${krb-utils.jar.repo}//commons-logging-api-1.1.1.jar" /&gt;
    &lt;/jar&gt;
  &lt;/target&gt;

</pre>
<h3>Running The Application</h3>
<p>Our application can now be run all by itself with <code>java -jar ...</code>:</p>
<pre class="code">

kyleburton@indigo64 exec-jar[master*]$ java -jar target/exec-jar-0.1.jar ant zipfileset

ZipFileSet Type
http://ant.apache.org/manual/CoreTypes/zipfileset.html

Zip Task
http://ant.apache.org/manual/CoreTasks/zip.html

Ant Best Practices: Use ZipFileSet | The Build Doctor
http://www.build-doctor.com/2008/07/13/ant-best-practices-use-zipfileset

Top 15 Ant Best Practices - O&amp;#39;Reilly Media
http://www.onjava.com/pub/a/onjava/2003/12/17/ant_bestpractices.html

&amp;#39;cvs commit: ant/src/main/org/apache/tools/ant/types ZipFileSet ...
http://marc.info/?l=ant-dev&amp;m=112197754500691&amp;w=2

[picocontainer-scm] [CVS java] improved maven scri: msg#00056 java ...
http://osdir.com/ml/java.picocontainer.cvs/2004-07/msg00056.html

ZipFileSet Apache Ant 1.6.5 API Documentation and Javadoc
http://www.jdocs.com/link/org/apache/tools/ant/types/zipfileset.html

svn commit: r719578 - /ant/core/trunk/src/tests/antunit/types ...
http://mail-archives.apache.org/mod_mbox/ant-notifications/200811.mbox/%3C20081121133918.572D2238889E@eris.apache.org%3E

ZipFileSet (Apache Ant API)
http://lia.deis.unibo.it/Courses/TecnologieWeb0607/materiale/laboratorio/ant/api/org/apache/tools/ant/types/ZipFileSet.html

[news.eclipse.platform] Re: Problem with ANT zipfileset ... Re ...
http://dev.eclipse.org/newslists/news.eclipse.platform/msg07778.html

kyleburton@indigo64 exec-jar[master]$ 

</pre>
<h3>Conclusion</h3>
<p><img src="/images/2009-06/glass-jar.jpg" style="float: right; margin-left: 1em; " /></p>
<p>Bundling your application into a single Jar can simplify the deployment, and distribution of your application.  What tends to be less desirable about this technique though is that you have to track your dependencies carefully (you risk <code>ClassNotFoundException</code>s) and the jars you create are often quite large.  You can not add additional jars or paths to the classpath when running <code>java -jar</code>, which means that you won&#8217;t be able to re-use the libraries across other applications.</p>
<p>This technique allows you to create a single file that your users can download to run your clojure based applications.</p>
<p class="meta">Kyle Burton, 28th June 2009 &#8211; Wayne PA</p>
<h4>Links</h4>
<ul>
	<li><a href="http://java.sun.com/docs/books/tutorial/deployment/jar/" title="Sun">Jar Deployment Tutorial</a></li>
	<li><a href="http://java.sun.com/docs/books/tutorial/deployment/jar/manifestindex.html" title="Sun">Manifest Files</a></li>
</ul>
<h5>Photo Credits</h5>
<ul>
	<li><a href="http://www.flickr.com/photos/mmechtley/2110083185/sizes/l/">Green Glowing Jars</a></li>
	<li><a href="http://www.flickr.com/photos/mmechtley/2110083601/sizes/l/in/set-72157603453391346/">Blue Glowing Jars</a></li>
	<li><a href="http://www.flickr.com/photos/pacomexico/3288346239/sizes/l/">Cookie Jar and Orange</a></li>
	<li><a href="http://www.flickr.com/photos/riotjane/2216995811/sizes/l/">Glass Jar</a></li>
</ul>]]></description>
      <content:encoded><![CDATA[<h1>Creating Executable Jars For Your Clojure Application</h1>
<p><img src="/images/2009-06/green-glowing-jar.jpg" style="float: left; margin-right: 1em; " /></p>
<p>It is possible to create stand alone executable <a href="http://en.wikipedia.org/wiki/JAR_(file_format%29">Jar</a> files for your <a href="http://clojure.org/">Clojure</a> programs.  In this post I walk you through the issues you need to keep in mind and the steps you need to take to create the jar.  You can download the example code this post walks through in its entirety from my <a href="http://github.com/kyleburton/sandbox/tree/master">GitHub</a> account (under examples/exec-jar).</p>
<p>I used <a href="http://ant.apache.org/">ant</a> to build the jar, other <a href="http://maven.apache.org/">Java development tools</a> can also do the task.</p>
<h3>Jar Files</h3>
<p>Jar files are <a href="http://en.wikipedia.org/wiki/ZIP_(file_format%29">Zip</a> files with a few conventions for what goes where and of their contents.  Jar files support a <a href="http://en.wikipedia.org/wiki/Manifest_file">Manifest File</a> file which tells Java what the archive contains.  The manifest file has a simple format of key/value pairs, very similar to an <span class="caps">HTTP</span> header.  This is manifest for the Clojure Jar:</p>
<pre class="code">
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.1
Created-By: 11.2-b01 (Sun Microsystems Inc.)
Main-Class: clojure.main
Class-Path: .
</pre>
<p>The important bit there is &#8216;Main-Class&#8217;.  The Main-Class specifies the Java class that will be executed by default when run as <code>java -jar clojure.jar</code>.  In <code>clojure.jar</code> the main class is <code>clojure.main</code>.</p>
<h3>Clojure Application</h3>
<p>The example application performs a <a href="http://google.com/">Google</a> search, printing each link and its text:</p>
<pre class="code">

(ns com.github.kyleburton.app
  (:gen-class)
  (:use [com.github.kyleburton.sandbox.web :as kweb]
        [com.github.kyleburton.sandbox.landmark-parser :as lp]
        [clojure.contrib.str-utils :as str-utils]))

(defn fetch-page [terms]
  (let [page (kweb/get-&gt;string (format "http://www.google.com/search?q=%s" (str-utils/str-join "+" terms)))]
    (doseq [link (filter #(.contains % "class=l") (lp/html-&gt;anchors page))]
      (let [href (lp/anchor-&gt;href link)
            text (kweb/strip-html (lp/anchor-&gt;body link))]
        (println text)
        (println href)
        (println "\n")))))

(defn show-help []
  (pritnln
   "app term [term2 [term3 ...]]

Performs a Google Search for the given terms

"))

(defn -main [&amp; terms]
  (cond (empty? terms)
        (show-help)
        true
        (fetch-page terms)))



</pre>
<h3>Compilation</h3>
<p>Java will only run Java byte code so we need to compile the application.  I&#8217;ve set up the <code>build.xml</code> to do so:</p>
<pre class="code">

  &lt;target name="compile" description="Run the Clojure Compiler"&gt;
    &lt;property name="cpath" refid="classpath" /&gt;
    &lt;echo message="cpath=${cpath}" /&gt;
    &lt;mkdir dir="${classes.dir}"/&gt;
    &lt;java classname="clojure.lang.Compile" fork="true"&gt;
      &lt;sysproperty key="clojure.compile.path" value="${classes.dir}" /&gt;
      &lt;classpath refid="classpath" /&gt;
      &lt;arg value="com.github.kyleburton.app" /&gt;
    &lt;/java&gt;
  &lt;/target&gt;

</pre>
<p>The <code>jar-with-manifest</code> then uses the compiled classes, generates a manifest file and uses <a href="http://ant.apache.org/">Ant&#8217;s</a> <code>jar</code> task with a series of <code>zipfileset</code>s to combine the clojure, clojure-contrib and other dependency&#8217;s jars into a single, executable, jar:</p>
<pre class="code">

  &lt;target name="jar-with-manifest" depends="compile" description="Build the JAR"&gt;
    &lt;manifest file="${target.dir}/MANIFEST.MF"&gt;
      &lt;attribute name="Built-By" value="${user.name}" /&gt;
      &lt;attribute name="Main-Class" value="com.github.kyleburton.app" /&gt;
    &lt;/manifest&gt;
    &lt;jar jarfile="${target.dir}/${jar.file.name}" manifest="${target.dir}/MANIFEST.MF"&gt;
      &lt;fileset dir="${classes.dir}" includes="**/*.class"/&gt;
      &lt;zipfileset src="${clojure.jar}" /&gt;
      &lt;zipfileset src="${clojure-contrib.jar}" /&gt;
      &lt;zipfileset src="${krb-utils.jar.repo}/commons-httpclient-3.1.jar" /&gt;
      &lt;zipfileset src="${krb-utils.jar.repo}/commons-codec-1.3.jar" /&gt;
      &lt;zipfileset src="${krb-utils.jar.repo}//commons-logging-1.1.1.jar" /&gt;
      &lt;zipfileset src="${krb-utils.jar.repo}//commons-logging-1.1.1-sources.jar" /&gt;
      &lt;zipfileset src="${krb-utils.jar.repo}//commons-logging-adapters-1.1.1.jar" /&gt;
      &lt;zipfileset src="${krb-utils.jar.repo}//commons-logging-api-1.1.1.jar" /&gt;
    &lt;/jar&gt;
  &lt;/target&gt;

</pre>
<h3>Running The Application</h3>
<p>Our application can now be run all by itself with <code>java -jar ...</code>:</p>
<pre class="code">

kyleburton@indigo64 exec-jar[master*]$ java -jar target/exec-jar-0.1.jar ant zipfileset

ZipFileSet Type
http://ant.apache.org/manual/CoreTypes/zipfileset.html

Zip Task
http://ant.apache.org/manual/CoreTasks/zip.html

Ant Best Practices: Use ZipFileSet | The Build Doctor
http://www.build-doctor.com/2008/07/13/ant-best-practices-use-zipfileset

Top 15 Ant Best Practices - O&amp;#39;Reilly Media
http://www.onjava.com/pub/a/onjava/2003/12/17/ant_bestpractices.html

&amp;#39;cvs commit: ant/src/main/org/apache/tools/ant/types ZipFileSet ...
http://marc.info/?l=ant-dev&amp;m=112197754500691&amp;w=2

[picocontainer-scm] [CVS java] improved maven scri: msg#00056 java ...
http://osdir.com/ml/java.picocontainer.cvs/2004-07/msg00056.html

ZipFileSet Apache Ant 1.6.5 API Documentation and Javadoc
http://www.jdocs.com/link/org/apache/tools/ant/types/zipfileset.html

svn commit: r719578 - /ant/core/trunk/src/tests/antunit/types ...
http://mail-archives.apache.org/mod_mbox/ant-notifications/200811.mbox/%3C20081121133918.572D2238889E@eris.apache.org%3E

ZipFileSet (Apache Ant API)
http://lia.deis.unibo.it/Courses/TecnologieWeb0607/materiale/laboratorio/ant/api/org/apache/tools/ant/types/ZipFileSet.html

[news.eclipse.platform] Re: Problem with ANT zipfileset ... Re ...
http://dev.eclipse.org/newslists/news.eclipse.platform/msg07778.html

kyleburton@indigo64 exec-jar[master]$ 

</pre>
<h3>Conclusion</h3>
<p><img src="/images/2009-06/glass-jar.jpg" style="float: right; margin-left: 1em; " /></p>
<p>Bundling your application into a single Jar can simplify the deployment, and distribution of your application.  What tends to be less desirable about this technique though is that you have to track your dependencies carefully (you risk <code>ClassNotFoundException</code>s) and the jars you create are often quite large.  You can not add additional jars or paths to the classpath when running <code>java -jar</code>, which means that you won&#8217;t be able to re-use the libraries across other applications.</p>
<p>This technique allows you to create a single file that your users can download to run your clojure based applications.</p>
<p class="meta">Kyle Burton, 28th June 2009 &#8211; Wayne PA</p>
<h4>Links</h4>
<ul>
	<li><a href="http://java.sun.com/docs/books/tutorial/deployment/jar/" title="Sun">Jar Deployment Tutorial</a></li>
	<li><a href="http://java.sun.com/docs/books/tutorial/deployment/jar/manifestindex.html" title="Sun">Manifest Files</a></li>
</ul>
<h5>Photo Credits</h5>
<ul>
	<li><a href="http://www.flickr.com/photos/mmechtley/2110083185/sizes/l/">Green Glowing Jars</a></li>
	<li><a href="http://www.flickr.com/photos/mmechtley/2110083601/sizes/l/in/set-72157603453391346/">Blue Glowing Jars</a></li>
	<li><a href="http://www.flickr.com/photos/pacomexico/3288346239/sizes/l/">Cookie Jar and Orange</a></li>
	<li><a href="http://www.flickr.com/photos/riotjane/2216995811/sizes/l/">Glass Jar</a></li>
</ul>]]></content:encoded>
    </item>
    
    <item>
      <title>Visualizing AMQP Broker Behavior with Clojure and Incanter</title>
      <link>http://asymmetrical-view.com/2009/06/02/incanter-amqp-benchmark.html</link>
      <comments>http://asymmetrical-view.com/2009/06/02/incanter-amqp-benchmark.html#comments</comments>

      <pubDate>2009-06-02T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2009/06/02/incanter-amqp-benchmark.html</guid>

      <id>http://asymmetrical-view.com/2009/06/02/incanter-amqp-benchmark</id>
      <description><![CDATA[<h1>Visualizing <span class="caps">AMQP</span> Broker Behavior with Clojure and Incanter</h1>
<p><img src="/images/2009-06/rabbit-run.jpg" style="float: left; margin-right: 1em; " /></p>
<p>I&#8217;m working with our system architect (<a href="http://www.linkedin.com/pub/mark-mehalik/13/113/461">Mark Mehalik</a>) evaluating <a href="http://amqp.org/"><span class="caps">AMQP</span></a> as a messaging implementation for a new project.  One of the things want to prove out is how the brokers behave under a widely varying number messages, message sizes, numbers of producers, consumers, queues and in differing clustering configurations.  Since <a href="http://amqp.org/"><span class="caps">AMQP</span></a> is a standard we should be able to build a single test suite and then execute it against the different brokers to measure their behavior as well as how robust they are under those conditions.</p>
<h2>Scripting and Automation</h2>
<p>I started the process of mocking up and automating the tests with the goal to help us figure out what we want to test.  I chose to do this with <a href="http://clojure.org/">Clojure</a> and to use <a href="http://github.com/liebke/incanter/tree/master">Incanter</a> for a quick and easy visualization.  You can the check the code out of my <a href="http://github.com/kyleburton/sandbox/tree/master">sandbox</a> project on <a href="http://github.com/">GitHub</a>.  The example code exercises a local <a href="http://amqp.org/"><span class="caps">AMQP</span></a> v0.8 broker using the <a href="http://www.rabbitmq.com/">RabbitMQ</a> Java Client Libraries (which support 0.8 at this time).</p>
<h3>Producer</h3>
<p>To test the broker, I created a simple producer and consumer and had them pass small (371 byte) messages.  They use the simple Rabbit Java client library primitives for <tt>Channel.basicPublish</tt> and <tt>Channel.basicGet</tt>.  The message consists of an array of two values: a message id (integer); and a time-stamp (<tt>java.util.Date</tt>).  They get serialized and placed into the <a href="http://amqp.org/"><span class="caps">AMQP</span></a> message body.  The producer just loops pushing all the messages to the broker and then logs its start and end times:</p>
<pre class="code">
(defn producer [producer-num cnt]
  (rabbit/with-amqp
   {}
   (let [start-time now]
     (dotimes [ii cnt]
       (object-publish [ii (Date.)]))
     (log-producer-stat producer-num cnt start-time (now)))))
</pre>
<h3>Consumer</h3>
<p>The consumer is a bit more more complex, doing more book keeping.  It tracks the number of messages it receives, its own elapsed time and totals up the amount of time each message was spent on the queue.  Just as with the producer, it logs its timings after it has consumed all of the messages on the queue.</p>
<pre class="code">
(defn consumer [consumer-num]
  (rabbit/with-amqp
   {}
   (let [start-time (now -1)
         num-msgs   (atom 0)
         msg-age    (atom 0)]
     (loop [[ii dt] (rabbit/object-get)]
       (if ii
         (let [end         (now -1)
               msg-elapsed (- end (.getTime dt))]
           (reset! num-msgs (+ 1 @num-msgs))
           (reset! msg-age  (+ msg-elapsed @msg-age))
           (recur (rabbit/object-get)))))
     (log-consumer-stat consumer-num @num-msgs start-time (now) @msg-age)
     (let [elapsed (/ (- (now) start-time) 1000.0)
           rate    (/ @num-msgs elapsed)]
       (prn (format "%s messages in %s elapsed seconds @ %s/second"
                    @num-msgs
                    elapsed
                    rate))))))
</pre>
<h3>Benchmark</h3>
<p>I chose to run a series of tests with message counts from 1 up to 500k, repeating each test three times.  This is only to get some data to play with, we plan on creating longer running and distributed tests over the next week to measure the behavior of the brokers in other configurations.  This test was enough to produce data for me to try out <a href="http://github.com/liebke/incanter/tree/master">Incanter</a> with though and given how easy this was to create, we&#8217;ll likely continue to modify this set of files.</p>
<pre class="code">
(defn run-benchmark [broker num-prods num-cons]
  (doseq [msg-count [1 5 10 50 100 500 1000 5000 10000 50000 100000 500000]]
    (run-single-benchmark (format "Series-%sm-%sp-%sc" msg-count num-prods num-cons)
                          broker
                          3 
                          msg-count
                          num-prods))
  (prn (format "run-benchmark: %s completed" broker)))

(defn run-single-benchmark [series broker num-runs num-msgs num-producers]
  (dotimes [run-number num-runs]
    (binding [*testing-info* (merge *testing-info*
                                    {:series  series
                                     :broker  broker
                                     :run-num (+ 1 run-number)})]
      (let [msgs-per-producer (/ num-msgs num-producers)]
        (dotimes [ii num-producers]
          (.start (Thread. (fn [] (producer (format "p%s" ii) msgs-per-producer))))))
      (Thread/sleep 100)
      (consumer "c1"))))
</pre>
<h3>Incanter Visualization</h3>
<p>Once we had run this against <a href="http://qpid.apache.org/">Apache&#8217;s Qpid</a> and <a href="http://rabbitmq.com/">RabbitMQ</a> there was enough data to produce some charts.   There is code to support loading the collected data from the files from disk, and the <a href="http://github.com/liebke/incanter/tree/master">Incanter</a> code is wonderfully easy to use.</p>
<p><tt>get-stat-data</tt> pulls the data from the consumer log for the named broker as a sequence of maps where the column headers are the keys and the row fields are the values.  <tt>get-xy-data</tt> pulls two of the fields and separates them into two sequences &#8211; just what the plotting functions in <a href="http://github.com/liebke/incanter/tree/master">Incanter</a> expect.  <tt>simple-xy-plot</tt> then passes the two sequences to <a href="http://github.com/liebke/incanter/tree/master&#39;s">Incanter</a> line-plot to visualize the data.</p>
<pre class="code">
(defn get-xy-data [broker xname yname]
  (let [stat-data (get-stat-data broker *consumer-stats-file*)
        count-and-rate (map (fn [ent] [(ent xname) (ent yname)]) stat-data)
        x-vals    (map #(Double/parseDouble (% 0))  count-and-rate)
        y-vals    (map #(Double/parseDouble (% 1))  count-and-rate)]
    [x-vals y-vals]))

(defn simple-xy-plot [broker xname yname]
  (let [rabbit-data (get-xy-data broker xname yname)]
    (line-plot (rabbit-data 0) (rabbit-data 1)
               :title (format "%s vs %s" xname yname)
               :x-label xname
               :y-label yname)))

(view (simple-xy-plot "RabbitMQ"    "TOTAL-MESSAGES" "M/S"))
(view (simple-xy-plot "Apache-Qpid" "TOTAL-MESSAGES" "M/S"))
</pre>
<div style="margin-top: 4em; margin-bottom: 4em;">
<p><img src="/images/2009-06/feisty-rabbit.jpg" style="float: right; margin-left: 2em;" height="219" width="256" /></p>
<p>I ran the broker, and a single <span class="caps">JVM</span> hosting both the producer and consumer on my workstation (along with all my other processes, X, <span class="caps">KDE</span>, Emacs and a ton of other processes).  I did no tuning of the brokers, running them in their default configurations.  I don&#8217;t expect these numbers to be too representative of the brokers performance in any kind of production configuration.</p>
<p>There are a few other interesting findings:  With no tuning Qpid failed at 100k messages with an out of memory exception (crashed hard).  This was with the default 1024Mb heap setting, at 2048Mb it was able to handle 100k messages and the graph shows Qpid using the 2048Mb heap setting.  Rabbit survived up to 500k message (as far as I pushed it), <em>but</em> the performance degraded significantly down to about 170 messages per second.</p>
</div>
<h4>Qpid <span class="caps">RSS</span></h4>
<p><img src="/images/2009-06/qpid-mem-rss.png" /></p>
<p>This shows the 2048M heap configuration growing up to the 100k message mark.</p>
<h4>Qpid <span class="caps">VSS</span></h4>
<p><img src="/images/2009-06/qpid-mem-vss.png" /></p>
<p>The flatness of this isn&#8217;t surprising as the <span class="caps">JVM</span> allocated its entire heap all at once.</p>
<h4>Rabbit <span class="caps">RSS</span></h4>
<p><img src="/images/2009-06/rabbit-mem-rss.png" /></p>
<p><a href="http://erlang.org/">Erlang&#8217;s</a> a bit more interesting, you can see it trying to cope with the various message loads, spiking up to about 3/4 of a gig with 500k messages.  In this configuration Rabbit&#8217;s rate dropped significantly from its average, to about 170/s.  It did stay up though.  The next step here is to see what we can learn about how Rabbit is handling this deluge of messages.</p>
<h4>Rabbit <span class="caps">VSS</span></h4>
<p><img src="/images/2009-06/rabbit-mem-vss.png" /></p>
<p>This pretty closely follows the shape of the <span class="caps">RSS</span> graph.</p>
<h4><font color="red">Rabbit</font> vs <font color="blue">Qpid</font> Messages per Second</h4>
<p><img src="/images/2009-06/rabbit-vs-qpid-mps.png" /></p>
<h2>Clojure and Incanter</h2>
<p>It was very straight forward to set up these benchmarks and the graphing code with Clojure and Incanter.  We were able to try different approaches and visualizations very rapidly.  Clojure&#8217;s ease of development and Incanter&#8217;s high level graphing functions turned the profiling from a chore into a fun task.</p>
<p class="meta">Kyle Burton, 2nd June 2009 &#8211; King of Prussia PA</p>
<h5>Photo Credits</h5>
<ul>
	<li><a href="http://www.flickr.com/photos/sapphir3blu3/3235526282/sizes/l/">Rabbit Run</a></li>
	<li><a href="http://www.flickr.com/photos/markhillary/2950218730/sizes/l/">Nail Filer</a></li>
	<li><a href="http://www.flickr.com/photos/boskizzi/4731745/sizes/o/">Dead Rabbit</a></li>
	<li><a href="http://www.flickr.com/photos/flik/3182151968/sizes/l/">feisty rabbit</a></li>
	<li><a href="http://www.flickr.com/photos/thetim/458733962/">dryer rabbit</a></li>
	<li><a href="http://www.flickr.com/photos/53366513@N00/67046506/">hidden rabbit</a></li>
</ul>]]></description>
      <content:encoded><![CDATA[<h1>Visualizing <span class="caps">AMQP</span> Broker Behavior with Clojure and Incanter</h1>
<p><img src="/images/2009-06/rabbit-run.jpg" style="float: left; margin-right: 1em; " /></p>
<p>I&#8217;m working with our system architect (<a href="http://www.linkedin.com/pub/mark-mehalik/13/113/461">Mark Mehalik</a>) evaluating <a href="http://amqp.org/"><span class="caps">AMQP</span></a> as a messaging implementation for a new project.  One of the things want to prove out is how the brokers behave under a widely varying number messages, message sizes, numbers of producers, consumers, queues and in differing clustering configurations.  Since <a href="http://amqp.org/"><span class="caps">AMQP</span></a> is a standard we should be able to build a single test suite and then execute it against the different brokers to measure their behavior as well as how robust they are under those conditions.</p>
<h2>Scripting and Automation</h2>
<p>I started the process of mocking up and automating the tests with the goal to help us figure out what we want to test.  I chose to do this with <a href="http://clojure.org/">Clojure</a> and to use <a href="http://github.com/liebke/incanter/tree/master">Incanter</a> for a quick and easy visualization.  You can the check the code out of my <a href="http://github.com/kyleburton/sandbox/tree/master">sandbox</a> project on <a href="http://github.com/">GitHub</a>.  The example code exercises a local <a href="http://amqp.org/"><span class="caps">AMQP</span></a> v0.8 broker using the <a href="http://www.rabbitmq.com/">RabbitMQ</a> Java Client Libraries (which support 0.8 at this time).</p>
<h3>Producer</h3>
<p>To test the broker, I created a simple producer and consumer and had them pass small (371 byte) messages.  They use the simple Rabbit Java client library primitives for <tt>Channel.basicPublish</tt> and <tt>Channel.basicGet</tt>.  The message consists of an array of two values: a message id (integer); and a time-stamp (<tt>java.util.Date</tt>).  They get serialized and placed into the <a href="http://amqp.org/"><span class="caps">AMQP</span></a> message body.  The producer just loops pushing all the messages to the broker and then logs its start and end times:</p>
<pre class="code">
(defn producer [producer-num cnt]
  (rabbit/with-amqp
   {}
   (let [start-time now]
     (dotimes [ii cnt]
       (object-publish [ii (Date.)]))
     (log-producer-stat producer-num cnt start-time (now)))))
</pre>
<h3>Consumer</h3>
<p>The consumer is a bit more more complex, doing more book keeping.  It tracks the number of messages it receives, its own elapsed time and totals up the amount of time each message was spent on the queue.  Just as with the producer, it logs its timings after it has consumed all of the messages on the queue.</p>
<pre class="code">
(defn consumer [consumer-num]
  (rabbit/with-amqp
   {}
   (let [start-time (now -1)
         num-msgs   (atom 0)
         msg-age    (atom 0)]
     (loop [[ii dt] (rabbit/object-get)]
       (if ii
         (let [end         (now -1)
               msg-elapsed (- end (.getTime dt))]
           (reset! num-msgs (+ 1 @num-msgs))
           (reset! msg-age  (+ msg-elapsed @msg-age))
           (recur (rabbit/object-get)))))
     (log-consumer-stat consumer-num @num-msgs start-time (now) @msg-age)
     (let [elapsed (/ (- (now) start-time) 1000.0)
           rate    (/ @num-msgs elapsed)]
       (prn (format "%s messages in %s elapsed seconds @ %s/second"
                    @num-msgs
                    elapsed
                    rate))))))
</pre>
<h3>Benchmark</h3>
<p>I chose to run a series of tests with message counts from 1 up to 500k, repeating each test three times.  This is only to get some data to play with, we plan on creating longer running and distributed tests over the next week to measure the behavior of the brokers in other configurations.  This test was enough to produce data for me to try out <a href="http://github.com/liebke/incanter/tree/master">Incanter</a> with though and given how easy this was to create, we&#8217;ll likely continue to modify this set of files.</p>
<pre class="code">
(defn run-benchmark [broker num-prods num-cons]
  (doseq [msg-count [1 5 10 50 100 500 1000 5000 10000 50000 100000 500000]]
    (run-single-benchmark (format "Series-%sm-%sp-%sc" msg-count num-prods num-cons)
                          broker
                          3 
                          msg-count
                          num-prods))
  (prn (format "run-benchmark: %s completed" broker)))

(defn run-single-benchmark [series broker num-runs num-msgs num-producers]
  (dotimes [run-number num-runs]
    (binding [*testing-info* (merge *testing-info*
                                    {:series  series
                                     :broker  broker
                                     :run-num (+ 1 run-number)})]
      (let [msgs-per-producer (/ num-msgs num-producers)]
        (dotimes [ii num-producers]
          (.start (Thread. (fn [] (producer (format "p%s" ii) msgs-per-producer))))))
      (Thread/sleep 100)
      (consumer "c1"))))
</pre>
<h3>Incanter Visualization</h3>
<p>Once we had run this against <a href="http://qpid.apache.org/">Apache&#8217;s Qpid</a> and <a href="http://rabbitmq.com/">RabbitMQ</a> there was enough data to produce some charts.   There is code to support loading the collected data from the files from disk, and the <a href="http://github.com/liebke/incanter/tree/master">Incanter</a> code is wonderfully easy to use.</p>
<p><tt>get-stat-data</tt> pulls the data from the consumer log for the named broker as a sequence of maps where the column headers are the keys and the row fields are the values.  <tt>get-xy-data</tt> pulls two of the fields and separates them into two sequences &#8211; just what the plotting functions in <a href="http://github.com/liebke/incanter/tree/master">Incanter</a> expect.  <tt>simple-xy-plot</tt> then passes the two sequences to <a href="http://github.com/liebke/incanter/tree/master&#39;s">Incanter</a> line-plot to visualize the data.</p>
<pre class="code">
(defn get-xy-data [broker xname yname]
  (let [stat-data (get-stat-data broker *consumer-stats-file*)
        count-and-rate (map (fn [ent] [(ent xname) (ent yname)]) stat-data)
        x-vals    (map #(Double/parseDouble (% 0))  count-and-rate)
        y-vals    (map #(Double/parseDouble (% 1))  count-and-rate)]
    [x-vals y-vals]))

(defn simple-xy-plot [broker xname yname]
  (let [rabbit-data (get-xy-data broker xname yname)]
    (line-plot (rabbit-data 0) (rabbit-data 1)
               :title (format "%s vs %s" xname yname)
               :x-label xname
               :y-label yname)))

(view (simple-xy-plot "RabbitMQ"    "TOTAL-MESSAGES" "M/S"))
(view (simple-xy-plot "Apache-Qpid" "TOTAL-MESSAGES" "M/S"))
</pre>
<div style="margin-top: 4em; margin-bottom: 4em;">
<p><img src="/images/2009-06/feisty-rabbit.jpg" style="float: right; margin-left: 2em;" height="219" width="256" /></p>
<p>I ran the broker, and a single <span class="caps">JVM</span> hosting both the producer and consumer on my workstation (along with all my other processes, X, <span class="caps">KDE</span>, Emacs and a ton of other processes).  I did no tuning of the brokers, running them in their default configurations.  I don&#8217;t expect these numbers to be too representative of the brokers performance in any kind of production configuration.</p>
<p>There are a few other interesting findings:  With no tuning Qpid failed at 100k messages with an out of memory exception (crashed hard).  This was with the default 1024Mb heap setting, at 2048Mb it was able to handle 100k messages and the graph shows Qpid using the 2048Mb heap setting.  Rabbit survived up to 500k message (as far as I pushed it), <em>but</em> the performance degraded significantly down to about 170 messages per second.</p>
</div>
<h4>Qpid <span class="caps">RSS</span></h4>
<p><img src="/images/2009-06/qpid-mem-rss.png" /></p>
<p>This shows the 2048M heap configuration growing up to the 100k message mark.</p>
<h4>Qpid <span class="caps">VSS</span></h4>
<p><img src="/images/2009-06/qpid-mem-vss.png" /></p>
<p>The flatness of this isn&#8217;t surprising as the <span class="caps">JVM</span> allocated its entire heap all at once.</p>
<h4>Rabbit <span class="caps">RSS</span></h4>
<p><img src="/images/2009-06/rabbit-mem-rss.png" /></p>
<p><a href="http://erlang.org/">Erlang&#8217;s</a> a bit more interesting, you can see it trying to cope with the various message loads, spiking up to about 3/4 of a gig with 500k messages.  In this configuration Rabbit&#8217;s rate dropped significantly from its average, to about 170/s.  It did stay up though.  The next step here is to see what we can learn about how Rabbit is handling this deluge of messages.</p>
<h4>Rabbit <span class="caps">VSS</span></h4>
<p><img src="/images/2009-06/rabbit-mem-vss.png" /></p>
<p>This pretty closely follows the shape of the <span class="caps">RSS</span> graph.</p>
<h4><font color="red">Rabbit</font> vs <font color="blue">Qpid</font> Messages per Second</h4>
<p><img src="/images/2009-06/rabbit-vs-qpid-mps.png" /></p>
<h2>Clojure and Incanter</h2>
<p>It was very straight forward to set up these benchmarks and the graphing code with Clojure and Incanter.  We were able to try different approaches and visualizations very rapidly.  Clojure&#8217;s ease of development and Incanter&#8217;s high level graphing functions turned the profiling from a chore into a fun task.</p>
<p class="meta">Kyle Burton, 2nd June 2009 &#8211; King of Prussia PA</p>
<h5>Photo Credits</h5>
<ul>
	<li><a href="http://www.flickr.com/photos/sapphir3blu3/3235526282/sizes/l/">Rabbit Run</a></li>
	<li><a href="http://www.flickr.com/photos/markhillary/2950218730/sizes/l/">Nail Filer</a></li>
	<li><a href="http://www.flickr.com/photos/boskizzi/4731745/sizes/o/">Dead Rabbit</a></li>
	<li><a href="http://www.flickr.com/photos/flik/3182151968/sizes/l/">feisty rabbit</a></li>
	<li><a href="http://www.flickr.com/photos/thetim/458733962/">dryer rabbit</a></li>
	<li><a href="http://www.flickr.com/photos/53366513@N00/67046506/">hidden rabbit</a></li>
</ul>]]></content:encoded>
    </item>
    
    <item>
      <title>Trixx Gets a Build</title>
      <link>http://asymmetrical-view.com/2009/05/21/trixx-gets-a-build.html</link>
      <comments>http://asymmetrical-view.com/2009/05/21/trixx-gets-a-build.html#comments</comments>

      <pubDate>2009-05-21T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2009/05/21/trixx-gets-a-build.html</guid>

      <id>http://asymmetrical-view.com/2009/05/21/trixx-gets-a-build</id>
      <description><![CDATA[<h1>Trixx Gets a Build</h1>
<p>I just implemented an <a href="http://ant.apache.org/">ant</a> build for <a href="http://github.com/kyleburton/trixx/tree/master">Trixx</a>.  Trixx now builds, pulls down its dependencies jar, and contains and builds the required version of <a href="http://rabbitmq.com/">RabbitMQ</a>.</p>
<p>To build using ant (you will need to have <a href="http://erlang.org/">Erlang</a> already installed):</p>
<pre class="code">
kyleburton@indigo64 ~/personal/projects/$ git clone git@github.com:kyleburton/trixx.git
kyleburton@indigo64 ~/personal/projects/$ cd trixx
kyleburton@indigo64 ~/personal/projects/trixx[master]$ ant fetch-deps compile-rabbit-server compile-rabbit-java-client jar
</pre>
<p>Then in separate terminals, run RabbitMQ:</p>
<pre class="code">
kyleburton@indigo64 ~/personal/projects/trixx[master]$ ant run-rabbit
Buildfile: build.xml

run-rabbit:
     [exec] RabbitMQ %%VERSION%% (AMQP 8-0)
     [exec] Copyright (C) 2007-2009 LShift Ltd., Cohesive Financial Technologies LLC., and Rabbit Technologies Ltd.
     [exec] Licensed under the MPL.  See http://www.rabbitmq.com/
     [exec]
     [exec] Logging to "/home/kyleburton/local/var/rabbit/log/rabbit.log"
     [exec] SASL logging to "/home/kyleburton/local/var/rabbit/log/rabbit-sasl.log"
     [exec]
     [exec] starting database             ...done
     [exec] starting core processes       ...done
     [exec] starting recovery             ...done
     [exec] starting persister            ...done
     [exec] starting guid generator       ...done
     [exec] starting builtin applications ...done
     [exec] starting TCP listeners        ...done
     [exec]
     [exec] broker running
</pre>
<p>In another terminal, run Trixx:</p>
<pre class="code">
kyleburton@indigo64 ~/personal/projects/trixx[master]$ ant run-trixx
Buildfile: build.xml

run-trixx:
     [echo] Ensure you've run rabbit before this task...
     [java] "com.leftrightfold.trixx: *cookie*=FONEINRZCWQWZOERIHXH"
     [java] "com.leftrightfold.trixx: *server*=localhost"
     [java] "com.leftrightfold.trixx: *rabbit-instance=rabbit"
     [java] 2009-05-22 00:15:58.317::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog
     [java] clojure.proxy.javax.servlet.http.HttpServlet
     [java] 2009-05-22 00:15:58.395::INFO:  jetty-6.1.15
     [java] 2009-05-22 00:16:00.462::INFO:  Started SocketConnector@0.0.0.0:8080
</pre>
<p><a href="http://github.com/aaronfeng/">Aaron&#8217;s</a> stated goal is to make Trixx a management console for RabbitMQ.  He just started implementing a RESTfull interface using <a href="http://github.com/weavejester/compojure/tree/master">Compojure</a> which you can hit with a browser after running <code>ant run-trixx</code>.</p>
<p>Now that things are easier to build and run I expect the development to go more smoothly.</p>
<p class="meta">Kyle Burton, 21 May 2009 &#8211; Wayne PA</p>]]></description>
      <content:encoded><![CDATA[<h1>Trixx Gets a Build</h1>
<p>I just implemented an <a href="http://ant.apache.org/">ant</a> build for <a href="http://github.com/kyleburton/trixx/tree/master">Trixx</a>.  Trixx now builds, pulls down its dependencies jar, and contains and builds the required version of <a href="http://rabbitmq.com/">RabbitMQ</a>.</p>
<p>To build using ant (you will need to have <a href="http://erlang.org/">Erlang</a> already installed):</p>
<pre class="code">
kyleburton@indigo64 ~/personal/projects/$ git clone git@github.com:kyleburton/trixx.git
kyleburton@indigo64 ~/personal/projects/$ cd trixx
kyleburton@indigo64 ~/personal/projects/trixx[master]$ ant fetch-deps compile-rabbit-server compile-rabbit-java-client jar
</pre>
<p>Then in separate terminals, run RabbitMQ:</p>
<pre class="code">
kyleburton@indigo64 ~/personal/projects/trixx[master]$ ant run-rabbit
Buildfile: build.xml

run-rabbit:
     [exec] RabbitMQ %%VERSION%% (AMQP 8-0)
     [exec] Copyright (C) 2007-2009 LShift Ltd., Cohesive Financial Technologies LLC., and Rabbit Technologies Ltd.
     [exec] Licensed under the MPL.  See http://www.rabbitmq.com/
     [exec]
     [exec] Logging to "/home/kyleburton/local/var/rabbit/log/rabbit.log"
     [exec] SASL logging to "/home/kyleburton/local/var/rabbit/log/rabbit-sasl.log"
     [exec]
     [exec] starting database             ...done
     [exec] starting core processes       ...done
     [exec] starting recovery             ...done
     [exec] starting persister            ...done
     [exec] starting guid generator       ...done
     [exec] starting builtin applications ...done
     [exec] starting TCP listeners        ...done
     [exec]
     [exec] broker running
</pre>
<p>In another terminal, run Trixx:</p>
<pre class="code">
kyleburton@indigo64 ~/personal/projects/trixx[master]$ ant run-trixx
Buildfile: build.xml

run-trixx:
     [echo] Ensure you've run rabbit before this task...
     [java] "com.leftrightfold.trixx: *cookie*=FONEINRZCWQWZOERIHXH"
     [java] "com.leftrightfold.trixx: *server*=localhost"
     [java] "com.leftrightfold.trixx: *rabbit-instance=rabbit"
     [java] 2009-05-22 00:15:58.317::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog
     [java] clojure.proxy.javax.servlet.http.HttpServlet
     [java] 2009-05-22 00:15:58.395::INFO:  jetty-6.1.15
     [java] 2009-05-22 00:16:00.462::INFO:  Started SocketConnector@0.0.0.0:8080
</pre>
<p><a href="http://github.com/aaronfeng/">Aaron&#8217;s</a> stated goal is to make Trixx a management console for RabbitMQ.  He just started implementing a RESTfull interface using <a href="http://github.com/weavejester/compojure/tree/master">Compojure</a> which you can hit with a browser after running <code>ant run-trixx</code>.</p>
<p>Now that things are easier to build and run I expect the development to go more smoothly.</p>
<p class="meta">Kyle Burton, 21 May 2009 &#8211; Wayne PA</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Experience knows a Name</title>
      <link>http://asymmetrical-view.com/2009/05/20/expeirence-knows-a-name.html</link>
      <comments>http://asymmetrical-view.com/2009/05/20/expeirence-knows-a-name.html#comments</comments>

      <pubDate>2009-05-20T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2009/05/20/expeirence-knows-a-name.html</guid>

      <id>http://asymmetrical-view.com/2009/05/20/expeirence-knows-a-name</id>
      <description><![CDATA[<h1>Experience knows a Name</h1>
<p>Reading <a href="http://blog.bitquabit.com/2009/05/20/your-language-features-are-my-libraries/">Your Language Features Are My Libraries</a>, a thought occurred to me.  Not about language features, but about people.</p>
<p>I see new developers latch onto the new languages and the features that they support (Java has garbage collection; Ruby lets you extend classes and makes DSLs easy; C# has list comprehensions; and so on).  I see new developers lead themselves down the road of re-implementing solutions when pre-existing libraries may have been available (sometimes core libraries).  I see senior developers lament that the junior devs aren&#8217;t paying attention to what already exists.</p>
<h3>Senior Developers have an Index</h3>
<p>Seasoned or experienced developers have a large mental index of existing example code, libraries, design patterns, frameworks and full application stacks.  Experienced developers can often qualify and evaluate suitable pre-existing approaches (existing language support, core libraries, available libraries, pre-existing applications) &#8211; much more frequently and with more success (where success is re-use rather than re-implementation) than junior developers.</p>
<p>I&#8217;m not so sure that the only reason for this is just that new developers don&#8217;t have the mental index of language features and libraries that more experienced developers do.</p>
<p>Both types of developers can use Google right (it&#8217;s a big &#8220;index&#8221; after all)?  Well&#8230;not in the same way.  Experienced developers have a higher chance of already understanding core aspects of the problem they are facing.  Experienced developers are more likely to know the commonly used names for many of the aspects of the problem they are facing.  So when they search, they&#8217;re searching for something very specific, something that is more likely to be found.</p>
<p>Junior developers will not be searching by name, rather by definition.  They search by using the phrases that describe what they&#8217;re after.  This isn&#8217;t as successful.  Look at the difference between searching for <a href="http://www.google.com/search?q=carbonated+sugar+water">carbonated sugar water</a> versus <a href="http://www.google.com/search?q=coca-cola">coca-cola</a>.</p>
<p>This has a huge impact on the likelihood that a suitable pre-existing solution will even be identified.  I have improved in this respect over the years &#8211; partly just by accumulating knowledge of the names of things (this is the idea that naming something or knowing its name gives you some amount of power over it).</p>
<p>Then we come to the issue of understanding the problem.  Developers will more often have to work to build a working model of the problem before any search or selection could take place.  Developers by their very nature will write code to help them develop understanding of a problem.  Writing a prototype is a very powerful tool for helping you understand a problem &#8211; if you can instruct a computer to perform a task, you must have a pretty good understanding of it.</p>
<p>Here&#8217;s the rub though, once you have a prototype, you have something with value.  It becomes less attractive to qualify and acquire an alternative when you already have a working, or close to working &#8220;bird in hand&#8221;.  Junior developers often over value their prototypes, partly due to the actual effort it took them to create it.  Senior developers create more minimal prototypes, only explore the core parts of the problem domain they don&#8217;t already understand &#8211; and often with different tools, not caring about input, output or fixed data models or well defined types.  The point is to learn just enough and senior developers are more prescient of what &#8216;just enough&#8217; is.</p>
<h3>Junior Developers Implement to Learn</h3>
<p>The transfer of the names of things of these patterns of problems, is a core value that developers get out of mentoring each other.</p>
<p>Junior developers implement to learn.  I encourage the junior developers I work with to write prototypes of existing algorithms and design patterns &#8211; it is vital practice and helps them develop a deeper understanding of problems.  I try to discuss with them what they did, why they did it and try to transfer terminology and discuss with them existing solutions that I may know of for contrast.</p>
<p>As they gain experience, they will know its name.</p>
<p class="meta">Kyle Burton, 20 May 2009 &#8211; King of Prussia PA</p>]]></description>
      <content:encoded><![CDATA[<h1>Experience knows a Name</h1>
<p>Reading <a href="http://blog.bitquabit.com/2009/05/20/your-language-features-are-my-libraries/">Your Language Features Are My Libraries</a>, a thought occurred to me.  Not about language features, but about people.</p>
<p>I see new developers latch onto the new languages and the features that they support (Java has garbage collection; Ruby lets you extend classes and makes DSLs easy; C# has list comprehensions; and so on).  I see new developers lead themselves down the road of re-implementing solutions when pre-existing libraries may have been available (sometimes core libraries).  I see senior developers lament that the junior devs aren&#8217;t paying attention to what already exists.</p>
<h3>Senior Developers have an Index</h3>
<p>Seasoned or experienced developers have a large mental index of existing example code, libraries, design patterns, frameworks and full application stacks.  Experienced developers can often qualify and evaluate suitable pre-existing approaches (existing language support, core libraries, available libraries, pre-existing applications) &#8211; much more frequently and with more success (where success is re-use rather than re-implementation) than junior developers.</p>
<p>I&#8217;m not so sure that the only reason for this is just that new developers don&#8217;t have the mental index of language features and libraries that more experienced developers do.</p>
<p>Both types of developers can use Google right (it&#8217;s a big &#8220;index&#8221; after all)?  Well&#8230;not in the same way.  Experienced developers have a higher chance of already understanding core aspects of the problem they are facing.  Experienced developers are more likely to know the commonly used names for many of the aspects of the problem they are facing.  So when they search, they&#8217;re searching for something very specific, something that is more likely to be found.</p>
<p>Junior developers will not be searching by name, rather by definition.  They search by using the phrases that describe what they&#8217;re after.  This isn&#8217;t as successful.  Look at the difference between searching for <a href="http://www.google.com/search?q=carbonated+sugar+water">carbonated sugar water</a> versus <a href="http://www.google.com/search?q=coca-cola">coca-cola</a>.</p>
<p>This has a huge impact on the likelihood that a suitable pre-existing solution will even be identified.  I have improved in this respect over the years &#8211; partly just by accumulating knowledge of the names of things (this is the idea that naming something or knowing its name gives you some amount of power over it).</p>
<p>Then we come to the issue of understanding the problem.  Developers will more often have to work to build a working model of the problem before any search or selection could take place.  Developers by their very nature will write code to help them develop understanding of a problem.  Writing a prototype is a very powerful tool for helping you understand a problem &#8211; if you can instruct a computer to perform a task, you must have a pretty good understanding of it.</p>
<p>Here&#8217;s the rub though, once you have a prototype, you have something with value.  It becomes less attractive to qualify and acquire an alternative when you already have a working, or close to working &#8220;bird in hand&#8221;.  Junior developers often over value their prototypes, partly due to the actual effort it took them to create it.  Senior developers create more minimal prototypes, only explore the core parts of the problem domain they don&#8217;t already understand &#8211; and often with different tools, not caring about input, output or fixed data models or well defined types.  The point is to learn just enough and senior developers are more prescient of what &#8216;just enough&#8217; is.</p>
<h3>Junior Developers Implement to Learn</h3>
<p>The transfer of the names of things of these patterns of problems, is a core value that developers get out of mentoring each other.</p>
<p>Junior developers implement to learn.  I encourage the junior developers I work with to write prototypes of existing algorithms and design patterns &#8211; it is vital practice and helps them develop a deeper understanding of problems.  I try to discuss with them what they did, why they did it and try to transfer terminology and discuss with them existing solutions that I may know of for contrast.</p>
<p>As they gain experience, they will know its name.</p>
<p class="meta">Kyle Burton, 20 May 2009 &#8211; King of Prussia PA</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Exploring Quartz from Clojure</title>
      <link>http://asymmetrical-view.com/2009/05/19/quartz-and-clojure.html</link>
      <comments>http://asymmetrical-view.com/2009/05/19/quartz-and-clojure.html#comments</comments>

      <pubDate>2009-05-19T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2009/05/19/quartz-and-clojure.html</guid>

      <id>http://asymmetrical-view.com/2009/05/19/quartz-and-clojure</id>
      <description><![CDATA[<h1>Exploring Quartz from Clojure</h1>
<p>From the <a href="http://www.opensymphony.com/quartz/">Quartz</a> website:</p>
<blockquote>
Quartz is a job scheduling system that can be integrated with, or used along side virtually any other software system. The term &#8220;job scheduler&#8221; seems to conjure different ideas for different people&#8230;in short, a job scheduler is a system that is responsible for executing (or notifying) other software components when a pre-determined (scheduled) time arrives.
</blockquote>
<p>I wanted to be able to explore how Quartz worked from <a href="http://clojure.org/">Clojure</a>.  Quartz executes <a href="http://www.opensymphony.com/quartz/api/org/quartz/Job.html">Jobs</a>.  You do not schedule job instances in Quartz though, instead you pass the <a href="http://www.opensymphony.com/quartz/api/org/quartz/Scheduler.html">scheduler</a> a factory, specifically a <a href="http://www.opensymphony.com/quartz/api/org/quartz/JobDetail.html">JobDetail</a>.  The JobDetail will specify the Class of the class implementing the job, which must support a no-arg constructor.  This meant I couldn&#8217;t use Clojure&#8217;s <a href="http://clojure.org/java_interop">proxy</a> to implement the Job instance &#8211; since it needed to be constructible via a call like Class.newInstance.  Looking briefly at the Quartz source it appears to be the technique used in at least the SimpleJobFactory.</p>
<h3>ClojureJob.java</h3>
<p>To enable the calling of Clojure from a Quartz Job I implemented a very basic <a href="http://github.com/kyleburton/sandbox/blob/master/clojure-utils/src/java/com/github/kyleburton/sandbox/quartz/ClojureJob.java">ClojureJob</a> class:</p>
<pre class="code">
package com.github.kyleburton.sandbox.quartz;

import clojure.lang.Namespace;
import clojure.lang.RT;
import clojure.lang.Symbol;
import clojure.lang.Var;
import clojure.lang.IFn;

import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

/**
 * Quartz Job class for executing a clojure function.  The clojure
 * function will take a single argument, the JobExecutionContext which
 * is passed to this Job's execute method.
 *
 * NB: There is no way to capture or propagate an error from the
 * called function back to the context where the job was scheduled.
 *
 * http://www.opensymphony.com/quartz/
 *
 * @author Kyle R. Burton &lt;kyle.burton@gmail.com&gt;
 */
public class ClojureJob implements Job {
  /** JobExecutionContext/JobDetail/JobDataMap Parameter for the namespace of the function that will be called. */
  public  static final String NAMESPACE_PARAMETER     = "job.clojure.namespace";
  /** JobExecutionContext/JobDetail/JobDataMap Parameter for the name of the function that will be called. */
  public  static final String FUNCTION_NAME_PARAMETER = "job.clojure.function";
  /** */
  public  static final String FUNCTION_PARAMETER = "job.clojure.fn";
  private static final Class CLASS = ClojureJob.class;

  /**
   * Quartz required no-arg constructor.  Does nothing.
   */
  public ClojureJob() {
  }

  /**
   * Execute implementation, look up the clojure function specified in
   * the JobDataMap, invoke it with the JobExecutionContext.
   * @param context the JobExecutionContext passed in by quartz
   * @throws JobExecutionContext if the function can not be looked up,
   * or if the function throws an exception.
   */
  @Override
  public void execute(JobExecutionContext context) throws JobExecutionException {
    if ( null != contextParameter(context,FUNCTION_PARAMETER) ) {
      executeFunction(context,(IFn)contextParameter(context,FUNCTION_PARAMETER));
      return;
    }

    executeVar(context);
  }

  private void executeVar( JobExecutionContext context) throws JobExecutionException {
    Var fn = lookupClojureFunction(context);
    if ( null == fn ) {
      throw new JobExecutionException(
        String.format(CLASS.getName() + ".execute: unable to find the specified function, namespace=%s; function=%s", 
                      contextParameterString(context,NAMESPACE_PARAMETER),
                      contextParameterString(context,FUNCTION_NAME_PARAMETER)));
    }

    try {
      fn.invoke(context);
    }
    catch(Exception ex) {
      throw new JobExecutionException(ex);
    }
  }

  private void executeFunction( JobExecutionContext context, IFn fn) throws JobExecutionException {
    try {
      fn.invoke(context);
    }
    catch(Exception ex) {
      throw new JobExecutionException(ex);
    }
  }

  /**
   * Helper function for pulling parameters from the JobDataMap
   *
   * @param JobExecutionException the context to pull the parameter from
   * @param name the parameter to pull from the JobDataMap
   * @return the string value from the JobDataMap
   */
  private String contextParameterString(JobExecutionContext context, String name) {
    return context.getJobDetail().getJobDataMap().getString(name);
  }

  private Object contextParameter(JobExecutionContext context, String name) {
    return context.getJobDetail().getJobDataMap().get(name);
  }

  /**
   * Helper function for looking up the clojure function specified in
   * the quartz job.
   *
   * @param JobExecutionException the context passed in from quartz
   * @return the clojure Var which is the function
   */
  private Var lookupClojureFunction(JobExecutionContext context) { 
    String namespaceName = contextParameterString(context,NAMESPACE_PARAMETER);
    String functionName  = contextParameterString(context,FUNCTION_NAME_PARAMETER);
    Symbol symNamespace  = Symbol.create(namespaceName);
    Namespace namespace  = Namespace.findOrCreate(symNamespace);
    return Var.intern(namespace,Symbol.create(functionName));
  }
}
</pre>
<p>This class calls a clojure function that is either looked up or one that is passed in via the JobDetails of the JobExecutionContext.  In the case when an actual function (Clojure IFn) is passed, it is called without checking to see if a named function is passed.  The JobExecutionContext is passed to the <tt>invoke</tt> call So that parameters can be passed through to the Clojure function in either case.</p>
<h3>quartz.clj</h3>
<p>This allowed me to then create and schedule jobs which are backed by clojure functions.  Here is <a href="http://github.com/kyleburton/sandbox/blob/master/clojure-utils/src/clj/com/github/kyleburton/sandbox/quartz.clj">quartz.clj</a></p>
<pre class="code">
(ns com.github.kyleburton.sandbox.quartz
  (:import (org.quartz SchedulerFactory Scheduler TriggerUtils JobDetail)
           (org.quartz.impl StdSchedulerFactory)
           (com.github.kyleburton.sandbox.quartz ClojureJob)))

(def *schedule-factory* (StdSchedulerFactory.))

(def *scheduler* (atom nil))

(defn ensure-scheduler-started []
  (if (or (not @*scheduler*)
          (.isShutdown @*scheduler*)
          (not (.isStarted @*scheduler*)))
    (do
      (reset! *scheduler* (.getScheduler *schedule-factory*))
      (.start @*scheduler*)
      true)
    nil))

(defn stop-scheduler []
  (if (and @*scheduler*
           (.isStarted @*scheduler*))
    (.shutdown @*scheduler*)))

(defn schedule-job [job-detail trigger]
  (ensure-scheduler-started)
  (.scheduleJob @*scheduler* job-detail trigger))

(defn delete-job [job-detail]
  (.deleteJob @*scheduler*
              (.getName job-detail)
              (.getGroup job-detail)))

(defn job-exists? [job-detail]
  (not (nil? (.getJobDetail @*scheduler*
                            (.getName job-detail)
                            (.getGroup job-detail)))))

(defn testfn [context]
  (prn (format "testfn: context=%s time=%s" 
               context
               (java.util.Date.))))

(defn quartz-test []
  (let [job-detail (JobDetail. "myJob" nil ClojureJob)
        trigger (doto (TriggerUtils/makeSecondlyTrigger 10)
                  (.setStartTime (TriggerUtils/getEvenSecondDate (java.util.Date.)))
                  (.setName "My Second Trigger"))]
    (.put (.getJobDataMap job-detail) ClojureJob/NAMESPACE_PARAMETER "com.github.kyleburton.sandbox.quartz")
    (.put (.getJobDataMap job-detail) ClojureJob/FUNCTION_NAME_PARAMETER "testfn")
    (schedule-job job-detail trigger)))

(defn quartz-test-fn [fn]
  (let [job-detail (JobDetail. "myJob" nil ClojureJob)
        trigger (doto (TriggerUtils/makeSecondlyTrigger 10)
                  (.setStartTime (TriggerUtils/getEvenSecondDate (java.util.Date.)))
                  (.setName "My Second Trigger"))]
    (.put (.getJobDataMap job-detail) ClojureJob/FUNCTION_PARAMETER fn)
    (schedule-job job-detail trigger)))


;; (quartz-test)
;; (stop-scheduler)
;; (def *count* (atom 0))
;; (quartz-test-fn (fn [context] 
;;                   (reset! *count* (inc @*count*))
;;                   (prn (format "anon scheduled function! context=%s called %d times!" context @*count*))))
;; (stop-scheduler)
</pre>
<p>To play with these pull down my <a href="http://github.com/kyleburton/sandbox/tree/master">sandbox</a> run <a href="http://ant.apache.org/">ant</a> in the clojure-utils sub directory with the <tt>fetch-deps</tt> and <tt>jar</tt> targets.</p>
<pre class="code">
kyle@indigo64 ~/personal/projects/sandbox/clojure-utils[master]$ ant fetch-deps jar
Buildfile: build.xml

fetch-deps:
      [get] Getting: http://asymmetrical-view.com/personal/repo//ant-1.7.0.jar
      [get] To: /home/mortis/personal/projects/sandbox/clojure-utils/lib/ant-1.7.0.jar
      ...and lots more...

compile:
    [mkdir] Created dir: /home/mortis/personal/projects/sandbox/clojure-utils/target/classes
    [javac] Compiling 1 source file to /home/mortis/personal/projects/sandbox/clojure-utils/target/classes

jar:  
      [jar] Building jar: /home/mortis/personal/projects/sandbox/clojure-utils/target/krb-clojure-utils-0.1.jar

BUILD SUCCESSFUL
Total time: 23 seconds
kyle@indigo64 ~/personal/projects/sandbox/clojure-utils[master]$ ant repl

</pre>
<p>You can use <tt>ant repl</tt> to run a Clojure <span class="caps">REPL</span> with the necessary dependencies on the classpath.   Paste or type in the example functions to see them in action:</p>
<pre class="code">
(quartz-test)
;; wait a bit to see it run (it should run every 10s)
;; stop the scheduler to remove all tasks
(stop-scheduler)

;; define an atom to hold the count
(def *count* (atom 0))
;; schedule an anonymous function
(quartz-test-fn (fn [context] 
                  (reset! *count* (inc @*count*))
                  (prn (format "anon scheduled function! context=%s called %d times!" context @*count*))))
;; wait a bit to see it run (every 10s)
;; stop and exit the JVM
(stop-scheduler)
(System/exit 0)
</pre>
<p>The next thing I&#8217;d like to do is implement a prototype scheduler service exposing Quartz over <a href="http://amqp.org/"><span class="caps">AMQP</span></a> (<a href="http://www.rabbitmq.com/">RabbitMQ</a>).</p>
<p class="meta">Kyle Burton, 19 May 2009 &#8211; Wayne PA</p>]]></description>
      <content:encoded><![CDATA[<h1>Exploring Quartz from Clojure</h1>
<p>From the <a href="http://www.opensymphony.com/quartz/">Quartz</a> website:</p>
<blockquote>
Quartz is a job scheduling system that can be integrated with, or used along side virtually any other software system. The term &#8220;job scheduler&#8221; seems to conjure different ideas for different people&#8230;in short, a job scheduler is a system that is responsible for executing (or notifying) other software components when a pre-determined (scheduled) time arrives.
</blockquote>
<p>I wanted to be able to explore how Quartz worked from <a href="http://clojure.org/">Clojure</a>.  Quartz executes <a href="http://www.opensymphony.com/quartz/api/org/quartz/Job.html">Jobs</a>.  You do not schedule job instances in Quartz though, instead you pass the <a href="http://www.opensymphony.com/quartz/api/org/quartz/Scheduler.html">scheduler</a> a factory, specifically a <a href="http://www.opensymphony.com/quartz/api/org/quartz/JobDetail.html">JobDetail</a>.  The JobDetail will specify the Class of the class implementing the job, which must support a no-arg constructor.  This meant I couldn&#8217;t use Clojure&#8217;s <a href="http://clojure.org/java_interop">proxy</a> to implement the Job instance &#8211; since it needed to be constructible via a call like Class.newInstance.  Looking briefly at the Quartz source it appears to be the technique used in at least the SimpleJobFactory.</p>
<h3>ClojureJob.java</h3>
<p>To enable the calling of Clojure from a Quartz Job I implemented a very basic <a href="http://github.com/kyleburton/sandbox/blob/master/clojure-utils/src/java/com/github/kyleburton/sandbox/quartz/ClojureJob.java">ClojureJob</a> class:</p>
<pre class="code">
package com.github.kyleburton.sandbox.quartz;

import clojure.lang.Namespace;
import clojure.lang.RT;
import clojure.lang.Symbol;
import clojure.lang.Var;
import clojure.lang.IFn;

import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

/**
 * Quartz Job class for executing a clojure function.  The clojure
 * function will take a single argument, the JobExecutionContext which
 * is passed to this Job's execute method.
 *
 * NB: There is no way to capture or propagate an error from the
 * called function back to the context where the job was scheduled.
 *
 * http://www.opensymphony.com/quartz/
 *
 * @author Kyle R. Burton &lt;kyle.burton@gmail.com&gt;
 */
public class ClojureJob implements Job {
  /** JobExecutionContext/JobDetail/JobDataMap Parameter for the namespace of the function that will be called. */
  public  static final String NAMESPACE_PARAMETER     = "job.clojure.namespace";
  /** JobExecutionContext/JobDetail/JobDataMap Parameter for the name of the function that will be called. */
  public  static final String FUNCTION_NAME_PARAMETER = "job.clojure.function";
  /** */
  public  static final String FUNCTION_PARAMETER = "job.clojure.fn";
  private static final Class CLASS = ClojureJob.class;

  /**
   * Quartz required no-arg constructor.  Does nothing.
   */
  public ClojureJob() {
  }

  /**
   * Execute implementation, look up the clojure function specified in
   * the JobDataMap, invoke it with the JobExecutionContext.
   * @param context the JobExecutionContext passed in by quartz
   * @throws JobExecutionContext if the function can not be looked up,
   * or if the function throws an exception.
   */
  @Override
  public void execute(JobExecutionContext context) throws JobExecutionException {
    if ( null != contextParameter(context,FUNCTION_PARAMETER) ) {
      executeFunction(context,(IFn)contextParameter(context,FUNCTION_PARAMETER));
      return;
    }

    executeVar(context);
  }

  private void executeVar( JobExecutionContext context) throws JobExecutionException {
    Var fn = lookupClojureFunction(context);
    if ( null == fn ) {
      throw new JobExecutionException(
        String.format(CLASS.getName() + ".execute: unable to find the specified function, namespace=%s; function=%s", 
                      contextParameterString(context,NAMESPACE_PARAMETER),
                      contextParameterString(context,FUNCTION_NAME_PARAMETER)));
    }

    try {
      fn.invoke(context);
    }
    catch(Exception ex) {
      throw new JobExecutionException(ex);
    }
  }

  private void executeFunction( JobExecutionContext context, IFn fn) throws JobExecutionException {
    try {
      fn.invoke(context);
    }
    catch(Exception ex) {
      throw new JobExecutionException(ex);
    }
  }

  /**
   * Helper function for pulling parameters from the JobDataMap
   *
   * @param JobExecutionException the context to pull the parameter from
   * @param name the parameter to pull from the JobDataMap
   * @return the string value from the JobDataMap
   */
  private String contextParameterString(JobExecutionContext context, String name) {
    return context.getJobDetail().getJobDataMap().getString(name);
  }

  private Object contextParameter(JobExecutionContext context, String name) {
    return context.getJobDetail().getJobDataMap().get(name);
  }

  /**
   * Helper function for looking up the clojure function specified in
   * the quartz job.
   *
   * @param JobExecutionException the context passed in from quartz
   * @return the clojure Var which is the function
   */
  private Var lookupClojureFunction(JobExecutionContext context) { 
    String namespaceName = contextParameterString(context,NAMESPACE_PARAMETER);
    String functionName  = contextParameterString(context,FUNCTION_NAME_PARAMETER);
    Symbol symNamespace  = Symbol.create(namespaceName);
    Namespace namespace  = Namespace.findOrCreate(symNamespace);
    return Var.intern(namespace,Symbol.create(functionName));
  }
}
</pre>
<p>This class calls a clojure function that is either looked up or one that is passed in via the JobDetails of the JobExecutionContext.  In the case when an actual function (Clojure IFn) is passed, it is called without checking to see if a named function is passed.  The JobExecutionContext is passed to the <tt>invoke</tt> call So that parameters can be passed through to the Clojure function in either case.</p>
<h3>quartz.clj</h3>
<p>This allowed me to then create and schedule jobs which are backed by clojure functions.  Here is <a href="http://github.com/kyleburton/sandbox/blob/master/clojure-utils/src/clj/com/github/kyleburton/sandbox/quartz.clj">quartz.clj</a></p>
<pre class="code">
(ns com.github.kyleburton.sandbox.quartz
  (:import (org.quartz SchedulerFactory Scheduler TriggerUtils JobDetail)
           (org.quartz.impl StdSchedulerFactory)
           (com.github.kyleburton.sandbox.quartz ClojureJob)))

(def *schedule-factory* (StdSchedulerFactory.))

(def *scheduler* (atom nil))

(defn ensure-scheduler-started []
  (if (or (not @*scheduler*)
          (.isShutdown @*scheduler*)
          (not (.isStarted @*scheduler*)))
    (do
      (reset! *scheduler* (.getScheduler *schedule-factory*))
      (.start @*scheduler*)
      true)
    nil))

(defn stop-scheduler []
  (if (and @*scheduler*
           (.isStarted @*scheduler*))
    (.shutdown @*scheduler*)))

(defn schedule-job [job-detail trigger]
  (ensure-scheduler-started)
  (.scheduleJob @*scheduler* job-detail trigger))

(defn delete-job [job-detail]
  (.deleteJob @*scheduler*
              (.getName job-detail)
              (.getGroup job-detail)))

(defn job-exists? [job-detail]
  (not (nil? (.getJobDetail @*scheduler*
                            (.getName job-detail)
                            (.getGroup job-detail)))))

(defn testfn [context]
  (prn (format "testfn: context=%s time=%s" 
               context
               (java.util.Date.))))

(defn quartz-test []
  (let [job-detail (JobDetail. "myJob" nil ClojureJob)
        trigger (doto (TriggerUtils/makeSecondlyTrigger 10)
                  (.setStartTime (TriggerUtils/getEvenSecondDate (java.util.Date.)))
                  (.setName "My Second Trigger"))]
    (.put (.getJobDataMap job-detail) ClojureJob/NAMESPACE_PARAMETER "com.github.kyleburton.sandbox.quartz")
    (.put (.getJobDataMap job-detail) ClojureJob/FUNCTION_NAME_PARAMETER "testfn")
    (schedule-job job-detail trigger)))

(defn quartz-test-fn [fn]
  (let [job-detail (JobDetail. "myJob" nil ClojureJob)
        trigger (doto (TriggerUtils/makeSecondlyTrigger 10)
                  (.setStartTime (TriggerUtils/getEvenSecondDate (java.util.Date.)))
                  (.setName "My Second Trigger"))]
    (.put (.getJobDataMap job-detail) ClojureJob/FUNCTION_PARAMETER fn)
    (schedule-job job-detail trigger)))


;; (quartz-test)
;; (stop-scheduler)
;; (def *count* (atom 0))
;; (quartz-test-fn (fn [context] 
;;                   (reset! *count* (inc @*count*))
;;                   (prn (format "anon scheduled function! context=%s called %d times!" context @*count*))))
;; (stop-scheduler)
</pre>
<p>To play with these pull down my <a href="http://github.com/kyleburton/sandbox/tree/master">sandbox</a> run <a href="http://ant.apache.org/">ant</a> in the clojure-utils sub directory with the <tt>fetch-deps</tt> and <tt>jar</tt> targets.</p>
<pre class="code">
kyle@indigo64 ~/personal/projects/sandbox/clojure-utils[master]$ ant fetch-deps jar
Buildfile: build.xml

fetch-deps:
      [get] Getting: http://asymmetrical-view.com/personal/repo//ant-1.7.0.jar
      [get] To: /home/mortis/personal/projects/sandbox/clojure-utils/lib/ant-1.7.0.jar
      ...and lots more...

compile:
    [mkdir] Created dir: /home/mortis/personal/projects/sandbox/clojure-utils/target/classes
    [javac] Compiling 1 source file to /home/mortis/personal/projects/sandbox/clojure-utils/target/classes

jar:  
      [jar] Building jar: /home/mortis/personal/projects/sandbox/clojure-utils/target/krb-clojure-utils-0.1.jar

BUILD SUCCESSFUL
Total time: 23 seconds
kyle@indigo64 ~/personal/projects/sandbox/clojure-utils[master]$ ant repl

</pre>
<p>You can use <tt>ant repl</tt> to run a Clojure <span class="caps">REPL</span> with the necessary dependencies on the classpath.   Paste or type in the example functions to see them in action:</p>
<pre class="code">
(quartz-test)
;; wait a bit to see it run (it should run every 10s)
;; stop the scheduler to remove all tasks
(stop-scheduler)

;; define an atom to hold the count
(def *count* (atom 0))
;; schedule an anonymous function
(quartz-test-fn (fn [context] 
                  (reset! *count* (inc @*count*))
                  (prn (format "anon scheduled function! context=%s called %d times!" context @*count*))))
;; wait a bit to see it run (every 10s)
;; stop and exit the JVM
(stop-scheduler)
(System/exit 0)
</pre>
<p>The next thing I&#8217;d like to do is implement a prototype scheduler service exposing Quartz over <a href="http://amqp.org/"><span class="caps">AMQP</span></a> (<a href="http://www.rabbitmq.com/">RabbitMQ</a>).</p>
<p class="meta">Kyle Burton, 19 May 2009 &#8211; Wayne PA</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Introduction to Git talk at PLUG West Tonight at 7pm</title>
      <link>http://asymmetrical-view.com/2009/05/18/intro-to-git.html</link>
      <comments>http://asymmetrical-view.com/2009/05/18/intro-to-git.html#comments</comments>

      <pubDate>2009-05-18T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2009/05/18/intro-to-git.html</guid>

      <id>http://asymmetrical-view.com/2009/05/18/intro-to-git</id>
      <description><![CDATA[<h1>Introduction to Git talk at <span class="caps">PLUG</span> West Tonight at 7pm</h1>
<p>I&#8217;m giving my <a href="http://github.com/kyleburton/introduction-to-git/tree/master">Introduction to Git</a> talk tonight at the <a href="http://www.phillylinux.org/west.html">West</a> chapter of the <a href="http://www.phillylinux.org/">Philadelphia Linux Users Group</a>.  I&#8217;m bringing some minor give-aways, usb drives and post-it note pads, in case that is enticing :).</p>
<div style="width:425px;text-align:left" id="__ss_1452995"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/kyleburton/intro-to-git?type=presentation" title="Intro To Git">Intro To Git</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introtogit-090518104200-phpapp02&stripped_title=intro-to-git" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introtogit-090518104200-phpapp02&stripped_title=intro-to-git" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/kyleburton">kyleburton</a>.</div></div>
<p class="meta">Kyle Burton, 17 May 2009 &#8211; Wayne PA</p>]]></description>
      <content:encoded><![CDATA[<h1>Introduction to Git talk at <span class="caps">PLUG</span> West Tonight at 7pm</h1>
<p>I&#8217;m giving my <a href="http://github.com/kyleburton/introduction-to-git/tree/master">Introduction to Git</a> talk tonight at the <a href="http://www.phillylinux.org/west.html">West</a> chapter of the <a href="http://www.phillylinux.org/">Philadelphia Linux Users Group</a>.  I&#8217;m bringing some minor give-aways, usb drives and post-it note pads, in case that is enticing :).</p>
<div style="width:425px;text-align:left" id="__ss_1452995"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/kyleburton/intro-to-git?type=presentation" title="Intro To Git">Intro To Git</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introtogit-090518104200-phpapp02&stripped_title=intro-to-git" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introtogit-090518104200-phpapp02&stripped_title=intro-to-git" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/kyleburton">kyleburton</a>.</div></div>
<p class="meta">Kyle Burton, 17 May 2009 &#8211; Wayne PA</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Extending Jekyll</title>
      <link>http://asymmetrical-view.com/2009/05/17/extending-jekyll.html</link>
      <comments>http://asymmetrical-view.com/2009/05/17/extending-jekyll.html#comments</comments>

      <pubDate>2009-05-17T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2009/05/17/extending-jekyll.html</guid>

      <id>http://asymmetrical-view.com/2009/05/17/extending-jekyll</id>
      <description><![CDATA[<h1>Extending Jekyll</h1>
<p>After using <a href="http://www.jekyllrb.com/">Jekyll</a> to build my personal website, I was having some issues with my stylesheet not being reloaded by <a href="http://www.mozilla.com/firefox/">Firefox</a>.  Frameworks like <a href="http://rubyonrails.org/">Ruby on Rails</a> provide an <span class="caps">HTML</span> helper that add a short querystring which is simply the last modification time of the file being linked to.  This interacts nicely with the browse&#8217;s cache since it can cache the stylesheet and when you change it, the <span class="caps">URL</span> will be different (with the new mtime) and the browser will load the new stylesheet.</p>
<p>Rails provides <code>stylesheet_link_tag</code>, which you use as follows:</p>
<pre class="code">
  &lt;%= stylesheet_link_tag 'app', :media =&gt; "all" %&gt;
</pre>
<p><code>stylesheet_link_tag</code></code> then renders the following <span class="caps">HTML</span>:</p>
<pre class="code">
  &lt;link href="/stylesheets/app.css?1234672637" media="all" rel="stylesheet" type="text/css" /&gt;
</pre>
<p>Where <code>1234672637I</code> is the last modification time (or mtime) of the stylesheet file.  I wanted to have the same feature in Jekyll.  Jekyll uses of the <a href="http://www.liquidmarkup.org/">Liquid</a> text templating system, and Liquid supports being extended allowing you to add your own filters, tags and tag-blocks.  Tags are used for inserting content:</p>
<pre class="code">
   &lt;content type="html"&gt;{ { post.content } }&lt;/content&gt;
</pre>
<p>Filters are used to transform content, an example from the <a href="http://github.com/mojombo/mojombo.github.com/blob/master/atom.xml">atom.xml</a> formats the date:</p>
<pre class="code">
   &lt;updated&gt;{ { post.date | date_to_xmlschema } }&lt;/updated&gt;
</pre>
<p>What I wanted to be able to write was something like:</p>
<pre class="code">
   { % stylesheet "/css/style.css" % }
</pre>
<p>Which meant I had to make a new tag.  I created the tag file <code>lib/jekyll/tags/stylesheet_link.rb</code>:</p>
<pre class="code">
  module Jekyll

    class StylesheetTag &lt; Liquid::Tag
      def initialize(tag_name, file, tokens)
        super
        @file = file
      end

      def find_stylesheet(context)
        file = @file
        file.strip!
        file.gsub! /^["']/, ""
        file.gsub! /["']$/, ""
        if ! file =~ /.[a-z]+$/
          file = "#{file}.css"
        end

        files = [File.join(context.registers[:site].source, @file),
                 # strip a leading slash
                 File.join(context.registers[:site].source, @file[1..-1]),
                 ]
        files.each {|file|
          if File.exists? file
            return file
          end
        }
        return file
      end

      def render(context)
        file = find_stylesheet(context)

        mtime = nil
        if ! File.exists?(file)
          warn "Stylesheet file: '#{@file}' not found (#{file})"
          mtime = rand 1000000000
        else
          mtime = File.mtime(file).to_i
        end

        return %Q{&lt;link rel="stylesheet" href="#{@file}?#{mtime}" type="text/css" media="screen, projection" /&gt;}
      end
    end

  end

  Liquid::Template.register_tag('stylesheet', Jekyll::StylesheetTag)
</pre>
<p>All tags derive from Liquid::Tag and implement both <code>initialize</code> and <code>render</code>.  In the constructor the <code>StylesheetTag</code> saves off the argument (file).  In <code>render</code> it attempts to find the css file and then either uses a random value or the mtime of the file (if it was found), finally returning the string representing the stylesheet link.</p>
<p>Finally I added the module to the list of requires in <code>lib/jekyll.rb</code> so it is loaded when Jekyll runs:</p>
<pre class="code">
  ...
  # internal requires
  require 'jekyll/core_ext'
  require 'jekyll/pager'
  require 'jekyll/site'
  require 'jekyll/convertible'
  require 'jekyll/layout'
  require 'jekyll/page'
  require 'jekyll/post'
  require 'jekyll/filters'
  require 'jekyll/tags/highlight'
  require 'jekyll/tags/include'
  require 'jekyll/tags/stylesheet_link'
  require 'jekyll/albino'
  ...
</pre>
<p>Once that was completed the stylesheet tag generated links with the mtime as a query parameter and my stylesheets no longer had the caching issue.  I&#8217;m offering my changes back to <a href="http://github.com/mojombo" title="mojombo">Tom Preston-Werner</a>, but you can fork or clone <a href="http://github.com/kyleburton/jekyll/tree/master">my repository</a> if you want to try them yourself.</p>
<p class="meta">Kyle Burton, 17 May 2009 &#8211; Wayne PA</p>]]></description>
      <content:encoded><![CDATA[<h1>Extending Jekyll</h1>
<p>After using <a href="http://www.jekyllrb.com/">Jekyll</a> to build my personal website, I was having some issues with my stylesheet not being reloaded by <a href="http://www.mozilla.com/firefox/">Firefox</a>.  Frameworks like <a href="http://rubyonrails.org/">Ruby on Rails</a> provide an <span class="caps">HTML</span> helper that add a short querystring which is simply the last modification time of the file being linked to.  This interacts nicely with the browse&#8217;s cache since it can cache the stylesheet and when you change it, the <span class="caps">URL</span> will be different (with the new mtime) and the browser will load the new stylesheet.</p>
<p>Rails provides <code>stylesheet_link_tag</code>, which you use as follows:</p>
<pre class="code">
  &lt;%= stylesheet_link_tag 'app', :media =&gt; "all" %&gt;
</pre>
<p><code>stylesheet_link_tag</code></code> then renders the following <span class="caps">HTML</span>:</p>
<pre class="code">
  &lt;link href="/stylesheets/app.css?1234672637" media="all" rel="stylesheet" type="text/css" /&gt;
</pre>
<p>Where <code>1234672637I</code> is the last modification time (or mtime) of the stylesheet file.  I wanted to have the same feature in Jekyll.  Jekyll uses of the <a href="http://www.liquidmarkup.org/">Liquid</a> text templating system, and Liquid supports being extended allowing you to add your own filters, tags and tag-blocks.  Tags are used for inserting content:</p>
<pre class="code">
   &lt;content type="html"&gt;{ { post.content } }&lt;/content&gt;
</pre>
<p>Filters are used to transform content, an example from the <a href="http://github.com/mojombo/mojombo.github.com/blob/master/atom.xml">atom.xml</a> formats the date:</p>
<pre class="code">
   &lt;updated&gt;{ { post.date | date_to_xmlschema } }&lt;/updated&gt;
</pre>
<p>What I wanted to be able to write was something like:</p>
<pre class="code">
   { % stylesheet "/css/style.css" % }
</pre>
<p>Which meant I had to make a new tag.  I created the tag file <code>lib/jekyll/tags/stylesheet_link.rb</code>:</p>
<pre class="code">
  module Jekyll

    class StylesheetTag &lt; Liquid::Tag
      def initialize(tag_name, file, tokens)
        super
        @file = file
      end

      def find_stylesheet(context)
        file = @file
        file.strip!
        file.gsub! /^["']/, ""
        file.gsub! /["']$/, ""
        if ! file =~ /.[a-z]+$/
          file = "#{file}.css"
        end

        files = [File.join(context.registers[:site].source, @file),
                 # strip a leading slash
                 File.join(context.registers[:site].source, @file[1..-1]),
                 ]
        files.each {|file|
          if File.exists? file
            return file
          end
        }
        return file
      end

      def render(context)
        file = find_stylesheet(context)

        mtime = nil
        if ! File.exists?(file)
          warn "Stylesheet file: '#{@file}' not found (#{file})"
          mtime = rand 1000000000
        else
          mtime = File.mtime(file).to_i
        end

        return %Q{&lt;link rel="stylesheet" href="#{@file}?#{mtime}" type="text/css" media="screen, projection" /&gt;}
      end
    end

  end

  Liquid::Template.register_tag('stylesheet', Jekyll::StylesheetTag)
</pre>
<p>All tags derive from Liquid::Tag and implement both <code>initialize</code> and <code>render</code>.  In the constructor the <code>StylesheetTag</code> saves off the argument (file).  In <code>render</code> it attempts to find the css file and then either uses a random value or the mtime of the file (if it was found), finally returning the string representing the stylesheet link.</p>
<p>Finally I added the module to the list of requires in <code>lib/jekyll.rb</code> so it is loaded when Jekyll runs:</p>
<pre class="code">
  ...
  # internal requires
  require 'jekyll/core_ext'
  require 'jekyll/pager'
  require 'jekyll/site'
  require 'jekyll/convertible'
  require 'jekyll/layout'
  require 'jekyll/page'
  require 'jekyll/post'
  require 'jekyll/filters'
  require 'jekyll/tags/highlight'
  require 'jekyll/tags/include'
  require 'jekyll/tags/stylesheet_link'
  require 'jekyll/albino'
  ...
</pre>
<p>Once that was completed the stylesheet tag generated links with the mtime as a query parameter and my stylesheets no longer had the caching issue.  I&#8217;m offering my changes back to <a href="http://github.com/mojombo" title="mojombo">Tom Preston-Werner</a>, but you can fork or clone <a href="http://github.com/kyleburton/jekyll/tree/master">my repository</a> if you want to try them yourself.</p>
<p class="meta">Kyle Burton, 17 May 2009 &#8211; Wayne PA</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Getting Started With Jekyll</title>
      <link>http://asymmetrical-view.com/2009/05/14/starting-wtih-jekyll.html</link>
      <comments>http://asymmetrical-view.com/2009/05/14/starting-wtih-jekyll.html#comments</comments>

      <pubDate>2009-05-14T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2009/05/14/starting-wtih-jekyll.html</guid>

      <id>http://asymmetrical-view.com/2009/05/14/starting-wtih-jekyll</id>
      <description><![CDATA[<h1>Getting Started With Jekyll</h1>
<p>I took at look at <a href="http://cbcg.net/">Toby Di Pasquale&#8217;s website</a> tonight and it inspired me to get around to sprucing up my own site.</p>
<p>Toby used <a href="http://www.jekyllrb.com/">Jekyll</a>, a site generation and maintenance.  Jekyll allows you to maintain your site using <a href="http://wiki.github.com/tobi/liquid">liquid</a> (a text based templating tool), <a href="http://www.yaml.org/">Yaml</a> (for configuration) and <a href="http://maruku.rubyforge.org/">Markdown</a> (a simplified wiki-ish style markup language).  Jekyll is a bit different from dynamic Blogging or publishing platforms like <a href="http://wordpress.org/">WordPress</a> in that it intentionally generates your site as static content.  Most of the other publishing platforms dynamically generate their content at the time the page is requested by the browser.</p>
<p>Jekyll allows you to refactor your content, still allowing you to use templates and simplified markup, while allowing your site to be completely static.  This means you can deploy your site (or blog) to servers where you only have a web-server and no application software &#8211; it also means that your site will perform as well as your web-server can serve up static content, which is about as fast as you can get.</p>
<p>Setting the site up with Jekyll took only a few minutes&#8230;tweaking the css for the site and adding in some basic content took me a few hours.</p>
<h3>Installation</h3>
<p>You will need <a href="http://www.ruby-lang.org/en/">Ruby</a> installed along with <a href="http://docs.rubygems.org/">RubyGems</a>.  You will not need <a href="http://rubyonrails.org/">Ruby on Rails</a>.  Once Ruby and Gem are set up, follow the remaining instructions in the <a href="http://wiki.github.com/mojombo/jekyll/install">installation guide</a>.  A good place to start is by cloning one of the <a href="http://wiki.github.com/mojombo/jekyll/sites">example sites</a>:</p>
kyle@asymmetrical-view ~/projects$ git clone git://github.com/mojombo/mojombo.github.com.git
<p>This will give you a point of reference for creating your own site.  I made a directory and am using &quot;git&quot;h:ttp://git-scm.com/ to version my site.</p>
<h3>Create your _config.yml</h3>
<p>I initially had an incomplete `_config.yml` when I first tried to run Jekyll and it raised an exception.  Start with the downloaded example or use mine:</p>
<pre class="code">
    destination: ./_site
    auto:        false
    lsi:         false
    server_port: 4000
    pygments:    true
    markdown:    maruku
    permalink:   date
    maruku:
      use_tex:   false
      use_divs:  false
      png_dir:   images/latex
      png_url:   /images/latex
</pre>
<h3>Directory Structure</h3>
<p>I created a sub-directory for each of the major areas in the site (posts, projects, contact, talks and about), a directory for the &#8216;blog&#8217; posts (_posts) and for the layouts.</p>
<pre class="code">
./site/_posts/2000-05-14-starting-with-jekyll.textile
./site/projects/index.html
./site/index.html
./site/contact/index.html
./site/css/style.css
./site/_layouts/post.html
./site/_layouts/default.html
./site/_config.yml
./site/about/index.html
</pre>
<h3>Set up a Layout</h3>
<p>In the examples you&#8217;ll see a layout file in _layouts/default.html</p>
<p>The layouts are your page templates.  The template has the surrounding portion of the <span class="caps">HTML</span> page, with an inner yield block for the actual page content:</p>
<pre class="code">
  &lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
  &lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en-us"&gt;
  &lt;head&gt;
  ...
  &lt;div class="content"&gt;
    &lt;div style="margin-left: 22%;"&gt;
  { { content } }
  &lt;/div&gt;
  &lt;/div&gt;
  ...
  &lt;/body&gt;
  &lt;/html&gt;
</pre>
<p>Then make use of your layout, for example in my <code>./site/index.html</code>, I have a <a href="http://wiki.github.com/mojombo/jekyll/yaml-front-matter">Yaml front matter</a> that specifies the layout and the page title.</p>
<pre class="code">
  ---
  layout: default
  title: Seeking No Barriers To Abstraction
  ---
  &lt;div class="index-body"&gt;
    &lt;h1&gt;Welcome to Asymmetrical View&lt;/h1&gt;

    &lt;p&gt;
      This is the home site of Kyle Burton on the Internet.
    &lt;/p&gt;

    &lt;h1&gt;Recent Posts&lt;/h1&gt;
    &lt;ul class="posts"&gt;
      { %% for post in site.posts limit:5 %% }
        &lt;li&gt;&lt;span&gt;{ { post.date | date_to_string } }&lt;/span&gt; &amp;raquo; &lt;a href="{ { post.url } }"&gt;{ { post.title } }&lt;/a&gt;&lt;/li&gt;
      { %% endfor %% }
    &lt;/ul&gt;
  &lt;/div&gt;
</pre>
<h3>Creating Posts</h3>
<p>My posts are all in textile (<a href="http://maruku.rubyforge.org/">markdown</a>) format, using a similar technique as with the html files they have a <a href="http://wiki.github.com/mojombo/jekyll/yaml-front-matter">front matter</a> section and then some main content in the markup:</p>
<pre class="code">
  ---
  layout: post
  title: Getting Started With Jekyll
  ---

  h1. { { page.title } }

  I took at look at &lt;a href="http://cbcg.net/"&gt;Toby Di Pasquale's website&lt;/a&gt; tonight and it inspired me to get around to sprucing up my own site.
  
</pre>
<h3>Building and Testing Your Site</h3>
<p>To build out your site, just run jekyll.  You can also run it in a simple server mode in which it will attempt to recognize when you change files (via their last modification time) and rebuild the effected portions of your site.  One thing to keep in mind is that when you run jekyll with <code>--auto</code> it will not report on exceptions as robustly as it will when only invoked to perform teh build.  The workflow I use involves perdiocally restarting the jekyll server and removing the site build directory:</p>
<pre class="code">
  mortis@kburton-lin ~/personal/projects/this-blog/site[this-blog*]$ rm -rf _site/ &amp;&amp; jekyll  --auto --server 4001
</pre>
<p>When I stop seeing my changes reflected in the site I&#8217;ll <span class="caps">CTRL</span>-C Jekyl and re-run that command.</p>
<h3>Conclusion</h3>
<p>Installing and learning Jekyll was easy and it provides me with a much lighter weight process for maintaining my personal web site.</p>
<p class="meta">Kyle Burton, 14 May 2009 &#8211; Wayne PA</p>]]></description>
      <content:encoded><![CDATA[<h1>Getting Started With Jekyll</h1>
<p>I took at look at <a href="http://cbcg.net/">Toby Di Pasquale&#8217;s website</a> tonight and it inspired me to get around to sprucing up my own site.</p>
<p>Toby used <a href="http://www.jekyllrb.com/">Jekyll</a>, a site generation and maintenance.  Jekyll allows you to maintain your site using <a href="http://wiki.github.com/tobi/liquid">liquid</a> (a text based templating tool), <a href="http://www.yaml.org/">Yaml</a> (for configuration) and <a href="http://maruku.rubyforge.org/">Markdown</a> (a simplified wiki-ish style markup language).  Jekyll is a bit different from dynamic Blogging or publishing platforms like <a href="http://wordpress.org/">WordPress</a> in that it intentionally generates your site as static content.  Most of the other publishing platforms dynamically generate their content at the time the page is requested by the browser.</p>
<p>Jekyll allows you to refactor your content, still allowing you to use templates and simplified markup, while allowing your site to be completely static.  This means you can deploy your site (or blog) to servers where you only have a web-server and no application software &#8211; it also means that your site will perform as well as your web-server can serve up static content, which is about as fast as you can get.</p>
<p>Setting the site up with Jekyll took only a few minutes&#8230;tweaking the css for the site and adding in some basic content took me a few hours.</p>
<h3>Installation</h3>
<p>You will need <a href="http://www.ruby-lang.org/en/">Ruby</a> installed along with <a href="http://docs.rubygems.org/">RubyGems</a>.  You will not need <a href="http://rubyonrails.org/">Ruby on Rails</a>.  Once Ruby and Gem are set up, follow the remaining instructions in the <a href="http://wiki.github.com/mojombo/jekyll/install">installation guide</a>.  A good place to start is by cloning one of the <a href="http://wiki.github.com/mojombo/jekyll/sites">example sites</a>:</p>
kyle@asymmetrical-view ~/projects$ git clone git://github.com/mojombo/mojombo.github.com.git
<p>This will give you a point of reference for creating your own site.  I made a directory and am using &quot;git&quot;h:ttp://git-scm.com/ to version my site.</p>
<h3>Create your _config.yml</h3>
<p>I initially had an incomplete `_config.yml` when I first tried to run Jekyll and it raised an exception.  Start with the downloaded example or use mine:</p>
<pre class="code">
    destination: ./_site
    auto:        false
    lsi:         false
    server_port: 4000
    pygments:    true
    markdown:    maruku
    permalink:   date
    maruku:
      use_tex:   false
      use_divs:  false
      png_dir:   images/latex
      png_url:   /images/latex
</pre>
<h3>Directory Structure</h3>
<p>I created a sub-directory for each of the major areas in the site (posts, projects, contact, talks and about), a directory for the &#8216;blog&#8217; posts (_posts) and for the layouts.</p>
<pre class="code">
./site/_posts/2000-05-14-starting-with-jekyll.textile
./site/projects/index.html
./site/index.html
./site/contact/index.html
./site/css/style.css
./site/_layouts/post.html
./site/_layouts/default.html
./site/_config.yml
./site/about/index.html
</pre>
<h3>Set up a Layout</h3>
<p>In the examples you&#8217;ll see a layout file in _layouts/default.html</p>
<p>The layouts are your page templates.  The template has the surrounding portion of the <span class="caps">HTML</span> page, with an inner yield block for the actual page content:</p>
<pre class="code">
  &lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
  &lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en-us"&gt;
  &lt;head&gt;
  ...
  &lt;div class="content"&gt;
    &lt;div style="margin-left: 22%;"&gt;
  { { content } }
  &lt;/div&gt;
  &lt;/div&gt;
  ...
  &lt;/body&gt;
  &lt;/html&gt;
</pre>
<p>Then make use of your layout, for example in my <code>./site/index.html</code>, I have a <a href="http://wiki.github.com/mojombo/jekyll/yaml-front-matter">Yaml front matter</a> that specifies the layout and the page title.</p>
<pre class="code">
  ---
  layout: default
  title: Seeking No Barriers To Abstraction
  ---
  &lt;div class="index-body"&gt;
    &lt;h1&gt;Welcome to Asymmetrical View&lt;/h1&gt;

    &lt;p&gt;
      This is the home site of Kyle Burton on the Internet.
    &lt;/p&gt;

    &lt;h1&gt;Recent Posts&lt;/h1&gt;
    &lt;ul class="posts"&gt;
      { %% for post in site.posts limit:5 %% }
        &lt;li&gt;&lt;span&gt;{ { post.date | date_to_string } }&lt;/span&gt; &amp;raquo; &lt;a href="{ { post.url } }"&gt;{ { post.title } }&lt;/a&gt;&lt;/li&gt;
      { %% endfor %% }
    &lt;/ul&gt;
  &lt;/div&gt;
</pre>
<h3>Creating Posts</h3>
<p>My posts are all in textile (<a href="http://maruku.rubyforge.org/">markdown</a>) format, using a similar technique as with the html files they have a <a href="http://wiki.github.com/mojombo/jekyll/yaml-front-matter">front matter</a> section and then some main content in the markup:</p>
<pre class="code">
  ---
  layout: post
  title: Getting Started With Jekyll
  ---

  h1. { { page.title } }

  I took at look at &lt;a href="http://cbcg.net/"&gt;Toby Di Pasquale's website&lt;/a&gt; tonight and it inspired me to get around to sprucing up my own site.
  
</pre>
<h3>Building and Testing Your Site</h3>
<p>To build out your site, just run jekyll.  You can also run it in a simple server mode in which it will attempt to recognize when you change files (via their last modification time) and rebuild the effected portions of your site.  One thing to keep in mind is that when you run jekyll with <code>--auto</code> it will not report on exceptions as robustly as it will when only invoked to perform teh build.  The workflow I use involves perdiocally restarting the jekyll server and removing the site build directory:</p>
<pre class="code">
  mortis@kburton-lin ~/personal/projects/this-blog/site[this-blog*]$ rm -rf _site/ &amp;&amp; jekyll  --auto --server 4001
</pre>
<p>When I stop seeing my changes reflected in the site I&#8217;ll <span class="caps">CTRL</span>-C Jekyl and re-run that command.</p>
<h3>Conclusion</h3>
<p>Installing and learning Jekyll was easy and it provides me with a much lighter weight process for maintaining my personal web site.</p>
<p class="meta">Kyle Burton, 14 May 2009 &#8211; Wayne PA</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Introduction to Git talk at PLUG North Tonight at 7pm</title>
      <link>http://asymmetrical-view.com/2009/05/11/intro-to-git.html</link>
      <comments>http://asymmetrical-view.com/2009/05/11/intro-to-git.html#comments</comments>

      <pubDate>2009-05-11T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2009/05/11/intro-to-git.html</guid>

      <id>http://asymmetrical-view.com/2009/05/11/intro-to-git</id>
      <description><![CDATA[<h1>Introduction to Git talk at <span class="caps">PLUG</span> North Tonight at 7pm</h1>
<p>I&#8217;m giving my <a href="http://github.com/kyleburton/introduction-to-git/tree/master">Introduction to Git</a> talk tonight at the <a href="http://www.phillylinux.org/north.html">north</a> chapter of the <a href="http://www.phillylinux.org/">Philadelphia Linux Users Group</a>.  I&#8217;m bringing some minor give-aways, usb drives and post-it note pads, in case that is enticing :).</p>
<div style="width:425px;text-align:left" id="__ss_1452995"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/kyleburton/intro-to-git?type=presentation" title="Intro To Git">Intro To Git</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introtogit-090518104200-phpapp02&stripped_title=intro-to-git" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introtogit-090518104200-phpapp02&stripped_title=intro-to-git" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/kyleburton">kyleburton</a>.</div></div>
<p class="meta">Kyle Burton, 11 May 2009 &#8211; Wayne PA</p>]]></description>
      <content:encoded><![CDATA[<h1>Introduction to Git talk at <span class="caps">PLUG</span> North Tonight at 7pm</h1>
<p>I&#8217;m giving my <a href="http://github.com/kyleburton/introduction-to-git/tree/master">Introduction to Git</a> talk tonight at the <a href="http://www.phillylinux.org/north.html">north</a> chapter of the <a href="http://www.phillylinux.org/">Philadelphia Linux Users Group</a>.  I&#8217;m bringing some minor give-aways, usb drives and post-it note pads, in case that is enticing :).</p>
<div style="width:425px;text-align:left" id="__ss_1452995"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/kyleburton/intro-to-git?type=presentation" title="Intro To Git">Intro To Git</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introtogit-090518104200-phpapp02&stripped_title=intro-to-git" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introtogit-090518104200-phpapp02&stripped_title=intro-to-git" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/kyleburton">kyleburton</a>.</div></div>
<p class="meta">Kyle Burton, 11 May 2009 &#8211; Wayne PA</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Introduction to Git talk at PLUG Central Tonight at 7pm</title>
      <link>http://asymmetrical-view.com/2009/05/06/intro-to-git.html</link>
      <comments>http://asymmetrical-view.com/2009/05/06/intro-to-git.html#comments</comments>

      <pubDate>2009-05-06T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2009/05/06/intro-to-git.html</guid>

      <id>http://asymmetrical-view.com/2009/05/06/intro-to-git</id>
      <description><![CDATA[<h1>Introduction to Git talk at <span class="caps">PLUG</span> Central Tonight at 7pm</h1>
<p>I&#8217;m giving my <a href="http://github.com/kyleburton/introduction-to-git/tree/master">Introduction to Git</a> talk tonight at <span class="caps">PLUG</span> Central the main chapter of the <a href="http://www.phillylinux.org/">Philadelphia Linux Users Group</a>.  I&#8217;m bringing some minor give-aways, usb drives and post-it note pads, in case that is enticing :).</p>
<div style="width:425px;text-align:left" id="__ss_1452995"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/kyleburton/intro-to-git?type=presentation" title="Intro To Git">Intro To Git</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introtogit-090518104200-phpapp02&stripped_title=intro-to-git" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introtogit-090518104200-phpapp02&stripped_title=intro-to-git" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/kyleburton">kyleburton</a>.</div></div>
<p class="meta">Kyle Burton, 06 May 2009 &#8211; Wayne PA</p>]]></description>
      <content:encoded><![CDATA[<h1>Introduction to Git talk at <span class="caps">PLUG</span> Central Tonight at 7pm</h1>
<p>I&#8217;m giving my <a href="http://github.com/kyleburton/introduction-to-git/tree/master">Introduction to Git</a> talk tonight at <span class="caps">PLUG</span> Central the main chapter of the <a href="http://www.phillylinux.org/">Philadelphia Linux Users Group</a>.  I&#8217;m bringing some minor give-aways, usb drives and post-it note pads, in case that is enticing :).</p>
<div style="width:425px;text-align:left" id="__ss_1452995"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/kyleburton/intro-to-git?type=presentation" title="Intro To Git">Intro To Git</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introtogit-090518104200-phpapp02&stripped_title=intro-to-git" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introtogit-090518104200-phpapp02&stripped_title=intro-to-git" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/kyleburton">kyleburton</a>.</div></div>
<p class="meta">Kyle Burton, 06 May 2009 &#8211; Wayne PA</p>]]></content:encoded>
    </item>
    
    <item>
      <title>List Comprehensions in Clojure</title>
      <link>http://asymmetrical-view.com/2008/11/18/list-comprehensions-in-clojure.html</link>
      <comments>http://asymmetrical-view.com/2008/11/18/list-comprehensions-in-clojure.html#comments</comments>

      <pubDate>2008-11-18T00:00:00-05:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2008/11/18/list-comprehensions-in-clojure.html</guid>

      <id>http://asymmetrical-view.com/2008/11/18/list-comprehensions-in-clojure</id>
      <description><![CDATA[<h1>List Comprehensions in Clojure</h1>
<p>This is a basic example of the list comprehension support in <a href="http://clojure.org/">Clojure</a>, the same feature supported by <a href="http://erlang.org/">Erlang</a>, <a href="http://www.haskell.org/">Haskell</a> and Common Lisp (via a libraries like <a href="http://github.com/jmbr/incf-cl/tree/master">incf-cl</a>).</p>
<pre class="code">
;; generate the positions of a chess board:
(for [file "ABCDEFGH"
      rank (range 1 9)]
  (format "%c%d" file rank))

;; Evaluate and put the result into the buffer: C-u 8 C-x C-e
;; ("A1" "A2" "A3" "A4" "A5" "A6" "A7" "A8" 
;;  "B1" "B2" "B3" "B4" "B5" "B6" "B7" "B8" 
;;  "C1" "C2" "C3" "C4" "C5" "C6" "C7" "C8" 
;;  "D1" "D2" "D3" "D4" "D5" "D6" "D7" "D8" 
;;  "E1" "E2" "E3" "E4" "E5" "E6" "E7" "E8" 
;;  "F1" "F2" "F3" "F4" "F5" "F6" "F7" "F8" 
;;  "G1" "G2" "G3" "G4" "G5" "G6" "G7" "G8" 
;;  "H1" "H2" "H3" "H4" "H5" "H6" "H7" "H8")

(count (for [file "ABCDEFGH"
              rank (range 1 9)]
          (format "%c%d" file rank)))
;; Make sure it 8x8 (64)

;; the pythagorean triples example:
(for [aa (range 1 10)
      bb (range 1 10)
      cc (range 1 10)
      :when (= (* cc cc)
               (+ (* aa aa)
                  (* bb bb)))]
  (list aa bb cc))
;; ((3 4 5) (4 3 5))

;; all permutations
(defn all-permutations [things]
  (if (= 1 (count things))
    (list things)
    (for [head things
          tail (all-permutations (disj (set things) head))]
      (do
        (cons head tail)))))

(all-permutations '(a b c))
;; ((a c b) (a b c) (b a c) (b c a) (c a b) (c b a))

</pre>
<p class="meta">Kyle Burton, 11 Nov 2008 &#8211; Wayne PA</p>]]></description>
      <content:encoded><![CDATA[<h1>List Comprehensions in Clojure</h1>
<p>This is a basic example of the list comprehension support in <a href="http://clojure.org/">Clojure</a>, the same feature supported by <a href="http://erlang.org/">Erlang</a>, <a href="http://www.haskell.org/">Haskell</a> and Common Lisp (via a libraries like <a href="http://github.com/jmbr/incf-cl/tree/master">incf-cl</a>).</p>
<pre class="code">
;; generate the positions of a chess board:
(for [file "ABCDEFGH"
      rank (range 1 9)]
  (format "%c%d" file rank))

;; Evaluate and put the result into the buffer: C-u 8 C-x C-e
;; ("A1" "A2" "A3" "A4" "A5" "A6" "A7" "A8" 
;;  "B1" "B2" "B3" "B4" "B5" "B6" "B7" "B8" 
;;  "C1" "C2" "C3" "C4" "C5" "C6" "C7" "C8" 
;;  "D1" "D2" "D3" "D4" "D5" "D6" "D7" "D8" 
;;  "E1" "E2" "E3" "E4" "E5" "E6" "E7" "E8" 
;;  "F1" "F2" "F3" "F4" "F5" "F6" "F7" "F8" 
;;  "G1" "G2" "G3" "G4" "G5" "G6" "G7" "G8" 
;;  "H1" "H2" "H3" "H4" "H5" "H6" "H7" "H8")

(count (for [file "ABCDEFGH"
              rank (range 1 9)]
          (format "%c%d" file rank)))
;; Make sure it 8x8 (64)

;; the pythagorean triples example:
(for [aa (range 1 10)
      bb (range 1 10)
      cc (range 1 10)
      :when (= (* cc cc)
               (+ (* aa aa)
                  (* bb bb)))]
  (list aa bb cc))
;; ((3 4 5) (4 3 5))

;; all permutations
(defn all-permutations [things]
  (if (= 1 (count things))
    (list things)
    (for [head things
          tail (all-permutations (disj (set things) head))]
      (do
        (cons head tail)))))

(all-permutations '(a b c))
;; ((a c b) (a b c) (b a c) (b c a) (c a b) (c b a))

</pre>
<p class="meta">Kyle Burton, 11 Nov 2008 &#8211; Wayne PA</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Cloud Con East 2008</title>
      <link>http://asymmetrical-view.com/2008/10/21/cloud-con-east-notes.html</link>
      <comments>http://asymmetrical-view.com/2008/10/21/cloud-con-east-notes.html#comments</comments>

      <pubDate>2008-10-21T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2008/10/21/cloud-con-east-notes.html</guid>

      <id>http://asymmetrical-view.com/2008/10/21/cloud-con-east-notes</id>
      <description><![CDATA[<h1>Cloud Con East 2008</h1>
<p>Overall <a href="http://www.chariotsolutions.com/">Chariot Solutions</a> <a href="http://www.cloudconeast.com/">Computing Among The Clouds</a> was a great conference.</p>
<p>Cloud computing is not well defined and mostly correlates to the movement of applications, services and compute resources (machines, storage, queuing services) into hosted data centers and billed based on usage.  It brings with it concepts of dynamic provisioning and relinquishing of resources.</p>
<p>So, how do you evaluate the current cloud offerings?</p>
<h3>Stick With Your Own Data Center If</h3>
<h5>You have a steady baseline load.</h5>
<p><span class="caps">AWS</span>, used 24&#215;7&#215;365 is more expensive (in 2008) than owning and hosting physical machines in terms of capex for many organizations.</p>
<h5>You have hard SLAs</h5>
<p>If you need more than 3 or 4 9&#8217;s, you are better off with more traditional hosting or your own data center.  Currently <span class="caps">AWS</span> doesn&#8217;t guarantee up-time as well as many medium and large business can with their own dedicated IT staffs and data centers.</p>
<h5>You can handle your peak loads</h5>
<p>If you have constant processing loads or have an <span class="caps">SLA</span> that requires you to have enough spare capacity to handle any given peak, then you&#8217;re better served with your own data center.  There is no reason to rent capacity if you already have it.</p>
<h5>You have sensitive data</h5>
<p>You may require more certainty about where the data gets stored and who has access to it.  This is likely to be a legislative or contractual issue than organizational.  Though there are cloud computing platforms and initiatives that are working towards security data data protection certifications.</p>
<h3>On Demand (<span class="caps">AWS</span> EC2) Is Right For You If</h3>
<h5>You have intermittent load</h5>
<p>Your needs scale up and then can scale back down, thus saving on keeping spare capacity on-line.</p>
<h5>You can plan for the Peaks</h5>
<p>If you can anticipate load spikes, then you will have time to provision resources to handle those loads.</p>
<h5>You have no capitol budget</h5>
<p>If you have no capitol budget but must do large scale testing or data analysis, then renting resources will be significantly cheaper than buying hardware.</p>
<h5>You want to charge based on utilization</h5>
<p>You have a service where you can charge in direct proportion to utilization rather than based on capacity.</p>
<h3>Higher Level Application Stacks, PaaS Google App Engine</h3>
<p>Keep in mind these are new and the space is still being explored, more will appear.   Models will develop around these PaaS providers [Platform as a Service], more languages and frameworks will be supported &#8211; though they will mostly will be based on those that can be easily hosted, sandboxed and run-time instrumented, which is why you&#8217;re seeing Python first and Java following closely along.</p>
<p>These providers hide the provisioning from you.  Google&#8217;s offering dynamically scales your application up and down based on utilization.  This provides a significant reduction in your design and administrative overhead for web development projects.</p>
<p>Simplicity of application development <em>and</em> scalability are rarely found in existing technologies, this will be one of the more interesting segments to watch mature.</p>
<p>Organizations and individuals are starting to learn how they need to change the design of their services and applications to take better advantage of the Cloud.  It takes a change in mind-set &#8211; the phrase was dropped &#8220;Machine Instances are the new processes&#8221; and I think that&#8217;s an appropriate framing of one of the changes in mindset for taking advantage of the mass of resources that is becoming available.</p>
<p>Changing your software to be more easily bootstrapped, eliminate the assumption that you have access to local, disk based services &#8211; everything is pulled remotely, use URLs, and services &#8211; don&#8217;t assume local interfaces, assume remote.  Design to come up / boot faster &#8211; scaling up / down quickly you don&#8217;t get the same amortization over time for start up costs.  Design with the crash fast mentality &#8211; as robust as these systems are, you should still design with the idea that the system could go away at any moment.  In addition to the benefit of quickly recovering from unexpected outages, this allows you to scale <em>down</em> faster, not just up.  Keep your persistent data in the providers data stores and use the provided queuing systems to distribute work.</p>
<h3>Gaining Wider Acceptance</h3>
<p>There are some things these offerings need to do to gain wider acceptance.</p>
<p>Harder SLAs will develop as there is more competition.  Higher level tools will develop on top of the instance-based cloud offerings (EC2) to allow for more automated provisioning &#8211; this will make it easier for you, but as easy as the PaaS stacks like <span class="caps">GAE</span> will make it.</p>
<p>We&#8217;ll see tools and offerings develop that will come down towards traditional data centers to allow a simpler mixing of a traditional service with bleed over to the cloud as resources need to be scaled up but also so that you can have control over the processing of your (sensitive) data in your own protected environment but push generic activity up into the cloud as necessary.</p>
<h3>Other notable happenings</h3>
<p>Microsoft is creating AMIs for Windows on EC2.</p>
<p>Google just announced that Java will be a supported App Engine development language &#8211; previously only Python was supported.</p>
<h3>Haskell in the corporate environment</h3>
<p>This session seemed out of place for the event &#8211; not really Cloud oriented.  Though I personally see Functional Programming being a larger industry trend and something that facilitates concurrency and parallelization.  It follows from structured -&gt; procedural -&gt; object oriented -&gt; functional &#8211; with respect to the time line of coming out of academia at least, not necessarily the idea of one being &#8216;higher level&#8217; than the other &#8211; though so far, time has implied that with the other programming paradigms.</p>
<p>The presenter, Jeff Polakow, is using it extensively at his current employer.</p>
<p>Those kinds of firms (Wall St.) allow a lot of latitude to the technical staff, so its easier to experiment (R&amp;D) with new technologies.  It&#8217;s much harder for a company like my own to decide to take on something like this &#8211; it&#8217;s hard to find developers who know how to develop, deploy, monitor and design with these technologies.</p>
<p>Functional Programming trend is being pushed into industry by the shift to multi-core, the past difficulties of developing concurrent, the more wide spread need for parallel/distributed applications (concurrency is the new garbage collection &#8211; it will become something that developers no longer control manually), the need for infrastructural level automatic scaling, and the easier path to robustness that languages like Erlang offer.</p>
<p>In languages like Java, you have to take into consideration all the libraries (where the default development practice in many cases is to not consider the re-entrancy &#8211; you can&#8217;t make the assumption that code is thread-safe in Java) you&#8217;re using with respect to their referential transparency &#8211; it&#8217;s not the default.  In the FP languages referential transparency is the <em>default</em> case, so you can, in general, make that assumption.  The underlying stack can also make that assumption about your code as well &#8211; which is why the concurrency / distribution model is less coupled to the implementation than it is in the more imperative languages.</p>
<h3>Horizontal Scaling with HiveDB</h3>
<p>CafePress has a <em>large</em> catalog.  I was surprised to hear that they have 265 million products across all their customers catalogs.  They have a low margin based on the aggregate amount of data they have to store and serve up, so commercial solutions like Oracle were just not an option for them simply due to cost.</p>
<p>Cafe spent time analyzing their options and didn&#8217;t find anything that fit their needs (cost, performance, on-line resharding), and went down the path of creating a more scalable data storage architecture themselves.</p>
<p>The solution they created performs better, scales better, is more robust and has a better <span class="caps">SLA</span> than many of the commercial solutions (their words).</p>
<p>Cafe&#8217;s <span class="caps">DAL</span> is effectively a hibernate extension that uses MySQL to do data partitioning (pseudo-automatically) by using a set of replicated MySQL databases as a catalog to map to where the data is stored for your shard (replicated 3x).  The system supports dynamic repartitioning &#8211; migration of shards away from a shard-host to get less busy data away from data that is more &#8216;hot&#8217; &#8211; the busiest data sets end up on their own shard-node with everything else having been pushed away from them.</p>
<p>They only need to &#8216;lock&#8217; is for a single user when migrating their data off the shard.  This is a write-lock, not a read lock &#8211; it only keeps the user from updating their own catalog of products while the move is taking place.  Most users never notice when this happens.  The system as a whole doesn&#8217;t go down (their words).  The MySQL catalogs are replicated (3 machines, master-master, writing to 1) and can be upgraded by taking 1 of the 3 out of the cluster at a time.  The same kind of approach goes for the other sharing servers.</p>
<h3>Panel Discussion</h3>
<p>The panel discussion was most memorable for how Chris and Toby seemed to dominate the discussion.</p>
<h3>Hive and Hadoop</h3>
<p>Hive is a data storage system developed on top of Hadoop with its own query language (HiveQL), built by Facebook.  The goals are a bit different from HiveDB &#8211; HiveDB is more for <span class="caps">OLTP</span>, while Hive is more for large-scale analytics.  Being built on top of Hadoop, HiveDB is much more batch oriented.  Facebook uses it for doing analytics, data-mining, and machine-learning of their user and transactional data sets (logs, user activities, etc.) to mine out aggregate and trending intelligence from the large data set.</p>
<p>Interesting fact: Facebook&#8217;s Hive sees <strong>2Tb</strong> of growth <em>per</em> <strong><em>day</em></strong>.</p>
<h3>Building Scalable Web Applications with Google App Engine</h3>
<p>PaaS stacks like <span class="caps">GAE</span> take a more managed environment approach than the more raw or primitive services provided by <span class="caps">AWS</span> style on-demand services.  The two fit into different use cases though and, <span class="caps">IMO</span>, one will not necessarily eliminate the other.</p>
<p><span class="caps">GAE</span> takes away from you all the concerns about deployment, production architecture, system management or administration.  It gives you a data store with an OO <span class="caps">API</span>, and a web-app development environment that you develop your application within.  There are things you can&#8217;t do, for example, you can&#8217;t run arbitrary software or services on <span class="caps">GAE</span> like you can on the more machine-image based cloud services (<span class="caps">AWS</span> EC2).</p>
<p>What you gain from giving up those capabilities is Google&#8217;s infrastructure for scaling, it becomes <em>your</em> infrastructure for scaling.  Your app is designed in a pseudo-functional way &#8211; the stack encourages you to design your app to perform all dynamism at put/post time and to just render/display at get time.  This approach helps with the scaling of the system.  Storage location transparency helps with spooling up other instances of the app in disparate data centers, etc.</p>
<p>This kind of stack really makes it easy to develop the most common case of web applications &#8211; it is both easy to do and it scales.  This is a combination that you rarely see in a platform or technology.</p>
<p>I see these kinds of stacks as becoming more established and a large part of Internet based application development &#8211; I think that more organizations will offer these kind of stacks across more technologies.</p>
<p>My advice: You should sign up for an account and try <a href="http://code.google.com/appengine/"><span class="caps">GAE</span></a> out.</p>
<h3>Developing and Deploying Java applications on Amazon EC2</h3>
<p>Chris Richardson has created cloud-tools, a package of utilities (and a <a href="http://maven.apache.org/">maven</a> plug-in) for provisioning EC2 instances, pushing your application up and executing tasks across your cluster of instances.  The tools look like they make it very easy to get your Java app into EC2.</p>
<h2>Conclusion</h2>
<p>The main theme I took away from it is that on-demand computing is a continuing trend.  Services will continue to appear and be developed that will make taking advantage of these resource pools easier and more cost effective.</p>
<p>The trend for physical data centers will continue to become more and more outsourced to organizations that can provide those services with greater economy of scale.  Currently Amazon&#8217;s offerings are slightly more expensive than a hosted system that you own &#8211; in the case where you need up-time or have high constant utilization.  More guidelines are being developed showing when the trade off is appropriate.  As a trend, cloud computing is still new and not well defined &#8211; it is likely that these trade offs will shift &#8211; even as soon as over the next few years (eg: it is likely, in my opinion, that the raw cost of 24&#215;7 allocation for SMBs will fall below the cost of ownership due to these on-demand provider&#8217;s economies of scale).</p>
<p>We&#8217;re past the point of asking if your organization can make use of these on-demand providers and to the point where you should be identifying the areas where you can realize savings by taking advantage of these services.</p>
<p class="meta">Kyle Burton, 21 Oct 2008 &#8211; Malvern PA</p>]]></description>
      <content:encoded><![CDATA[<h1>Cloud Con East 2008</h1>
<p>Overall <a href="http://www.chariotsolutions.com/">Chariot Solutions</a> <a href="http://www.cloudconeast.com/">Computing Among The Clouds</a> was a great conference.</p>
<p>Cloud computing is not well defined and mostly correlates to the movement of applications, services and compute resources (machines, storage, queuing services) into hosted data centers and billed based on usage.  It brings with it concepts of dynamic provisioning and relinquishing of resources.</p>
<p>So, how do you evaluate the current cloud offerings?</p>
<h3>Stick With Your Own Data Center If</h3>
<h5>You have a steady baseline load.</h5>
<p><span class="caps">AWS</span>, used 24&#215;7&#215;365 is more expensive (in 2008) than owning and hosting physical machines in terms of capex for many organizations.</p>
<h5>You have hard SLAs</h5>
<p>If you need more than 3 or 4 9&#8217;s, you are better off with more traditional hosting or your own data center.  Currently <span class="caps">AWS</span> doesn&#8217;t guarantee up-time as well as many medium and large business can with their own dedicated IT staffs and data centers.</p>
<h5>You can handle your peak loads</h5>
<p>If you have constant processing loads or have an <span class="caps">SLA</span> that requires you to have enough spare capacity to handle any given peak, then you&#8217;re better served with your own data center.  There is no reason to rent capacity if you already have it.</p>
<h5>You have sensitive data</h5>
<p>You may require more certainty about where the data gets stored and who has access to it.  This is likely to be a legislative or contractual issue than organizational.  Though there are cloud computing platforms and initiatives that are working towards security data data protection certifications.</p>
<h3>On Demand (<span class="caps">AWS</span> EC2) Is Right For You If</h3>
<h5>You have intermittent load</h5>
<p>Your needs scale up and then can scale back down, thus saving on keeping spare capacity on-line.</p>
<h5>You can plan for the Peaks</h5>
<p>If you can anticipate load spikes, then you will have time to provision resources to handle those loads.</p>
<h5>You have no capitol budget</h5>
<p>If you have no capitol budget but must do large scale testing or data analysis, then renting resources will be significantly cheaper than buying hardware.</p>
<h5>You want to charge based on utilization</h5>
<p>You have a service where you can charge in direct proportion to utilization rather than based on capacity.</p>
<h3>Higher Level Application Stacks, PaaS Google App Engine</h3>
<p>Keep in mind these are new and the space is still being explored, more will appear.   Models will develop around these PaaS providers [Platform as a Service], more languages and frameworks will be supported &#8211; though they will mostly will be based on those that can be easily hosted, sandboxed and run-time instrumented, which is why you&#8217;re seeing Python first and Java following closely along.</p>
<p>These providers hide the provisioning from you.  Google&#8217;s offering dynamically scales your application up and down based on utilization.  This provides a significant reduction in your design and administrative overhead for web development projects.</p>
<p>Simplicity of application development <em>and</em> scalability are rarely found in existing technologies, this will be one of the more interesting segments to watch mature.</p>
<p>Organizations and individuals are starting to learn how they need to change the design of their services and applications to take better advantage of the Cloud.  It takes a change in mind-set &#8211; the phrase was dropped &#8220;Machine Instances are the new processes&#8221; and I think that&#8217;s an appropriate framing of one of the changes in mindset for taking advantage of the mass of resources that is becoming available.</p>
<p>Changing your software to be more easily bootstrapped, eliminate the assumption that you have access to local, disk based services &#8211; everything is pulled remotely, use URLs, and services &#8211; don&#8217;t assume local interfaces, assume remote.  Design to come up / boot faster &#8211; scaling up / down quickly you don&#8217;t get the same amortization over time for start up costs.  Design with the crash fast mentality &#8211; as robust as these systems are, you should still design with the idea that the system could go away at any moment.  In addition to the benefit of quickly recovering from unexpected outages, this allows you to scale <em>down</em> faster, not just up.  Keep your persistent data in the providers data stores and use the provided queuing systems to distribute work.</p>
<h3>Gaining Wider Acceptance</h3>
<p>There are some things these offerings need to do to gain wider acceptance.</p>
<p>Harder SLAs will develop as there is more competition.  Higher level tools will develop on top of the instance-based cloud offerings (EC2) to allow for more automated provisioning &#8211; this will make it easier for you, but as easy as the PaaS stacks like <span class="caps">GAE</span> will make it.</p>
<p>We&#8217;ll see tools and offerings develop that will come down towards traditional data centers to allow a simpler mixing of a traditional service with bleed over to the cloud as resources need to be scaled up but also so that you can have control over the processing of your (sensitive) data in your own protected environment but push generic activity up into the cloud as necessary.</p>
<h3>Other notable happenings</h3>
<p>Microsoft is creating AMIs for Windows on EC2.</p>
<p>Google just announced that Java will be a supported App Engine development language &#8211; previously only Python was supported.</p>
<h3>Haskell in the corporate environment</h3>
<p>This session seemed out of place for the event &#8211; not really Cloud oriented.  Though I personally see Functional Programming being a larger industry trend and something that facilitates concurrency and parallelization.  It follows from structured -&gt; procedural -&gt; object oriented -&gt; functional &#8211; with respect to the time line of coming out of academia at least, not necessarily the idea of one being &#8216;higher level&#8217; than the other &#8211; though so far, time has implied that with the other programming paradigms.</p>
<p>The presenter, Jeff Polakow, is using it extensively at his current employer.</p>
<p>Those kinds of firms (Wall St.) allow a lot of latitude to the technical staff, so its easier to experiment (R&amp;D) with new technologies.  It&#8217;s much harder for a company like my own to decide to take on something like this &#8211; it&#8217;s hard to find developers who know how to develop, deploy, monitor and design with these technologies.</p>
<p>Functional Programming trend is being pushed into industry by the shift to multi-core, the past difficulties of developing concurrent, the more wide spread need for parallel/distributed applications (concurrency is the new garbage collection &#8211; it will become something that developers no longer control manually), the need for infrastructural level automatic scaling, and the easier path to robustness that languages like Erlang offer.</p>
<p>In languages like Java, you have to take into consideration all the libraries (where the default development practice in many cases is to not consider the re-entrancy &#8211; you can&#8217;t make the assumption that code is thread-safe in Java) you&#8217;re using with respect to their referential transparency &#8211; it&#8217;s not the default.  In the FP languages referential transparency is the <em>default</em> case, so you can, in general, make that assumption.  The underlying stack can also make that assumption about your code as well &#8211; which is why the concurrency / distribution model is less coupled to the implementation than it is in the more imperative languages.</p>
<h3>Horizontal Scaling with HiveDB</h3>
<p>CafePress has a <em>large</em> catalog.  I was surprised to hear that they have 265 million products across all their customers catalogs.  They have a low margin based on the aggregate amount of data they have to store and serve up, so commercial solutions like Oracle were just not an option for them simply due to cost.</p>
<p>Cafe spent time analyzing their options and didn&#8217;t find anything that fit their needs (cost, performance, on-line resharding), and went down the path of creating a more scalable data storage architecture themselves.</p>
<p>The solution they created performs better, scales better, is more robust and has a better <span class="caps">SLA</span> than many of the commercial solutions (their words).</p>
<p>Cafe&#8217;s <span class="caps">DAL</span> is effectively a hibernate extension that uses MySQL to do data partitioning (pseudo-automatically) by using a set of replicated MySQL databases as a catalog to map to where the data is stored for your shard (replicated 3x).  The system supports dynamic repartitioning &#8211; migration of shards away from a shard-host to get less busy data away from data that is more &#8216;hot&#8217; &#8211; the busiest data sets end up on their own shard-node with everything else having been pushed away from them.</p>
<p>They only need to &#8216;lock&#8217; is for a single user when migrating their data off the shard.  This is a write-lock, not a read lock &#8211; it only keeps the user from updating their own catalog of products while the move is taking place.  Most users never notice when this happens.  The system as a whole doesn&#8217;t go down (their words).  The MySQL catalogs are replicated (3 machines, master-master, writing to 1) and can be upgraded by taking 1 of the 3 out of the cluster at a time.  The same kind of approach goes for the other sharing servers.</p>
<h3>Panel Discussion</h3>
<p>The panel discussion was most memorable for how Chris and Toby seemed to dominate the discussion.</p>
<h3>Hive and Hadoop</h3>
<p>Hive is a data storage system developed on top of Hadoop with its own query language (HiveQL), built by Facebook.  The goals are a bit different from HiveDB &#8211; HiveDB is more for <span class="caps">OLTP</span>, while Hive is more for large-scale analytics.  Being built on top of Hadoop, HiveDB is much more batch oriented.  Facebook uses it for doing analytics, data-mining, and machine-learning of their user and transactional data sets (logs, user activities, etc.) to mine out aggregate and trending intelligence from the large data set.</p>
<p>Interesting fact: Facebook&#8217;s Hive sees <strong>2Tb</strong> of growth <em>per</em> <strong><em>day</em></strong>.</p>
<h3>Building Scalable Web Applications with Google App Engine</h3>
<p>PaaS stacks like <span class="caps">GAE</span> take a more managed environment approach than the more raw or primitive services provided by <span class="caps">AWS</span> style on-demand services.  The two fit into different use cases though and, <span class="caps">IMO</span>, one will not necessarily eliminate the other.</p>
<p><span class="caps">GAE</span> takes away from you all the concerns about deployment, production architecture, system management or administration.  It gives you a data store with an OO <span class="caps">API</span>, and a web-app development environment that you develop your application within.  There are things you can&#8217;t do, for example, you can&#8217;t run arbitrary software or services on <span class="caps">GAE</span> like you can on the more machine-image based cloud services (<span class="caps">AWS</span> EC2).</p>
<p>What you gain from giving up those capabilities is Google&#8217;s infrastructure for scaling, it becomes <em>your</em> infrastructure for scaling.  Your app is designed in a pseudo-functional way &#8211; the stack encourages you to design your app to perform all dynamism at put/post time and to just render/display at get time.  This approach helps with the scaling of the system.  Storage location transparency helps with spooling up other instances of the app in disparate data centers, etc.</p>
<p>This kind of stack really makes it easy to develop the most common case of web applications &#8211; it is both easy to do and it scales.  This is a combination that you rarely see in a platform or technology.</p>
<p>I see these kinds of stacks as becoming more established and a large part of Internet based application development &#8211; I think that more organizations will offer these kind of stacks across more technologies.</p>
<p>My advice: You should sign up for an account and try <a href="http://code.google.com/appengine/"><span class="caps">GAE</span></a> out.</p>
<h3>Developing and Deploying Java applications on Amazon EC2</h3>
<p>Chris Richardson has created cloud-tools, a package of utilities (and a <a href="http://maven.apache.org/">maven</a> plug-in) for provisioning EC2 instances, pushing your application up and executing tasks across your cluster of instances.  The tools look like they make it very easy to get your Java app into EC2.</p>
<h2>Conclusion</h2>
<p>The main theme I took away from it is that on-demand computing is a continuing trend.  Services will continue to appear and be developed that will make taking advantage of these resource pools easier and more cost effective.</p>
<p>The trend for physical data centers will continue to become more and more outsourced to organizations that can provide those services with greater economy of scale.  Currently Amazon&#8217;s offerings are slightly more expensive than a hosted system that you own &#8211; in the case where you need up-time or have high constant utilization.  More guidelines are being developed showing when the trade off is appropriate.  As a trend, cloud computing is still new and not well defined &#8211; it is likely that these trade offs will shift &#8211; even as soon as over the next few years (eg: it is likely, in my opinion, that the raw cost of 24&#215;7 allocation for SMBs will fall below the cost of ownership due to these on-demand provider&#8217;s economies of scale).</p>
<p>We&#8217;re past the point of asking if your organization can make use of these on-demand providers and to the point where you should be identifying the areas where you can realize savings by taking advantage of these services.</p>
<p class="meta">Kyle Burton, 21 Oct 2008 &#8211; Malvern PA</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Common Lisp - destructuring-bind</title>
      <link>http://asymmetrical-view.com/2008/09/18/destructuring-bind.html</link>
      <comments>http://asymmetrical-view.com/2008/09/18/destructuring-bind.html#comments</comments>

      <pubDate>2008-09-18T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2008/09/18/destructuring-bind.html</guid>

      <id>http://asymmetrical-view.com/2008/09/18/destructuring-bind</id>
      <description><![CDATA[<h1>Common Lisp &#8211; destructuring-bind</h1>
<p>Destructuring bind examples in Common Lisp:</p>
<pre class="code">
;; This is a typical usage, for pulling apart a list
(destructuring-bind
      (first second)
    '(1 2)
  (format t "~%~%;;; =&gt; first:~a second:~a~&amp;" first second))
;;; &gt; first:1 second:2

;; You can also pull apart improper lists:
(destructuring-bind
      (first . second)
    '(1 . 2)
  (format t "~%~%;;; =&gt; first:~a second:~a~&amp;" first second))

;;; &gt; first:1 second:2

;; The first argument to destructuring-bind is a lambda list, but you
;; can grab the remainder by either using a dotted list:

(destructuring-bind
      (first second . stuff)
    '(1 2 3 4 5)
  (format t "~%~%;;; =&gt; first:~a second:~a rest:~a~&amp;" first second stuff))

;;; =&gt; first:1 second:2 rest:(3 4 5)

;; or you can grab the remainder with &amp;rest, just like you do for
;; functions that take a variable number of arguments:
(destructuring-bind
      (first second &amp;rest stuff)
    '(1 2 3 4 5)
  (format t "~%~%;;; =&gt; first:~a second:~a rest:~a~&amp;" first second stuff))

;;; =&gt; first:1 second:2 rest:(3 4 5)

;; It really is a lambda list, you can use default parameters:
(destructuring-bind
      (first second &amp;optional (third 'default))
    '(1 2)
  (format t "~%~%;;; =&gt; first:~a second:~a third:~a~&amp;" first second third))

;;; =&gt; first:1 second:2 third:DEFAULT

(destructuring-bind
      (first second &amp;optional (third 'default))
    '(1 2 3)
  (format t "~%~%;;; =&gt; first:~a second:~a third:~a~&amp;" first second third))

;;; =&gt; first:1 second:2 third:3

;; And you can use keyword parameters:
(destructuring-bind
      (first second &amp;key third)
    '(1 2 :third 3)
  (format t "~%~%;;; =&gt; first:~a second:~a third:~a~&amp;" first second third))

;;; =&gt; first:1 second:2 third:3

;; Finally, you can use it to 'unparse' trees as well, which is a
;; really great feature, since your variable declaration matches the
;; 'shape' of the data strucutre you're pulling apart.  This technique
;; is really handy for dealing with XML after it's been converted to
;; s-expressions.
(destructuring-bind
      (a (b (c d e (f g) h i j)) &amp;rest remainder)
    '(1 (2 (3 4 5 (6 7) 8 9 10)) 11 12 13 14 15)
  (format t
          "~%~%;;; =&gt; a:~a b:~a c:~a d:~a e:~a f:~a g:~a h:~a i:~a j:~a remainder:~a ~&amp;"
          a b c d e f g h i j remainder))

;;; =&gt; a:1 b:2 c:3 d:4 e:5 f:6 g:7 h:8 i:9 j:10 remainder:(11 12 13 14 15)

</pre>]]></description>
      <content:encoded><![CDATA[<h1>Common Lisp &#8211; destructuring-bind</h1>
<p>Destructuring bind examples in Common Lisp:</p>
<pre class="code">
;; This is a typical usage, for pulling apart a list
(destructuring-bind
      (first second)
    '(1 2)
  (format t "~%~%;;; =&gt; first:~a second:~a~&amp;" first second))
;;; &gt; first:1 second:2

;; You can also pull apart improper lists:
(destructuring-bind
      (first . second)
    '(1 . 2)
  (format t "~%~%;;; =&gt; first:~a second:~a~&amp;" first second))

;;; &gt; first:1 second:2

;; The first argument to destructuring-bind is a lambda list, but you
;; can grab the remainder by either using a dotted list:

(destructuring-bind
      (first second . stuff)
    '(1 2 3 4 5)
  (format t "~%~%;;; =&gt; first:~a second:~a rest:~a~&amp;" first second stuff))

;;; =&gt; first:1 second:2 rest:(3 4 5)

;; or you can grab the remainder with &amp;rest, just like you do for
;; functions that take a variable number of arguments:
(destructuring-bind
      (first second &amp;rest stuff)
    '(1 2 3 4 5)
  (format t "~%~%;;; =&gt; first:~a second:~a rest:~a~&amp;" first second stuff))

;;; =&gt; first:1 second:2 rest:(3 4 5)

;; It really is a lambda list, you can use default parameters:
(destructuring-bind
      (first second &amp;optional (third 'default))
    '(1 2)
  (format t "~%~%;;; =&gt; first:~a second:~a third:~a~&amp;" first second third))

;;; =&gt; first:1 second:2 third:DEFAULT

(destructuring-bind
      (first second &amp;optional (third 'default))
    '(1 2 3)
  (format t "~%~%;;; =&gt; first:~a second:~a third:~a~&amp;" first second third))

;;; =&gt; first:1 second:2 third:3

;; And you can use keyword parameters:
(destructuring-bind
      (first second &amp;key third)
    '(1 2 :third 3)
  (format t "~%~%;;; =&gt; first:~a second:~a third:~a~&amp;" first second third))

;;; =&gt; first:1 second:2 third:3

;; Finally, you can use it to 'unparse' trees as well, which is a
;; really great feature, since your variable declaration matches the
;; 'shape' of the data strucutre you're pulling apart.  This technique
;; is really handy for dealing with XML after it's been converted to
;; s-expressions.
(destructuring-bind
      (a (b (c d e (f g) h i j)) &amp;rest remainder)
    '(1 (2 (3 4 5 (6 7) 8 9 10)) 11 12 13 14 15)
  (format t
          "~%~%;;; =&gt; a:~a b:~a c:~a d:~a e:~a f:~a g:~a h:~a i:~a j:~a remainder:~a ~&amp;"
          a b c d e f g h i j remainder))

;;; =&gt; a:1 b:2 c:3 d:4 e:5 f:6 g:7 h:8 i:9 j:10 remainder:(11 12 13 14 15)

</pre>]]></content:encoded>
    </item>
    
    <item>
      <title>Introduction to Lisp talk at PLUG North Tonight at 7pm</title>
      <link>http://asymmetrical-view.com/2008/08/11/introduction-to-lisp.html</link>
      <comments>http://asymmetrical-view.com/2008/08/11/introduction-to-lisp.html#comments</comments>

      <pubDate>2008-08-11T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2008/08/11/introduction-to-lisp.html</guid>

      <id>http://asymmetrical-view.com/2008/08/11/introduction-to-lisp</id>
      <description><![CDATA[<h1>Introduction to Lisp talk at <span class="caps">PLUG</span> North Tonight at 7pm</h1>
<p>I&#8217;m giving my Introduction to Lisp talk tonight at the <a href="http://www.phillylinux.org/north.html">north</a> chapter of the <a href="http://www.phillylinux.org/">Philadelphia Linux Users Group</a>.</p>
<div style="width:425px;text-align:left" id="__ss_1453033"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/kyleburton/introduction-to-lisp?type=presentation" title="Introduction To Lisp">Introduction To Lisp</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introduction-to-lisp-090518105029-phpapp01&stripped_title=introduction-to-lisp" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introduction-to-lisp-090518105029-phpapp01&stripped_title=introduction-to-lisp" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/kyleburton">kyleburton</a>.</div></div>
<p class="meta">Kyle Burton, 11 Aug 2008 &#8211; Wayne PA</p>]]></description>
      <content:encoded><![CDATA[<h1>Introduction to Lisp talk at <span class="caps">PLUG</span> North Tonight at 7pm</h1>
<p>I&#8217;m giving my Introduction to Lisp talk tonight at the <a href="http://www.phillylinux.org/north.html">north</a> chapter of the <a href="http://www.phillylinux.org/">Philadelphia Linux Users Group</a>.</p>
<div style="width:425px;text-align:left" id="__ss_1453033"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/kyleburton/introduction-to-lisp?type=presentation" title="Introduction To Lisp">Introduction To Lisp</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introduction-to-lisp-090518105029-phpapp01&stripped_title=introduction-to-lisp" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=introduction-to-lisp-090518105029-phpapp01&stripped_title=introduction-to-lisp" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/kyleburton">kyleburton</a>.</div></div>
<p class="meta">Kyle Burton, 11 Aug 2008 &#8211; Wayne PA</p>]]></content:encoded>
    </item>
    
    <item>
      <title>A Survey of Fuzzy String Matching Algorithms at PLUG Central Tonight at 7pm</title>
      <link>http://asymmetrical-view.com/2008/08/06/fuzzy-string.html</link>
      <comments>http://asymmetrical-view.com/2008/08/06/fuzzy-string.html#comments</comments>

      <pubDate>2008-08-06T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2008/08/06/fuzzy-string.html</guid>

      <id>http://asymmetrical-view.com/2008/08/06/fuzzy-string</id>
      <description><![CDATA[<h1>A Survey of Fuzzy String Matching Algorithms at <span class="caps">PLUG</span> Central Tonight at 7pm</h1>
<p>I&#8217;m giving my Survey of Fuzzy String Matching Algorithms talk tonight at the central chapter of the <a href="http://www.phillylinux.org/">Philadelphia Linux Users Group</a>.</p>
<div style="width:425px;text-align:left" id="__ss_822817"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/kyleburton/fuzzy-string-matching?type=presentation" title="Fuzzy String Matching">Fuzzy String Matching</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=fuzzy-string-matching-7107&stripped_title=fuzzy-string-matching" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=fuzzy-string-matching-7107&stripped_title=fuzzy-string-matching" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/kyleburton">kyleburton</a>.</div></div>
<p class="meta">Kyle Burton, 06 Aug 2008 &#8211; Wayne PA</p>]]></description>
      <content:encoded><![CDATA[<h1>A Survey of Fuzzy String Matching Algorithms at <span class="caps">PLUG</span> Central Tonight at 7pm</h1>
<p>I&#8217;m giving my Survey of Fuzzy String Matching Algorithms talk tonight at the central chapter of the <a href="http://www.phillylinux.org/">Philadelphia Linux Users Group</a>.</p>
<div style="width:425px;text-align:left" id="__ss_822817"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/kyleburton/fuzzy-string-matching?type=presentation" title="Fuzzy String Matching">Fuzzy String Matching</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=fuzzy-string-matching-7107&stripped_title=fuzzy-string-matching" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=fuzzy-string-matching-7107&stripped_title=fuzzy-string-matching" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/kyleburton">kyleburton</a>.</div></div>
<p class="meta">Kyle Burton, 06 Aug 2008 &#8211; Wayne PA</p>]]></content:encoded>
    </item>
    
    <item>
      <title>OSCon Day 1</title>
      <link>http://asymmetrical-view.com/2008/07/21/oscon-day-1.html</link>
      <comments>http://asymmetrical-view.com/2008/07/21/oscon-day-1.html#comments</comments>

      <pubDate>2008-07-21T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2008/07/21/oscon-day-1.html</guid>

      <id>http://asymmetrical-view.com/2008/07/21/oscon-day-1</id>
      <description><![CDATA[<h1>OSCon Day 1</h1>
<h3>Morning</h3>
<p>Andrew and I arrived for <a href="http://en.oreilly.com/oscon2008/">OScon 2008</a> registration and took advantage of the continental breakfast before heading up to the Intro to Python.</p>
<p>O&#8217;Reilly had the registration process pretty streamlined.  They had a long bank of laptops which you needed only enter your registration code, or your email address (if you registered on the OSCon conference web site).  Register, then walk up to the materials station and pick up your ID and badge card.</p>
<p>There were plenty of juices, coffee, fruit and pastries.  There was also plenty of seating.  To either <a href="http://conferences.oreillynet.com/">O&#8217;Reilly&#8217;s</a> or the <a href="http://www.oregoncc.org/">Oregon Conference Center&#8217;s</a> credit, things were very well organized.</p>
<h3>Python in 3 Hours</h3>
<p>The first conference room we were in must have had seating for a few hundred people and it was effectively full.  There was limited space for each attendee and their items (it was at least cramped for me) &#8211; though they anticipated a laptop per person &#8211; so there were plenty of power strips laid along every other row of tables within easy reach of every single seat.  It was well planned and laid out.</p>
<p>The <a href="http://en.oreilly.com/oscon2008/public/schedule/detail/2488">intro to Python</a> got underway at 8:30 and although it was geared toward an audience with some programming experience, it assumed (as the title suggested) no python experience.  <a href="http://en.oreilly.com/oscon2008/public/schedule/speaker/4913">Steve Holden</a> was a great speaker, filling in twice with anecdotes while technical issues were worked out with equipment (once was a mis-configuration of his laptop, the other was a power interruption).</p>
<p><a href="http://www.python.org/">Python</a> is a very capable language.  It is more consistent about its OO and syntax when compared to <a href="http://www.perl.org/">Perl</a>.  The python community is also a lot bigger on the use of common conventions.  This is mostly focused on formatting (one expression per line), in-line documentation and coding style in general.</p>
<p>Functions are first class types, you can assign a function to a variable, you can implement the equivalent of funcall and apply in python.  Functions can be passed as arguments.  Python supports positional parameters, default values for function params and calling functions, any function, with positional arguments, named arguments, a tuple of arguments (similar to funcall), or a dictionary (an indirect way of using named arguments).</p>
<p>Python actually has a lot of features which were inspired by functional programming (including one of my favorites: <a href="http://en.wikipedia.org/wiki/List_comprehension">list comprehensions</a>).</p>
<p>Python is byte-compiled, like Java.  You write code in a .py file, and the first time it is loaded as a module (import), python compiles the code for you.  The time stamp check of the .pyc vs the .py file is transparently handled by python &#8211; no explicit make or compile step.</p>
<p>Strings are immutable, which is something that helps <a href="http://www.jython.org/">Jython</a> be a natural fit in the <span class="caps">JVM</span>.</p>
<p>Python supports list destructuring, based on tuples.  It&#8217;s easier to show an example than to try to explain:</p>
<pre class="code">
  a, (b, c) = (1, (2, 3))

  print a,b,c =&gt; 1, 2, 3
</pre>
<p>Tuples, and this kind of binding syntax, are widely used in processing things like lists, and maps.</p>
<p>An interesting feature of the language is the pair of functions, local() and gobal().  local() returns a dictionary (Python&#8217;s name for a Map), of all of the variable bindings (and values) that are visible in the current scope (exclusive of global variables).  globals() returns the variables in the entire module&#8217;s scope (not local, lexical or class scope, and not global in the sense of a Perl global &#8211; not universally global).</p>
<h5>Other Highlights</h5>
<p>The <code>yield()</code> form, is like a weak kind of continuation.</p>
<p><code>for</code>, and <code>while</code> loops can have an else clause which is executed when the form does not execute.</p>
<p>The Python try/catch form (try/except/finally) can have an else form, again, which is executed if no exception was thrown in the try block.</p>
<h3>Introduction to Django</h3>
<p>After a break for lunch, both Andrew and I attended the Introduction to <a href="http://www.djangoproject.com/">Django</a>, presented by <a href="http://djangopeople.net/jacobian/">Jacob Kaplan-Moss</a>.</p>
<p>Django is an <span class="caps">MVC</span> framework for Python for rapid development of interactive web sites.  It is an <span class="caps">MVC</span> framework very much in the spirit of <a href="http://rubyonrails.org/">Ruby on Rails</a> &#8211; I&#8217;ve done some work in Rails and the parallels are very close between the two frameworks.</p>
<p>Django has a code generation framework, an <span class="caps">ORM</span> layer (which is very similar to Rails&#8217; ActiveRecord), an html template system (with a default syntax based on PHPs smarty template system), and integrated support for testing.</p>
<p>Django has an interesting testing feature called doctests.  If you&#8217;ve worked with an interactive language with a <span class="caps">REPL</span>, you have probably used it to explore the behavior of code and to informally test the code.  Doctests are a way of (almost literally) taking a cut and paste of the interactive session and vivifying the transcript as a regression test.  I like the idea of a recorded test, but as Andrew and I talked about it he convinced me that the literal representation wasn&#8217;t the best choice for implementing those kinds of tests. I do like the reduction of effort that comes with that kind of testing and recognize the inherent informality of it.</p>
<p>All that said, Django (like Rails) is big on doing test driven development.</p>
<p>I looked up the status of Django on Jython and apparently it&#8217;s close to being a 1.0 release (nothing I&#8217;d recommend for use at my employer at the moment, but <a href="http://www.sun.com/">Sun</a> has hired people to work on Jython and Django is one of the frameworks they are concerned with supporting).</p>
<p>I&#8217;m looking forward to tomorrow.</p>]]></description>
      <content:encoded><![CDATA[<h1>OSCon Day 1</h1>
<h3>Morning</h3>
<p>Andrew and I arrived for <a href="http://en.oreilly.com/oscon2008/">OScon 2008</a> registration and took advantage of the continental breakfast before heading up to the Intro to Python.</p>
<p>O&#8217;Reilly had the registration process pretty streamlined.  They had a long bank of laptops which you needed only enter your registration code, or your email address (if you registered on the OSCon conference web site).  Register, then walk up to the materials station and pick up your ID and badge card.</p>
<p>There were plenty of juices, coffee, fruit and pastries.  There was also plenty of seating.  To either <a href="http://conferences.oreillynet.com/">O&#8217;Reilly&#8217;s</a> or the <a href="http://www.oregoncc.org/">Oregon Conference Center&#8217;s</a> credit, things were very well organized.</p>
<h3>Python in 3 Hours</h3>
<p>The first conference room we were in must have had seating for a few hundred people and it was effectively full.  There was limited space for each attendee and their items (it was at least cramped for me) &#8211; though they anticipated a laptop per person &#8211; so there were plenty of power strips laid along every other row of tables within easy reach of every single seat.  It was well planned and laid out.</p>
<p>The <a href="http://en.oreilly.com/oscon2008/public/schedule/detail/2488">intro to Python</a> got underway at 8:30 and although it was geared toward an audience with some programming experience, it assumed (as the title suggested) no python experience.  <a href="http://en.oreilly.com/oscon2008/public/schedule/speaker/4913">Steve Holden</a> was a great speaker, filling in twice with anecdotes while technical issues were worked out with equipment (once was a mis-configuration of his laptop, the other was a power interruption).</p>
<p><a href="http://www.python.org/">Python</a> is a very capable language.  It is more consistent about its OO and syntax when compared to <a href="http://www.perl.org/">Perl</a>.  The python community is also a lot bigger on the use of common conventions.  This is mostly focused on formatting (one expression per line), in-line documentation and coding style in general.</p>
<p>Functions are first class types, you can assign a function to a variable, you can implement the equivalent of funcall and apply in python.  Functions can be passed as arguments.  Python supports positional parameters, default values for function params and calling functions, any function, with positional arguments, named arguments, a tuple of arguments (similar to funcall), or a dictionary (an indirect way of using named arguments).</p>
<p>Python actually has a lot of features which were inspired by functional programming (including one of my favorites: <a href="http://en.wikipedia.org/wiki/List_comprehension">list comprehensions</a>).</p>
<p>Python is byte-compiled, like Java.  You write code in a .py file, and the first time it is loaded as a module (import), python compiles the code for you.  The time stamp check of the .pyc vs the .py file is transparently handled by python &#8211; no explicit make or compile step.</p>
<p>Strings are immutable, which is something that helps <a href="http://www.jython.org/">Jython</a> be a natural fit in the <span class="caps">JVM</span>.</p>
<p>Python supports list destructuring, based on tuples.  It&#8217;s easier to show an example than to try to explain:</p>
<pre class="code">
  a, (b, c) = (1, (2, 3))

  print a,b,c =&gt; 1, 2, 3
</pre>
<p>Tuples, and this kind of binding syntax, are widely used in processing things like lists, and maps.</p>
<p>An interesting feature of the language is the pair of functions, local() and gobal().  local() returns a dictionary (Python&#8217;s name for a Map), of all of the variable bindings (and values) that are visible in the current scope (exclusive of global variables).  globals() returns the variables in the entire module&#8217;s scope (not local, lexical or class scope, and not global in the sense of a Perl global &#8211; not universally global).</p>
<h5>Other Highlights</h5>
<p>The <code>yield()</code> form, is like a weak kind of continuation.</p>
<p><code>for</code>, and <code>while</code> loops can have an else clause which is executed when the form does not execute.</p>
<p>The Python try/catch form (try/except/finally) can have an else form, again, which is executed if no exception was thrown in the try block.</p>
<h3>Introduction to Django</h3>
<p>After a break for lunch, both Andrew and I attended the Introduction to <a href="http://www.djangoproject.com/">Django</a>, presented by <a href="http://djangopeople.net/jacobian/">Jacob Kaplan-Moss</a>.</p>
<p>Django is an <span class="caps">MVC</span> framework for Python for rapid development of interactive web sites.  It is an <span class="caps">MVC</span> framework very much in the spirit of <a href="http://rubyonrails.org/">Ruby on Rails</a> &#8211; I&#8217;ve done some work in Rails and the parallels are very close between the two frameworks.</p>
<p>Django has a code generation framework, an <span class="caps">ORM</span> layer (which is very similar to Rails&#8217; ActiveRecord), an html template system (with a default syntax based on PHPs smarty template system), and integrated support for testing.</p>
<p>Django has an interesting testing feature called doctests.  If you&#8217;ve worked with an interactive language with a <span class="caps">REPL</span>, you have probably used it to explore the behavior of code and to informally test the code.  Doctests are a way of (almost literally) taking a cut and paste of the interactive session and vivifying the transcript as a regression test.  I like the idea of a recorded test, but as Andrew and I talked about it he convinced me that the literal representation wasn&#8217;t the best choice for implementing those kinds of tests. I do like the reduction of effort that comes with that kind of testing and recognize the inherent informality of it.</p>
<p>All that said, Django (like Rails) is big on doing test driven development.</p>
<p>I looked up the status of Django on Jython and apparently it&#8217;s close to being a 1.0 release (nothing I&#8217;d recommend for use at my employer at the moment, but <a href="http://www.sun.com/">Sun</a> has hired people to work on Jython and Django is one of the frameworks they are concerned with supporting).</p>
<p>I&#8217;m looking forward to tomorrow.</p>]]></content:encoded>
    </item>
    
    <item>
      <title>A Survey of Fuzzy String Matching Algorithms at Philly Lambda</title>
      <link>http://asymmetrical-view.com/2008/06/26/fuzzy-string.html</link>
      <comments>http://asymmetrical-view.com/2008/06/26/fuzzy-string.html#comments</comments>

      <pubDate>2008-06-26T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2008/06/26/fuzzy-string.html</guid>

      <id>http://asymmetrical-view.com/2008/06/26/fuzzy-string</id>
      <description><![CDATA[<h1>A Survey of Fuzzy String Matching Algorithms at Philly Lambda</h1>
<p>I&#8217;m giving my Survey of Fuzzy String Matching Algorithms talk tonight at <a href="http://groups.google.com/group/philly-lambda">Philly Lambda</a> hosted by <a href="http://www.algorithmics.com/EN/">Algorithmics</a>, See you at 7.</p>
<div style="width:425px;text-align:left" id="__ss_822817"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/kyleburton/fuzzy-string-matching?type=presentation" title="Fuzzy String Matching">Fuzzy String Matching</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=fuzzy-string-matching-7107&stripped_title=fuzzy-string-matching" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=fuzzy-string-matching-7107&stripped_title=fuzzy-string-matching" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/kyleburton">kyleburton</a>.</div></div>
<p class="meta">Kyle Burton, 25 Jun 2008 &#8211; Wayne PA</p>]]></description>
      <content:encoded><![CDATA[<h1>A Survey of Fuzzy String Matching Algorithms at Philly Lambda</h1>
<p>I&#8217;m giving my Survey of Fuzzy String Matching Algorithms talk tonight at <a href="http://groups.google.com/group/philly-lambda">Philly Lambda</a> hosted by <a href="http://www.algorithmics.com/EN/">Algorithmics</a>, See you at 7.</p>
<div style="width:425px;text-align:left" id="__ss_822817"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/kyleburton/fuzzy-string-matching?type=presentation" title="Fuzzy String Matching">Fuzzy String Matching</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=fuzzy-string-matching-7107&stripped_title=fuzzy-string-matching" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=fuzzy-string-matching-7107&stripped_title=fuzzy-string-matching" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/kyleburton">kyleburton</a>.</div></div>
<p class="meta">Kyle Burton, 25 Jun 2008 &#8211; Wayne PA</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Idempotency or Singleton Memoization in Perl</title>
      <link>http://asymmetrical-view.com/2008/06/18/idempotency-or-singleton-memoization.html</link>
      <comments>http://asymmetrical-view.com/2008/06/18/idempotency-or-singleton-memoization.html#comments</comments>

      <pubDate>2008-06-18T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2008/06/18/idempotency-or-singleton-memoization.html</guid>

      <id>http://asymmetrical-view.com/2008/06/18/idempotency-or-singleton-memoization</id>
      <description><![CDATA[<h1>Idempotency or Singleton Memoization in Perl</h1>
<p>This is an example of a factory for creating a function who&#8217;s body will only fire once, returning the first computed result each time it is invoked thereafter.</p>
<pre class="code">
sub makeDoOnce {
  my($sub) = @_;
  my $alreadyDone = undef;
  my @result      = undef;
  my $exception   = undef;
  return sub {
    die $exception if $exception;
    if ($alreadyDone) {return wantarray ? @result : $result[0];}

    eval {
      my $w = wantarray;
      if (not defined $w) {             $sub-&gt;(@_)}
      if ($w)             {@result    = $sub-&gt;(@_)}
      else                {$result[0] = $sub-&gt;(@_)}
    };
    $exception = $@ if $@;
    die $exception if $exception;
    $alreadyDone = 1;
    return wantarray ? @result : $result[0];
  };
}
</pre>
<p>This works by creating a <a href="http://en.wikipedia.org/wiki/Closure_(computer_science%29">closure</a> over the <code>$alreadyDone</code>, <code>@result</code> and <code>$exception</code> variables.  Within the returned sub, any exception is re-thrown, if the result was previously computed, it is returned.  If no exception or previous result was calculated, then the original function is invoked, storing off the exception or result and returning or throwing as appropriate.</p>
<p>An example usage is:</p>
<pre class="code">
  my $getStartTime = makeDoOnce(sub { time });
  print "We started at: ", scalar(localtime $getStartTime-&gt;()), "\n";
  sleep 5;
  print "We started at: ", scalar(localtime $getStartTime-&gt;()), "\n";
</pre>
<p>I often use this pattern for one-time initializations (loading plugin systems, ensuring file structures exist, etc), where I want the time of call to be flexible but the action it performs to happen only one time.</p>
<p class="meta">Kyle Burton, 18 Jun 2008 &#8211; Wayne PA</p>]]></description>
      <content:encoded><![CDATA[<h1>Idempotency or Singleton Memoization in Perl</h1>
<p>This is an example of a factory for creating a function who&#8217;s body will only fire once, returning the first computed result each time it is invoked thereafter.</p>
<pre class="code">
sub makeDoOnce {
  my($sub) = @_;
  my $alreadyDone = undef;
  my @result      = undef;
  my $exception   = undef;
  return sub {
    die $exception if $exception;
    if ($alreadyDone) {return wantarray ? @result : $result[0];}

    eval {
      my $w = wantarray;
      if (not defined $w) {             $sub-&gt;(@_)}
      if ($w)             {@result    = $sub-&gt;(@_)}
      else                {$result[0] = $sub-&gt;(@_)}
    };
    $exception = $@ if $@;
    die $exception if $exception;
    $alreadyDone = 1;
    return wantarray ? @result : $result[0];
  };
}
</pre>
<p>This works by creating a <a href="http://en.wikipedia.org/wiki/Closure_(computer_science%29">closure</a> over the <code>$alreadyDone</code>, <code>@result</code> and <code>$exception</code> variables.  Within the returned sub, any exception is re-thrown, if the result was previously computed, it is returned.  If no exception or previous result was calculated, then the original function is invoked, storing off the exception or result and returning or throwing as appropriate.</p>
<p>An example usage is:</p>
<pre class="code">
  my $getStartTime = makeDoOnce(sub { time });
  print "We started at: ", scalar(localtime $getStartTime-&gt;()), "\n";
  sleep 5;
  print "We started at: ", scalar(localtime $getStartTime-&gt;()), "\n";
</pre>
<p>I often use this pattern for one-time initializations (loading plugin systems, ensuring file structures exist, etc), where I want the time of call to be flexible but the action it performs to happen only one time.</p>
<p class="meta">Kyle Burton, 18 Jun 2008 &#8211; Wayne PA</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Basic Data Analysis at the Unix shell</title>
      <link>http://asymmetrical-view.com/2008/04/28/data-analysis-in-the-unix-shell.html</link>
      <comments>http://asymmetrical-view.com/2008/04/28/data-analysis-in-the-unix-shell.html#comments</comments>

      <pubDate>2008-04-28T00:00:00-04:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2008/04/28/data-analysis-in-the-unix-shell.html</guid>

      <id>http://asymmetrical-view.com/2008/04/28/data-analysis-in-the-unix-shell</id>
      <description><![CDATA[<h1>Basic Data Analysis at the Unix shell</h1>
<p>I often prefer the shell and Unix utilities to having to wait to load data into a relational database or MS Access.  There are plenty of cases when an <span class="caps">RDBMS</span> is a better choice &#8211; especially when what you&#8217;re doing requires joins.  At the shell it&#8217;s often possible to not even have to transform the encoding of the files before analyzing them.  I have developed a couple of recipes for doing some <span class="caps">SQL</span> equivalents at the shell.  These are a few that I just used so they&#8217;re fresh in my mind.  Most of the time all it takes is a bit of imagination about how to create a simple data-flow by learning and composing a small handful of the ubiquitous Unix utilities.</p>
<p>All these examples will also work within the <a href="http://www.cygwin.com/">Cygwin</a> environment for Windows, or at a Terminal in OS X (especially when combined with the additional software available via <a href="http://www.finkproject.org/">Fink</a> or <a href="http://www.macports.org/">Mac Ports</a> projects.</p>
<h3>Counting Records</h3>
<pre class="code">"SELECT COUNT(*) FROM TABLE"</pre>
<p>Just selecting the count of records from an input file is one of the easiest things to accomplish (if your file is already line-oriented). The <tt>wc</tt>, or word count, utility can do this easily.  By default it counts characters, words and lines.  With &#8216;-l&#8217; it will emit only the count of lines.</p>
<pre class="code">
  user@host:~/data$ wc -l table.tab
  10
</pre>
<p>If you want to ignore the header, start with the second line (see the next example for a more thorough explanation):</p>
<pre class="code">
  user@host:~/data$ tail -n +2 | table.tab
  9
</pre>
<h3>Counting Distinct Values from a Column</h3>
<pre class="code">"SELECT COUNT(DISTINCT(FIELD1)) FROM TABLE"</pre>
<p>For getting a distinct count of values in a column:</p>
<pre class="code">
  user@host:~/data$ cut -f1 table.tab | tail -n +2 | sort | uniq -c
</pre>
<p>This operations starts with the <tt>cut</tt> utility.  <tt>cut</tt>  allows you to take particular columns from a tab-delimited file, or character ranges from a fixed-width file.  <tt>cut</tt> also allows you to specify the delimiter &#8211; but be warned that the commonly encountered <span class="caps">CSV</span> format is more complex than <tt>cut</tt> can handle (<span class="caps">CSV</span> can support embedded delimiters and quote characters, which are beyond the scope of what <tt>cut</tt> attempts to handle).  The usage of <tt>cut</tt> takes the first column out of the input file.</p>
<p>The next part is the <tt>tail</tt> command.  <tt>tail</tt> outputs the end or &#8216;tail&#8217; of a file.  The &#8216;-n&#8217; option instructs <tt>tail</tt> to emit a specific number of lines (counted from the end of the file) when no &#8216;+&#8217; sign is present on the number.  The &#8216;+&#8217; tells <tt>tail</tt> to start at the second line from the beginning (in stead of from the end).  This effectively discards the header line.</p>
<p>Then the values from the first column themselves are sorted.  This is necessary for the <tt>uniq</tt> command, which will only collapse or count duplicate lines when they are adjacent.</p>
<p>Finally we reduce duplicate lines with <tt>uniq</tt>.  The &#8216;-c&#8217; tells <tt>uniq</tt> to emit the count of duplicates when collapsing them.</p>
<h3>Dealing with various file archive types</h3>
<p>I often work with files in zip archives and tar (unix tape archive) archives, sometimes with additional compression applied to them (.Z, unix compress; .gz, gzip; and .bz2, bzip).  It is possible to work with these files without having to unarchive or decompress them permanently if all you need is a simple count of lines or to only process them once.</p>
<h4>Pulling a file from a Zip Archive</h4>
<p>To pull one or more files from within a zip archive, and send them to another command (as part of a pipeline):</p>
<pre class="code">
  user@host:~/data$ unzip -l archive.zip
  Archive: archive.zip
    Length    Date   Time   Name
   --------   ----   ----   ----
        34  04-28-08 11:01  table1.tab
        56  04-28-08 11:01  table1.tab
  user@host:~/data$ unzip -c archive.zip table1.tab table2.tab | wc -l
  36
</pre>
<p>That example uses the <tt>unzip</tt> command to pull 2 files out and send them to standard output (the <tt>-c</tt> option to unzip instructs it to print the files to standard out rather than extract them to the file system).  Those two files were then sent to <tt>wc</tt> to get the combined line (record) count for the two files.  We don&#8217;t have to worry about cleaning up the two files after the command has completed since they were never written to disk.</p>
<p class="meta">Kyle Burton, 28 Apr 2008 &#8211; Wayne PA</p>]]></description>
      <content:encoded><![CDATA[<h1>Basic Data Analysis at the Unix shell</h1>
<p>I often prefer the shell and Unix utilities to having to wait to load data into a relational database or MS Access.  There are plenty of cases when an <span class="caps">RDBMS</span> is a better choice &#8211; especially when what you&#8217;re doing requires joins.  At the shell it&#8217;s often possible to not even have to transform the encoding of the files before analyzing them.  I have developed a couple of recipes for doing some <span class="caps">SQL</span> equivalents at the shell.  These are a few that I just used so they&#8217;re fresh in my mind.  Most of the time all it takes is a bit of imagination about how to create a simple data-flow by learning and composing a small handful of the ubiquitous Unix utilities.</p>
<p>All these examples will also work within the <a href="http://www.cygwin.com/">Cygwin</a> environment for Windows, or at a Terminal in OS X (especially when combined with the additional software available via <a href="http://www.finkproject.org/">Fink</a> or <a href="http://www.macports.org/">Mac Ports</a> projects.</p>
<h3>Counting Records</h3>
<pre class="code">"SELECT COUNT(*) FROM TABLE"</pre>
<p>Just selecting the count of records from an input file is one of the easiest things to accomplish (if your file is already line-oriented). The <tt>wc</tt>, or word count, utility can do this easily.  By default it counts characters, words and lines.  With &#8216;-l&#8217; it will emit only the count of lines.</p>
<pre class="code">
  user@host:~/data$ wc -l table.tab
  10
</pre>
<p>If you want to ignore the header, start with the second line (see the next example for a more thorough explanation):</p>
<pre class="code">
  user@host:~/data$ tail -n +2 | table.tab
  9
</pre>
<h3>Counting Distinct Values from a Column</h3>
<pre class="code">"SELECT COUNT(DISTINCT(FIELD1)) FROM TABLE"</pre>
<p>For getting a distinct count of values in a column:</p>
<pre class="code">
  user@host:~/data$ cut -f1 table.tab | tail -n +2 | sort | uniq -c
</pre>
<p>This operations starts with the <tt>cut</tt> utility.  <tt>cut</tt>  allows you to take particular columns from a tab-delimited file, or character ranges from a fixed-width file.  <tt>cut</tt> also allows you to specify the delimiter &#8211; but be warned that the commonly encountered <span class="caps">CSV</span> format is more complex than <tt>cut</tt> can handle (<span class="caps">CSV</span> can support embedded delimiters and quote characters, which are beyond the scope of what <tt>cut</tt> attempts to handle).  The usage of <tt>cut</tt> takes the first column out of the input file.</p>
<p>The next part is the <tt>tail</tt> command.  <tt>tail</tt> outputs the end or &#8216;tail&#8217; of a file.  The &#8216;-n&#8217; option instructs <tt>tail</tt> to emit a specific number of lines (counted from the end of the file) when no &#8216;+&#8217; sign is present on the number.  The &#8216;+&#8217; tells <tt>tail</tt> to start at the second line from the beginning (in stead of from the end).  This effectively discards the header line.</p>
<p>Then the values from the first column themselves are sorted.  This is necessary for the <tt>uniq</tt> command, which will only collapse or count duplicate lines when they are adjacent.</p>
<p>Finally we reduce duplicate lines with <tt>uniq</tt>.  The &#8216;-c&#8217; tells <tt>uniq</tt> to emit the count of duplicates when collapsing them.</p>
<h3>Dealing with various file archive types</h3>
<p>I often work with files in zip archives and tar (unix tape archive) archives, sometimes with additional compression applied to them (.Z, unix compress; .gz, gzip; and .bz2, bzip).  It is possible to work with these files without having to unarchive or decompress them permanently if all you need is a simple count of lines or to only process them once.</p>
<h4>Pulling a file from a Zip Archive</h4>
<p>To pull one or more files from within a zip archive, and send them to another command (as part of a pipeline):</p>
<pre class="code">
  user@host:~/data$ unzip -l archive.zip
  Archive: archive.zip
    Length    Date   Time   Name
   --------   ----   ----   ----
        34  04-28-08 11:01  table1.tab
        56  04-28-08 11:01  table1.tab
  user@host:~/data$ unzip -c archive.zip table1.tab table2.tab | wc -l
  36
</pre>
<p>That example uses the <tt>unzip</tt> command to pull 2 files out and send them to standard output (the <tt>-c</tt> option to unzip instructs it to print the files to standard out rather than extract them to the file system).  Those two files were then sent to <tt>wc</tt> to get the combined line (record) count for the two files.  We don&#8217;t have to worry about cleaning up the two files after the command has completed since they were never written to disk.</p>
<p class="meta">Kyle Burton, 28 Apr 2008 &#8211; Wayne PA</p>]]></content:encoded>
    </item>
    
    <item>
      <title>SRFI-26's cut macro</title>
      <link>http://asymmetrical-view.com/2008/01/30/srfi-26-s-cut-macro.html</link>
      <comments>http://asymmetrical-view.com/2008/01/30/srfi-26-s-cut-macro.html#comments</comments>

      <pubDate>2008-01-30T00:00:00-05:00</pubDate>
      <dc:creator>Kyle Burton</dc:creator>
      <!-- <category><![CDATA[Philly Lambda]]></category> -->
      <guid isPermaLink="false">http://asymmetrical-view.com/2008/01/30/srfi-26-s-cut-macro.html</guid>

      <id>http://asymmetrical-view.com/2008/01/30/srfi-26-s-cut-macro</id>
      <description><![CDATA[<h1><span class="caps">SRFI</span>-26&#8217;s cut macro</h1>
<p>I&#8217;m working on an <a href="http://asymmetrical-view.com/lisp-presentation/">introduction to lisp presentation</a> for <a href="http://www.phillylinux.org/west.html">Plug West</a>.  I&#8217;m trying to think through examples of macros which are a good demonstration of what they&#8217;re for.  Towards that end I picked Scheme&#8217;s srfi-26&#8217;s cut macro, which allows for specialization of argument, and try to extend it in a couple of ways.  Below is the example code, including a simplified cut, a recursive (or tree) cut, and a pattern cut (which allows the cut points to be named).</p>
<pre class="code">
  ;; the scheme cut macro...srfi-26, when written as:
  ;;
  ;;  (cut #'format "~a~&amp;" &lt;&gt;)
  ;;
  ;; it produces:
  ;;
  ;; =&gt; #'(lambda (x) (format "~a~&amp;" x))
  ;;
  ;; 'Lifting' the '&lt;&gt;' out of the form as an argument to the generated lambda.
  ;; It's 'flat' though, it'd be nice to have something which could work
  ;; on any form...a recursive cut, which is what we'll write, first a helper:
  
  (defmacro aprog1 (it &amp;rest body)
    "Anaphoric prog1, returns the value of the first expression,
  executing all subsequent expressions for their side effects.  It binds
  the symbol 'it' to the result of the first expression.  This can also
  be seen as a 'construct and initialize' pattern.
  
    (aprog1
      (make-hash-table :test #'equal)
      (setf (gethash \"a\" it) 1)
      (setf (gethash \"b\" it) 2)
      (setf (gethash \"c\" it) 3))
    =&gt; #&lt;HASH-TABLE :TEST EQUAL :COUNT 3 {BE49831}&gt;
  
  "
    `(let ((it ,it))
       ,@body
       it))
  
  (defmacro cut (fn &amp;rest body)
    "srfi-26's cut in Common Lisp, some examples:

  (cut #'cons (+ a 1) &lt;&gt;) is the same as (lambda (x2) (cons (+ a 1) x2))
  (cut #'list 1 &lt;&gt; 3 &lt;&gt; 5) is the same as (lambda (x2 x4) (list 1 x2 3 x4 5))
  (cut #'list) is the same as (lambda () (list))
  (cut #'list 1 &lt;&gt; 3 &lt;...&gt;) is the same as (lambda (x2 . xs) (apply list 1 x2 3 xs))
  
  The following form is not supported in this version:

    (cut &lt;&gt; a b) is the same as (lambda (f) (f a b))

  Scheme does that simply by virte that it is a Lisp-1, I didn't go through the
  effort of doing the check. "
    (let* ((formals (list))
           (new-body
            (mapcar #'(lambda (item)
                        (if (equal '&lt;&gt; item)
                            (aprog1
                             (gensym)
                             (push it formals)
                             it)
                            item))
                    body)))
      `#'(lambda ,(reverse formals)
           (funcall ,fn ,@new-body))))

  ;; lets take a look at an expansion and try a couple of examples  
  ;; (macroexpand-1 '(cut #'format t "~a: ~a~&amp;" "thing" &lt;&gt;))
  ;; (funcall (cut #'format t "~a: ~a~&amp;" "thing" &lt;&gt;) 10)
  ;; (funcall (cut #'format t "~a: ~a~&amp;" &lt;&gt; &lt;&gt;) "thing" 10)

  ;; Our next helper, the visitor pattern, invoke the function 
  ;; on each non-branch (leaf node) element in the tree, replacing
  ;; the existing value with fn's result.  NB: this is a depth first 
  ;; search.
  (defun map-tree (fn tree)
    (cond ((null tree)
           tree)
          ((not (listp tree))
           (funcall fn tree))
          (t
           (mapcar #'(lambda (elt) (map-tree fn elt)) tree))))
  
  ;; test it out, this should increment each number in the tree:
  ;; (map-tree #'(lambda (elt) (format t "x:~a~&amp;" elt) (1+ elt)) '(1 2 (3 4 (5 6 (7)))))
  
  ;; With those tools we can enhance cut to use map-tree instead of map, providing
  ;; the recursive search for cut points.
  (defmacro rcut (&amp;rest body)
    (let* ((formals (list))
           (new-body
            (map-tree #'(lambda (elt)
                          (if (equalp '&lt;&gt; elt)
                              (aprog1
                               (gensym)
                               (push it formals)
                               it)
                              elt))
                      body)))
      `#'(lambda ,(reverse formals)
           ,@new-body)))
  
  ;; see what it expands to
  (macroexpand-1
   '(rcut
     (cond ((&gt; &lt;&gt; 1)
            (format t "first arg was &gt;1, second arg is: ~a~&amp;" &lt;&gt;))
           (t
            (format t "first arg was &lt;1, third arg is: ~a~&amp;" &lt;&gt;)))))
  

  ;; test out the resulting function  
  (let ((fn
         (rcut
          (cond ((&gt; &lt;&gt; 1)
                 (format t "first arg was &gt;1, second arg is: ~a~&amp;" &lt;&gt;))
                (t
                 (format t "first arg was &lt;1, third arg is: ~a~&amp;" &lt;&gt;))))))
    (funcall fn 1/2 'a 'b)
    (funcall fn 2/1 'a 'b))
  
  
  
  
  ;; that's all well and good, but the whole depth first ordering can
  ;; be hard to think through with respect to how it maps to the
  ;; ordering of the function arguments.  What we want to try next
  ;; is pcut (pattern cut), for example:
  ;; 
  ;;    (pcut
  ;;      (cond ((&gt; ?fst 1)
  ;;             (format t "first arg (~a) was &gt;1, x is: ~a~&amp;" ?fst ?x))
  ;;            (t
  ;;             (format t "first arg (~a) was &lt;1, x is: ~a, y is:~a~&amp;" ?fst ?x ?y)))
  ;;
  ;; The ordering still mattes, it's still depth-first, but now we can re-use arguments by 
  ;; name, without inventing new locals.

  ;; Helper predicate to see if we have a cut pattern symbol  
  (defun starts-with-? (sym)
    (equal "?"  (subseq (format nil "~a" sym) 0 1)))
  
  ;; the main difference here is DRY (don't repeat yourself, 
  ;; only capture each named binding once), and use the #'starts-with-? 
  ;; predicate instead of the equality test (#'equalp).
  (defmacro pcut (&amp;rest body)
    (let* ((formals (list))
           (fml-hash (make-hash-table :test #'equal))
           (new-body
            (map-tree #'(lambda (elt)
                          (if (starts-with-? elt)
                              (aprog1
                               (or (gethash elt fml-hash)
                                   (aprog1
                                    (gensym)
                                    (push it formals)
                                    (setf (gethash elt fml-hash) it)
                                    it))
                               it)
                              elt))
                      body)))
      `#'(lambda ,(reverse formals)
           ,@new-body)))

  ;; take a look at the expansion
  (macroexpand-1
   '(pcut
          (cond ((&gt; ?fst 1)
                 (format t "first arg (~a) was &gt;1, x is: ~a~&amp;" ?fst ?x))
                (t
                 (format t "first arg (~a) was &lt;1, x is: ~a, y is:~a~&amp;" ?fst ?x ?y)))))
    
  ;; test out the expansion
  (let ((fn (pcut
             (cond ((&gt; ?fst 1)
                    (format t "first arg (~a) was &gt;1, x is: ~a~&amp;" ?fst ?x))
                   (t
                    (format t "first arg (~a) was &lt;1, x is: ~a, y is:~a~&amp;" ?fst ?x ?y))))))
    (funcall fn 1/2 'a 'b)
    (funcall fn 2/1 'a 'b))
</pre>
<h3>Conclusion</h3>
<p>Hopefully these are useful pedagalogical examples of macros in Common Lisp.</p>
<p class="meta">Kyle Burton, 30 Jan 2008 &#8211; Wayne PA</p>]]></description>
      <content:encoded><![CDATA[<h1><span class="caps">SRFI</span>-26&#8217;s cut macro</h1>
<p>I&#8217;m working on an <a href="http://asymmetrical-view.com/lisp-presentation/">introduction to lisp presentation</a> for <a href="http://www.phillylinux.org/west.html">Plug West</a>.  I&#8217;m trying to think through examples of macros which are a good demonstration of what they&#8217;re for.  Towards that end I picked Scheme&#8217;s srfi-26&#8217;s cut macro, which allows for specialization of argument, and try to extend it in a couple of ways.  Below is the example code, including a simplified cut, a recursive (or tree) cut, and a pattern cut (which allows the cut points to be named).</p>
<pre class="code">
  ;; the scheme cut macro...srfi-26, when written as:
  ;;
  ;;  (cut #'format "~a~&amp;" &lt;&gt;)
  ;;
  ;; it produces:
  ;;
  ;; =&gt; #'(lambda (x) (format "~a~&amp;" x))
  ;;
  ;; 'Lifting' the '&lt;&gt;' out of the form as an argument to the generated lambda.
  ;; It's 'flat' though, it'd be nice to have something which could work
  ;; on any form...a recursive cut, which is what we'll write, first a helper:
  
  (defmacro aprog1 (it &amp;rest body)
    "Anaphoric prog1, returns the value of the first expression,
  executing all subsequent expressions for their side effects.  It binds
  the symbol 'it' to the result of the first expression.  This can also
  be seen as a 'construct and initialize' pattern.
  
    (aprog1
      (make-hash-table :test #'equal)
      (setf (gethash \"a\" it) 1)
      (setf (gethash \"b\" it) 2)
      (setf (gethash \"c\" it) 3))
    =&gt; #&lt;HASH-TABLE :TEST EQUAL :COUNT 3 {BE49831}&gt;
  
  "
    `(let ((it ,it))
       ,@body
       it))
  
  (defmacro cut (fn &amp;rest body)
    "srfi-26's cut in Common Lisp, some examples:

  (cut #'cons (+ a 1) &lt;&gt;) is the same as (lambda (x2) (cons (+ a 1) x2))
  (cut #'list 1 &lt;&gt; 3 &lt;&gt; 5) is the same as (lambda (x2 x4) (list 1 x2 3 x4 5))
  (cut #'list) is the same as (lambda () (list))
  (cut #'list 1 &lt;&gt; 3 &lt;...&gt;) is the same as (lambda (x2 . xs) (apply list 1 x2 3 xs))
  
  The following form is not supported in this version:

    (cut &lt;&gt; a b) is the same as (lambda (f) (f a b))

  Scheme does that simply by virte that it is a Lisp-1, I didn't go through the
  effort of doing the check. "
    (let* ((formals (list))
           (new-body
            (mapcar #'(lambda (item)
                        (if (equal '&lt;&gt; item)
                            (aprog1
                             (gensym)
                             (push it formals)
                             it)
                            item))
                    body)))
      `#'(lambda ,(reverse formals)
           (funcall ,fn ,@new-body))))

  ;; lets take a look at an expansion and try a couple of examples  
  ;; (macroexpand-1 '(cut #'format t "~a: ~a~&amp;" "thing" &lt;&gt;))
  ;; (funcall (cut #'format t "~a: ~a~&amp;" "thing" &lt;&gt;) 10)
  ;; (funcall (cut #'format t "~a: ~a~&amp;" &lt;&gt; &lt;&gt;) "thing" 10)

  ;; Our next helper, the visitor pattern, invoke the function 
  ;; on each non-branch (leaf node) element in the tree, replacing
  ;; the existing value with fn's result.  NB: this is a depth first 
  ;; search.
  (defun map-tree (fn tree)
    (cond ((null tree)
           tree)
          ((not (listp tree))
           (funcall fn tree))
          (t
           (mapcar #'(lambda (elt) (map-tree fn elt)) tree))))
  
  ;; test it out, this should increment each number in the tree:
  ;; (map-tree #'(lambda (elt) (format t "x:~a~&amp;" elt) (1+ elt)) '(1 2 (3 4 (5 6 (7)))))
  
  ;; With those tools we can enhance cut to use map-tree instead of map, providing
  ;; the recursive search for cut points.
  (defmacro rcut (&amp;rest body)
    (let* ((formals (list))
           (new-body
            (map-tree #'(lambda (elt)
                          (if (equalp '&lt;&gt; elt)
                              (aprog1
                               (gensym)
                               (push it formals)
                               it)
                              elt))
                      body)))
      `#'(lambda ,(reverse formals)
           ,@new-body)))
  
  ;; see what it expands to
  (macroexpand-1
   '(rcut
     (cond ((&gt; &lt;&gt; 1)
            (format t "first arg was &gt;1, second arg is: ~a~&amp;" &lt;&gt;))
           (t
            (format t "first arg was &lt;1, third arg is: ~a~&amp;" &lt;&gt;)))))
  

  ;; test out the resulting function  
  (let ((fn
         (rcut
          (cond ((&gt; &lt;&gt; 1)
                 (format t "first arg was &gt;1, second arg is: ~a~&amp;" &lt;&gt;))
                (t
                 (format t "first arg was &lt;1, third arg is: ~a~&amp;" &lt;&gt;))))))
    (funcall fn 1/2 'a 'b)
    (funcall fn 2/1 'a 'b))
  
  
  
  
  ;; that's all well and good, but the whole depth first ordering can
  ;; be hard to think through with respect to how it maps to the
  ;; ordering of the function arguments.  What we want to try next
  ;; is pcut (pattern cut), for example:
  ;; 
  ;;    (pcut
  ;;      (cond ((&gt; ?fst 1)
  ;;             (format t "first arg (~a) was &gt;1, x is: ~a~&amp;" ?fst ?x))
  ;;            (t
  ;;             (format t "first arg (~a) was &lt;1, x is: ~a, y is:~a~&amp;" ?fst ?x ?y)))
  ;;
  ;; The ordering still mattes, it's still depth-first, but now we can re-use arguments by 
  ;; name, without inventing new locals.

  ;; Helper predicate to see if we have a cut pattern symbol  
  (defun starts-with-? (sym)
    (equal "?"  (subseq (format nil "~a" sym) 0 1)))
  
  ;; the main difference here is DRY (don't repeat yourself, 
  ;; only capture each named binding once), and use the #'starts-with-? 
  ;; predicate instead of the equality test (#'equalp).
  (defmacro pcut (&amp;rest body)
    (let* ((formals (list))
           (fml-hash (make-hash-table :test #'equal))
           (new-body
            (map-tree #'(lambda (elt)
                          (if (starts-with-? elt)
                              (aprog1
                               (or (gethash elt fml-hash)
                                   (aprog1
                                    (gensym)
                                    (push it formals)
                                    (setf (gethash elt fml-hash) it)
                                    it))
                               it)
                              elt))
                      body)))
      `#'(lambda ,(reverse formals)
           ,@new-body)))

  ;; take a look at the expansion
  (macroexpand-1
   '(pcut
          (cond ((&gt; ?fst 1)
                 (format t "first arg (~a) was &gt;1, x is: ~a~&amp;" ?fst ?x))
                (t
                 (format t "first arg (~a) was &lt;1, x is: ~a, y is:~a~&amp;" ?fst ?x ?y)))))
    
  ;; test out the expansion
  (let ((fn (pcut
             (cond ((&gt; ?fst 1)
                    (format t "first arg (~a) was &gt;1, x is: ~a~&amp;" ?fst ?x))
                   (t
                    (format t "first arg (~a) was &lt;1, x is: ~a, y is:~a~&amp;" ?fst ?x ?y))))))
    (funcall fn 1/2 'a 'b)
    (funcall fn 2/1 'a 'b))
</pre>
<h3>Conclusion</h3>
<p>Hopefully these are useful pedagalogical examples of macros in Common Lisp.</p>
<p class="meta">Kyle Burton, 30 Jan 2008 &#8211; Wayne PA</p>]]></content:encoded>
    </item>
    
  </channel>

</rss>

