<?xml version="1.0"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>The Zero Bit Stream</title>
    <link>http://blog.thezerobit.com/</link>
    <atom:link href="http://blog.thezerobit.com/rss.xml" rel="self" type="application/rss+xml" />
    <description>A blog by Stephen A. Goss.</description>
    <language>en-us</language>
    <pubDate>Sat, 08 Sep 2012 10:27:30 -0700</pubDate>
    <lastBuildDate>Sat, 08 Sep 2012 10:27:30 -0700</lastBuildDate>

    
    <item>
      <title>Beautiful Quicksort in Common Lisp</title>
      <link>http://blog.thezerobit.com/2012/09/01/beautiful-quicksort-in-common-lisp.html</link>
      <pubDate>Sat, 01 Sep 2012 00:00:00 -0700</pubDate>
      <author>steveth45@gmail.com (Stephen A. Goss)</author>
      <guid isPermaLink="true">http://blog.thezerobit.com/2012/09/01/beautiful-quicksort-in-common-lisp.html</guid>
      <category>programming</category>
      <category>lisp</category>
      <category>common-lisp</category>
      <category>haskell</category>
      
      <description>&lt;p&gt;Pre-disclaimer. Angry Haskell nerds: please go away, I didn&amp;#8217;t write this for you. This isn&amp;#8217;t a X is better than Y piece, just a friendly comparison and maybe a tool to help people understand some functional programming concepts better.&lt;/p&gt;

&lt;p&gt;Second pre-disclaimer. This is Quicksort, just not one you&amp;#8217;d use in production. You can see it does twice as many comparisons as necessary, or much worse if it encounters a pre-sorted list. The list manipulation (via ++ or APPEND) is doing more work and using more memory than necessary, even for a purely functional implementation.&lt;/p&gt;

&lt;h2 id='beautiful_quicksort_in_common_lisp'&gt;Beautiful Quicksort in Common Lisp&lt;/h2&gt;

&lt;h3 id='quicksort_in_haskell_vs_common_lisp'&gt;Quicksort in Haskell vs. Common Lisp&lt;/h3&gt;

&lt;p&gt;Haskell apologists often cite how Haskell code is terse and expressive. I&amp;#8217;ve used Haskell a bit, and while I do not find its syntax very friendly, it is quite powerful. (As a side note, I really like Standard ML, and I wish I could transplant its eagerness and impurity into Haskell.) Common Lisp is a master of multi-paradigm programming and it wears the functional hat pretty well, too. So, let&amp;#8217;s see how it stands up against Haskell.&lt;/p&gt;

&lt;p&gt;The canonical &amp;#8220;beautiful&amp;#8221; Haskell function is the quicksort. Here it is:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='haskell'&gt;&lt;span class='nf'&gt;quicksort&lt;/span&gt; &lt;span class='ow'&gt;::&lt;/span&gt; &lt;span class='kt'&gt;Ord&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='ow'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='ow'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
&lt;span class='nf'&gt;quicksort&lt;/span&gt; &lt;span class='kt'&gt;[]&lt;/span&gt;     &lt;span class='ow'&gt;=&lt;/span&gt; &lt;span class='kt'&gt;[]&lt;/span&gt;
&lt;span class='nf'&gt;quicksort&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='kt'&gt;:&lt;/span&gt;&lt;span class='n'&gt;xs&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ow'&gt;=&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;quicksort&lt;/span&gt; &lt;span class='n'&gt;lesser&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;++&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;++&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;quicksort&lt;/span&gt; &lt;span class='n'&gt;greater&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='kr'&gt;where&lt;/span&gt;
        &lt;span class='n'&gt;lesser&lt;/span&gt;  &lt;span class='ow'&gt;=&lt;/span&gt; &lt;span class='n'&gt;filter&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='n'&gt;xs&lt;/span&gt;
        &lt;span class='n'&gt;greater&lt;/span&gt; &lt;span class='ow'&gt;=&lt;/span&gt; &lt;span class='n'&gt;filter&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;=&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='n'&gt;xs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I gotta admit, that&amp;#8217;s a pretty good one. Let&amp;#8217;s see what it looks like in Common Lisp.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defun&lt;/span&gt; &lt;span class='nv'&gt;quicksort&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;when&lt;/span&gt; &lt;span class='nb'&gt;list&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;destructuring-bind&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;p&lt;/span&gt; &lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='nv'&gt;xs&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nb'&gt;list&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;lesser&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;remove-if-not&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;lambda&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;&amp;lt;&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;p&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='nv'&gt;xs&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
            &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;greater&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;remove-if-not&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;lambda&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;&amp;gt;=&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;p&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='nv'&gt;xs&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
        &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;append&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;quicksort&lt;/span&gt; &lt;span class='nv'&gt;lesser&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='nv'&gt;p&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;quicksort&lt;/span&gt; &lt;span class='nv'&gt;greater&lt;/span&gt;&lt;span class='p'&gt;))))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I probably wouldn&amp;#8217;t write it this way, but this is the closest approximation of what the Haskell function is doing. Let&amp;#8217;s break it down into pieces and show which parts correspond in the two examples.&lt;/p&gt;

&lt;p&gt;The Haskell code is using pattern matching to deal with the empty list case, and destructuring to split the list into head and tail.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='haskell'&gt;&lt;span class='nf'&gt;quicksort&lt;/span&gt; &lt;span class='kt'&gt;[]&lt;/span&gt;     &lt;span class='ow'&gt;=&lt;/span&gt; &lt;span class='kt'&gt;[]&lt;/span&gt;
&lt;span class='nf'&gt;quicksort&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='kt'&gt;:&lt;/span&gt;&lt;span class='n'&gt;xs&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ow'&gt;=&lt;/span&gt; &lt;span class='n'&gt;expr&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The Common Lisp code is using WHEN on the input (which returns NIL for an empty list and otherwise evaluates the expression) and is using DESTRUCTURING-BIND to split the list into head and tail.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;when&lt;/span&gt; &lt;span class='nb'&gt;list&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;destructuring-bind&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;p&lt;/span&gt; &lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='nv'&gt;xs&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nb'&gt;list&lt;/span&gt;
    &lt;span class='nv'&gt;expr&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Haskell uses &amp;#8220;where&amp;#8221; to bind local variable in an expression:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='haskell'&gt;&lt;span class='o'&gt;...&lt;/span&gt; &lt;span class='ow'&gt;=&lt;/span&gt; &lt;span class='n'&gt;expr&lt;/span&gt;
    &lt;span class='kr'&gt;where&lt;/span&gt;
        &lt;span class='n'&gt;binding_a&lt;/span&gt; &lt;span class='ow'&gt;=&lt;/span&gt; &lt;span class='n'&gt;expr_a&lt;/span&gt;
        &lt;span class='n'&gt;binding_b&lt;/span&gt; &lt;span class='ow'&gt;=&lt;/span&gt; &lt;span class='n'&gt;expr_b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Common Lisp uses LET to bind local variables in an expression:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;binding-a&lt;/span&gt; &lt;span class='nv'&gt;expr-a&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;binding-b&lt;/span&gt; &lt;span class='nv'&gt;expr-b&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='nv'&gt;expr&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Haskell uses partial application of the comparison functions with &amp;#8220;filter&amp;#8221; to filter the lists.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='haskell'&gt;&lt;span class='nf'&gt;lesser&lt;/span&gt;  &lt;span class='ow'&gt;=&lt;/span&gt; &lt;span class='n'&gt;filter&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='n'&gt;xs&lt;/span&gt;
&lt;span class='nf'&gt;greater&lt;/span&gt; &lt;span class='ow'&gt;=&lt;/span&gt; &lt;span class='n'&gt;filter&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;=&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='n'&gt;xs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Common Lisp uses lambdas to construct the filtering closures and REMOVE-IF-NOT which is essentially equivalent to Haskell&amp;#8217;s &amp;#8220;filter&amp;#8221;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lesser&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;remove-if-not&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;lambda&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;&amp;lt;&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;p&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='nv'&gt;xs&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;greater&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;remove-if-not&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;lambda&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;&amp;gt;=&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;p&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='nv'&gt;xs&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='even_terser'&gt;Even Terser&lt;/h3&gt;

&lt;p&gt;OK, but there&amp;#8217;s an even shorter, one-line Haskell quicksort.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='haskell'&gt;&lt;span class='nf'&gt;qsort&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='kt'&gt;:&lt;/span&gt;&lt;span class='n'&gt;xs&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ow'&gt;=&lt;/span&gt; &lt;span class='n'&gt;qsort&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='ow'&gt;&amp;lt;-&lt;/span&gt;&lt;span class='n'&gt;xs&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;++&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;++&lt;/span&gt; &lt;span class='n'&gt;qsort&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='ow'&gt;&amp;lt;-&lt;/span&gt;&lt;span class='n'&gt;xs&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;=&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Let&amp;#8217;s ignore for now the fact that using 1 and 2 letter variables is a very silly way to write &amp;#8220;shorter&amp;#8221; code. What&amp;#8217;s great about this solution, though, is the use of list comprehensions. Common Lisp doesn&amp;#8217;t have list comprehensions, but it doesn&amp;#8217;t matter because it has mother-flipping macros, and we can add list comprehensions.&lt;/p&gt;

&lt;p&gt;Now, I could pull in a library that gives list comprehensions, but wouldn&amp;#8217;t it be funner to write the macro right here?&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m not going to build a general replacement for all Haskell list comprehensions, just the ones here. I see 4 parts, the value, a binding, a list, and a test. Here&amp;#8217;s my first shot at a list comprehension macro:&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defmacro&lt;/span&gt; &lt;span class='nv'&gt;@&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;value&lt;/span&gt; &lt;span class='nv'&gt;bind&lt;/span&gt; &lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='nv'&gt;test&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;newlist&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;gensym&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
    &lt;span class='o'&gt;`&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='nv'&gt;newlist&lt;/span&gt; &lt;span class='no'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
       &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;dolist&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='nv'&gt;bind&lt;/span&gt; &lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
         &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;when&lt;/span&gt; &lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='nv'&gt;test&lt;/span&gt;
           &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;push&lt;/span&gt; &lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='nv'&gt;value&lt;/span&gt; &lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='nv'&gt;newlist&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
       &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;nreverse&lt;/span&gt; &lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='nv'&gt;newlist&lt;/span&gt;&lt;span class='p'&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;I selected the @ symbol because it&amp;#8217;s short and sweet, and mainly just short. The Haskell folks seem to think 1-letter names are the bees knees, so there you go. A quick test:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='c1'&gt;;; Something like this in Haskell: [x*2 | x&amp;lt;-[1, 2, 3, 4, 5, 6, 7], x&amp;gt;3]&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;@&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;*&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt; &lt;span class='mi'&gt;5&lt;/span&gt; &lt;span class='mi'&gt;6&lt;/span&gt; &lt;span class='mi'&gt;7&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;-&amp;gt; (8 10 12 14)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In case you don&amp;#8217;t know how DEFMACRO works, it takes the input forms, unevaluated and returns a list which is evaluated it its place. You can debug macros to see the intermediate form by just doing the transformation with MACROEXPAND:&lt;/p&gt;

&lt;p&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;macroexpand&lt;/span&gt; &lt;span class='o'&gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;@&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;*&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt; &lt;span class='mi'&gt;5&lt;/span&gt; &lt;span class='mi'&gt;6&lt;/span&gt; &lt;span class='mi'&gt;7&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;LET&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='ss'&gt;#:G791&lt;/span&gt; &lt;span class='no'&gt;NIL&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;DOLIST&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;X&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;LIST&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt; &lt;span class='mi'&gt;5&lt;/span&gt; &lt;span class='mi'&gt;6&lt;/span&gt; &lt;span class='mi'&gt;7&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;WHEN&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;&amp;gt;&lt;/span&gt; &lt;span class='nv'&gt;X&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;PUSH&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;*&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='nv'&gt;X&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;#:G791&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;NREVERSE&lt;/span&gt; &lt;span class='ss'&gt;#:G791&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;Alright, armed with our new list comprehension macro, let&amp;#8217;s write our super-short quicksort:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defun&lt;/span&gt; &lt;span class='nv'&gt;qsort&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;l&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;when&lt;/span&gt; &lt;span class='nv'&gt;l&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;destructuring-bind&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;p&lt;/span&gt; &lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='nv'&gt;xs&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nv'&gt;l&lt;/span&gt;
            &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;append&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;qsort&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;@&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;xs&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;&amp;lt;&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;p&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='nv'&gt;p&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
                    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;qsort&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;@&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;xs&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;&amp;gt;=&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;p&lt;/span&gt;&lt;span class='p'&gt;)))))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;That&amp;#8217;s pretty good. I still have to use WHEN to deal with the null case which Haskell seems to auto-magically handle, and I still have to use DESTRUCTURING-BIND explicitly. I think it holds up to Haskell&amp;#8217;s qsort.&lt;/p&gt;

&lt;h3 id='more_generic'&gt;More Generic&lt;/h3&gt;

&lt;p&gt;Oh, I know, the Haskell qsort function applies to lists of any Ord type, which is to say, any type that can be ordered (or at least implements the proper interface) (disclaimer: I don&amp;#8217;t pretend to know Haskell-speak when it comes to Classes, Types, Typeclasses, etc. I got it wrong, I don&amp;#8217;t care.). Common Lisp ships with CLOS which provides the ability to create generic methods, but it doesn&amp;#8217;t really ship with many implemented interfaces. That could be considered a shortcoming in the language, but more properly, it is a shortcoming in libraries. You can easily define generic methods and implement them on all the types you might want to sort, even types from other packages and libraries.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defgeneric&lt;/span&gt; &lt;span class='nv'&gt;lt&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;some&lt;/span&gt; &lt;span class='nv'&gt;other&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defmethod&lt;/span&gt; &lt;span class='nv'&gt;lt&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nb'&gt;some&lt;/span&gt; &lt;span class='nc'&gt;number&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;other&lt;/span&gt; &lt;span class='nc'&gt;number&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;&amp;lt;&lt;/span&gt; &lt;span class='nb'&gt;some&lt;/span&gt; &lt;span class='nv'&gt;other&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defmethod&lt;/span&gt; &lt;span class='nv'&gt;lt&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nb'&gt;some&lt;/span&gt; &lt;span class='nb'&gt;string&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;other&lt;/span&gt; &lt;span class='nb'&gt;string&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;string&amp;lt;&lt;/span&gt; &lt;span class='nb'&gt;some&lt;/span&gt; &lt;span class='nv'&gt;other&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defun&lt;/span&gt; &lt;span class='nv'&gt;qsort&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;l&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;when&lt;/span&gt; &lt;span class='nv'&gt;l&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;destructuring-bind&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;p&lt;/span&gt; &lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='nv'&gt;xs&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nv'&gt;l&lt;/span&gt;
            &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;append&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;qsort&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;@&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;xs&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lt&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;p&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='nv'&gt;p&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
                    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;qsort&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;@&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;xs&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;not&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lt&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='nv'&gt;p&lt;/span&gt;&lt;span class='p'&gt;))))))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;qsort&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;this&amp;quot;&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;is&amp;quot;&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;only&amp;quot;&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;a&amp;quot;&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;test&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;-&amp;gt; (&amp;quot;a&amp;quot; &amp;quot;is&amp;quot; &amp;quot;only&amp;quot; &amp;quot;test&amp;quot; &amp;quot;this&amp;quot;)&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;qsort&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='m'&gt;12/11&lt;/span&gt; &lt;span class='mf'&gt;-1.09&lt;/span&gt; &lt;span class='mi'&gt;3000&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;-&amp;gt; (-1.09 12/11 3000)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So we can be significantly generic with Common Lisp, too. No, it doesn&amp;#8217;t have Haskell&amp;#8217;s compile time type-checking goodness (or badness, however you want to slice it), it is a fundamentally dynamically typed language. But I think it matches Haskell in expressivity, and what it lacks in terse syntax, it makes up for with flexibility through macros, generic methods, and dynamism.&lt;/p&gt;

&lt;p&gt;In conclusion: I love Haskell, please don&amp;#8217;t shoot me. Also, Common Lisp is pretty neat, too. Both are definitely worth learning and excellent tools for functional programming.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Concurrency in Common Lisp with ChanL</title>
      <link>http://blog.thezerobit.com/2012/08/26/concurrency-in-common-lisp-with-chanl.html</link>
      <pubDate>Sun, 26 Aug 2012 00:00:00 -0700</pubDate>
      <author>steveth45@gmail.com (Stephen A. Goss)</author>
      <guid isPermaLink="true">http://blog.thezerobit.com/2012/08/26/concurrency-in-common-lisp-with-chanl.html</guid>
      <category>programming</category>
      <category>lisp</category>
      <category>common-lisp</category>
      <category>concurrency</category>
      
      <description>&lt;h2 id='concurrency_in_common_lisp_with_chanl'&gt;Concurrency in Common Lisp with ChanL&lt;/h2&gt;

&lt;p&gt;Rob Pike did a great &lt;a href='http://www.youtube.com/watch?v=HmxnCEa8Ctw'&gt;talk&lt;/a&gt; at Google on concurrency in Newsqueak. The gist of it is that you spawn concurrent tasks in separate lightweight processes and synchronize by communicating through channels. That stuff worked its way into the programming language Go. After seeing that video I wanted to try it out myself in Common Lisp, of course. It turns out there is a Quicklisp-installable library called &lt;a href='https://github.com/sykopomp/chanl'&gt;ChanL&lt;/a&gt; that provides just that functionality. I don&amp;#8217;t know how lightweight the threads are, but the interface is similar.&lt;/p&gt;

&lt;p&gt;A simple, but effective example of using channels is to perform a number of IO-bound tasks in parallel, such as retrieving several web pages. It&amp;#8217;s surprisingly simple to do in parallel. To start, I&amp;#8217;ll define a little timing macro:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defmacro&lt;/span&gt; &lt;span class='nv'&gt;time-it&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;&amp;amp;body&lt;/span&gt; &lt;span class='nv'&gt;body&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;start-time&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;gensym&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
    &lt;span class='o'&gt;`&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='nv'&gt;start-time&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;get-internal-real-time&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
       &lt;span class='o'&gt;,@&lt;/span&gt;&lt;span class='nv'&gt;body&lt;/span&gt;
       &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;format&lt;/span&gt; &lt;span class='no'&gt;t&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;Runtime: ~a milliseconds.~%&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;-&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;get-internal-real-time&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='nv'&gt;start-time&lt;/span&gt;&lt;span class='p'&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then, let&amp;#8217;s load the ChanL library and Drakma (for simple HTTP requests) using quicklisp:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;ql:quickload&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;drakma&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;ql:quickload&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;chanl&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Our example set of URLs:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defparameter&lt;/span&gt; &lt;span class='vg'&gt;*urls*&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt;
    &lt;span class='s'&gt;&amp;quot;http://blog.thezerobit.com/&amp;quot;&lt;/span&gt;
    &lt;span class='s'&gt;&amp;quot;http://quicklisp.org/&amp;quot;&lt;/span&gt;
    &lt;span class='s'&gt;&amp;quot;http://www.cliki.net/index&amp;quot;&lt;/span&gt;
    &lt;span class='s'&gt;&amp;quot;http://sbcl.org/&amp;quot;&lt;/span&gt;
    &lt;span class='p'&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now, here&amp;#8217;s a function that performs a single HTTP request and times it.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defun&lt;/span&gt; &lt;span class='nv'&gt;do-request&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;url&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;start-time&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;get-internal-real-time&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;format&lt;/span&gt; &lt;span class='no'&gt;t&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;Starting request: ~a~%&amp;quot;&lt;/span&gt; &lt;span class='nv'&gt;url&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;drakma:http-request&lt;/span&gt; &lt;span class='nv'&gt;url&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;elapsed&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;-&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;get-internal-real-time&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nv'&gt;start-time&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;format&lt;/span&gt; &lt;span class='no'&gt;t&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;Completed request in ~a ms: ~a~%&amp;quot;&lt;/span&gt; &lt;span class='nv'&gt;elapsed&lt;/span&gt; &lt;span class='nv'&gt;url&lt;/span&gt;&lt;span class='p'&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This is what you might do without concurrency if we wanted to perform these HTTP requests:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;time-it&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;dolist&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;url&lt;/span&gt; &lt;span class='vg'&gt;*urls*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
           &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;do-request&lt;/span&gt; &lt;span class='nv'&gt;url&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;span class='c1'&gt;;; Starting request: http://blog.thezerobit.com/&lt;/span&gt;
&lt;span class='c1'&gt;;; Completed request in 616 ms: http://blog.thezerobit.com/&lt;/span&gt;
&lt;span class='c1'&gt;;; Starting request: http://quicklisp.org/&lt;/span&gt;
&lt;span class='c1'&gt;;; Completed request in 819 ms: http://quicklisp.org/&lt;/span&gt;
&lt;span class='c1'&gt;;; Starting request: http://www.cliki.net/index&lt;/span&gt;
&lt;span class='c1'&gt;;; Completed request in 429 ms: http://www.cliki.net/index&lt;/span&gt;
&lt;span class='c1'&gt;;; Starting request: http://sbcl.org/&lt;/span&gt;
&lt;span class='c1'&gt;;; Completed request in 291 ms: http://sbcl.org/&lt;/span&gt;
&lt;span class='c1'&gt;;; Runtime: 2155 milliseconds.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It takes over 2 seconds to make all these requests in serial fashion. There may be a way to queue up these requests in parallel with the Drakma library, but instead we&amp;#8217;ll just use the ChanL library. Let&amp;#8217;s define a function, like DO-REQUEST that instead of printing its progress will send messages over a channel.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defun&lt;/span&gt; &lt;span class='nv'&gt;do-request-chan&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;url&lt;/span&gt; &lt;span class='nv'&gt;chan&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;start-time&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;get-internal-real-time&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;chanl:send&lt;/span&gt; &lt;span class='nv'&gt;chan&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;format&lt;/span&gt; &lt;span class='no'&gt;nil&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;Starting request: ~a~%&amp;quot;&lt;/span&gt; &lt;span class='nv'&gt;url&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;drakma:http-request&lt;/span&gt; &lt;span class='nv'&gt;url&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;elapsed&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;-&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;get-internal-real-time&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nv'&gt;start-time&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;chanl:send&lt;/span&gt; &lt;span class='nv'&gt;chan&lt;/span&gt;
                  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;format&lt;/span&gt; &lt;span class='no'&gt;nil&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;Completed request in ~a ms: ~a~%&amp;quot;&lt;/span&gt; &lt;span class='nv'&gt;elapsed&lt;/span&gt; &lt;span class='nv'&gt;url&lt;/span&gt;&lt;span class='p'&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We can use the PEXEC call to spawn separate processes for each HTTP request and then wait for the 8 messages to come in on the channel we create to synchronize.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;time-it&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;chan&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;make-instance&lt;/span&gt; &lt;span class='ss'&gt;&amp;#39;chanl:channel&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;dolist&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;url&lt;/span&gt; &lt;span class='vg'&gt;*urls*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;chanl:pexec&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;do-request-chan&lt;/span&gt; &lt;span class='nv'&gt;url&lt;/span&gt; &lt;span class='nv'&gt;chan&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;dotimes&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='mi'&gt;8&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;format&lt;/span&gt; &lt;span class='no'&gt;t&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;chanl:recv&lt;/span&gt; &lt;span class='nv'&gt;chan&lt;/span&gt;&lt;span class='p'&gt;)))))&lt;/span&gt;
&lt;span class='c1'&gt;;; Starting request: http://blog.thezerobit.com/&lt;/span&gt;
&lt;span class='c1'&gt;;; Starting request: http://quicklisp.org/&lt;/span&gt;
&lt;span class='c1'&gt;;; Starting request: http://sbcl.org/&lt;/span&gt;
&lt;span class='c1'&gt;;; Starting request: http://www.cliki.net/index&lt;/span&gt;
&lt;span class='c1'&gt;;; Completed request in 291 ms: http://blog.thezerobit.com/&lt;/span&gt;
&lt;span class='c1'&gt;;; Completed request in 302 ms: http://www.cliki.net/index&lt;/span&gt;
&lt;span class='c1'&gt;;; Completed request in 306 ms: http://sbcl.org/&lt;/span&gt;
&lt;span class='c1'&gt;;; Completed request in 703 ms: http://quicklisp.org/&lt;/span&gt;
&lt;span class='c1'&gt;;; Runtime: 703 milliseconds.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here, the whole operation takes only as long as the longest single request and the overhead of spawning separate threads is negligible compared to the time saved by making these requests concurrently. It is important to note that, by default, the channels are not buffered so calls to SEND will block until there&amp;#8217;s a RECV called on the same channel in a different thread. ChanL also provides buffered channels and some other goodies which I haven&amp;#8217;t touched on here.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Lazy Sequences in Common Lisp</title>
      <link>http://blog.thezerobit.com/2012/07/28/lazy-sequences-in-common-lisp.html</link>
      <pubDate>Sat, 28 Jul 2012 00:00:00 -0700</pubDate>
      <author>steveth45@gmail.com (Stephen A. Goss)</author>
      <guid isPermaLink="true">http://blog.thezerobit.com/2012/07/28/lazy-sequences-in-common-lisp.html</guid>
      <category>programming</category>
      <category>lisp</category>
      <category>common-lisp</category>
      
      <description>&lt;h2 id='lazy_sequences_in_common_lisp'&gt;Lazy Sequences in Common Lisp&lt;/h2&gt;

&lt;h3 id='0_delayed_evaluation_with_closures'&gt;0. Delayed Evaluation with Closures&lt;/h3&gt;

&lt;p&gt;&lt;a href='/2012/07/21/immutable-persistent-data-structures-in-common-lisp.html'&gt;Last week&lt;/a&gt; I expressed some anti-lazy sentiment, or at least it was perceived as such. Really, I am just not a fan of laziness by default. Common Lisp is decidedly not lazy by default, but it is easy to defer or avoid computation with closures. With macros, we can add it to the language in an easy-to-use form.&lt;/p&gt;

&lt;p&gt;Common Lisp is not a lazy language, but it is easy enough to add lazy sequences. We can model them after the normal list which is constructed piecemeal with the cons operator. The following recursive function builds a list of numbers counting down to 0 using cons.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defun&lt;/span&gt; &lt;span class='nv'&gt;countdown&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;&amp;gt;=&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cons&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;countdown&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;1-&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;countdown&lt;/span&gt; &lt;span class='mi'&gt;10&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (10 9 8 7 6 5 4 3 2 1 0)&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;reduce&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nb'&gt;+&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;countdown&lt;/span&gt; &lt;span class='mi'&gt;100&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; 5050&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This is a common pattern, but there are some shortcomings. First of all, it&amp;#8217;s not a tail recursive function, so this call will always build the stack since tail call optimization or tail recursion elimination does not apply, and will do so linearly with the argument n. Also, it constructs the entire list. You may want this list of numbers, but you don&amp;#8217;t need all of them right away sitting in memory. In the example above, the call to reduce gets a full list of 101 elements, from 100 to 0 before processing. Depending on the length of the sequence, a different algorithm might work better.&lt;/p&gt;

&lt;p&gt;One way (of many) to construct lazy sequences in Common Lisp is to store the CDR (second part) of the CONS cell as a thunk, or a closure that takes no argument and computes the next CONS in the list.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defun&lt;/span&gt; &lt;span class='nv'&gt;lazy-countdown&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;&amp;gt;=&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cons&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;lambda&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lazy-countdown&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;1-&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt;&lt;span class='p'&gt;))))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lazy-countdown&lt;/span&gt; &lt;span class='mi'&gt;10&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (10 . #&amp;lt;CCL:COMPILED-LEXICAL-CLOSURE (:INTERNAL LAZY-COUNTDOWN) #x30200F59400F&amp;gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We can grab the first element of the lazy list with CAR per normal, but to get the next CONS cell, we need a version of CDR which FUNCALLs the thunk. That will call LAZY-COUNTDOWN which will return another CONS cell.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defun&lt;/span&gt; &lt;span class='nv'&gt;lazy-cdr&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lazylist&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;funcall&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cdr&lt;/span&gt; &lt;span class='nv'&gt;lazylist&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lazy-cdr&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lazy-countdown&lt;/span&gt; &lt;span class='mi'&gt;10&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (9 . #&amp;lt;CCL:COMPILED-LEXICAL-CLOSURE (:INTERNAL LAZY-COUNTDOWN) #x30200F55B7BF&amp;gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So far, so good. Now we need a version of REDUCE which uses LAZY-CDR instead of CDR, and can reduce a lazy list for us.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defun&lt;/span&gt; &lt;span class='nv'&gt;lazy-reduce&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;f&lt;/span&gt; &lt;span class='nv'&gt;lazylist&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;labels&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;inner-reduce&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lazylist&lt;/span&gt; &lt;span class='nv'&gt;acc&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
             &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='nv'&gt;lazylist&lt;/span&gt;
               &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;inner-reduce&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lazy-cdr&lt;/span&gt; &lt;span class='nv'&gt;lazylist&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;funcall&lt;/span&gt; &lt;span class='nv'&gt;f&lt;/span&gt; &lt;span class='nv'&gt;acc&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;car&lt;/span&gt; &lt;span class='nv'&gt;lazylist&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
               &lt;span class='nv'&gt;acc&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;inner-reduce&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lazy-cdr&lt;/span&gt; &lt;span class='nv'&gt;lazylist&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;car&lt;/span&gt; &lt;span class='nv'&gt;lazylist&lt;/span&gt;&lt;span class='p'&gt;))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lazy-reduce&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nb'&gt;+&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lazy-countdown&lt;/span&gt; &lt;span class='mi'&gt;1000&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; 500500&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='1_use_clos_and_macros_for_a_nice_interface'&gt;1. Use CLOS and Macros for a Nice Interface&lt;/h3&gt;

&lt;p&gt;In order to use this pattern easily, we will create a nice interface. We&amp;#8217;ll package up the lazy list into its own class, which I will call LCONS and use a macro of the same name to construct lazy lists by automatically wrapping the second argument in a thunk.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defclass&lt;/span&gt; &lt;span class='nv'&gt;lcons&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt;
  &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;val&lt;/span&gt; &lt;span class='ss'&gt;:initarg&lt;/span&gt; &lt;span class='ss'&gt;:val&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defmacro&lt;/span&gt; &lt;span class='nv'&gt;lcons&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;head&lt;/span&gt; &lt;span class='nv'&gt;tail&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='o'&gt;`&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;make-instance&lt;/span&gt; &lt;span class='ss'&gt;&amp;#39;lcons&lt;/span&gt;
                  &lt;span class='ss'&gt;:val&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cons&lt;/span&gt; &lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='nv'&gt;head&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;lambda&lt;/span&gt; &lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='nv'&gt;tail&lt;/span&gt;&lt;span class='p'&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;For our interface, I am going to use methods HEAD, TAIL and EMPTY? to approximate CAR, CDR, and NULL and make them compatible with normal lists.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defgeneric&lt;/span&gt; &lt;span class='nv'&gt;empty?&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lcons&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defgeneric&lt;/span&gt; &lt;span class='nv'&gt;head&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lcons&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defgeneric&lt;/span&gt; &lt;span class='nv'&gt;tail&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lcons&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defmethod&lt;/span&gt; &lt;span class='nv'&gt;empty?&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;lcons&lt;/span&gt; &lt;span class='nv'&gt;lcons&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
  &lt;span class='no'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defmethod&lt;/span&gt; &lt;span class='nv'&gt;empty?&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;lcons&lt;/span&gt; &lt;span class='nb'&gt;list&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;null&lt;/span&gt; &lt;span class='nv'&gt;lcons&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defmethod&lt;/span&gt; &lt;span class='nv'&gt;head&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;lcons&lt;/span&gt; &lt;span class='nv'&gt;lcons&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;car&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;slot-value&lt;/span&gt; &lt;span class='nv'&gt;lcons&lt;/span&gt; &lt;span class='ss'&gt;&amp;#39;val&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defmethod&lt;/span&gt; &lt;span class='nv'&gt;head&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;lcons&lt;/span&gt; &lt;span class='nb'&gt;list&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;car&lt;/span&gt; &lt;span class='nv'&gt;lcons&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defmethod&lt;/span&gt; &lt;span class='nv'&gt;tail&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;lcons&lt;/span&gt; &lt;span class='nv'&gt;lcons&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;funcall&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cdr&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;slot-value&lt;/span&gt; &lt;span class='nv'&gt;lcons&lt;/span&gt; &lt;span class='ss'&gt;&amp;#39;val&lt;/span&gt;&lt;span class='p'&gt;))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defmethod&lt;/span&gt; &lt;span class='nv'&gt;tail&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;lcons&lt;/span&gt; &lt;span class='nb'&gt;list&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cdr&lt;/span&gt; &lt;span class='nv'&gt;lcons&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now, we can redefine LAZY-COUNTDOWN, just the same as the original COUNTDOWN but use LCONS instead of CONS.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defun&lt;/span&gt; &lt;span class='nv'&gt;countdown&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;&amp;gt;=&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cons&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;countdown&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;1-&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;car&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cdr&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;countdown&lt;/span&gt; &lt;span class='mi'&gt;10&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; 9&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defun&lt;/span&gt; &lt;span class='nv'&gt;lazy-countdown&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;&amp;gt;=&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lcons&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;countdown&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;1-&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;head&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;tail&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lazy-countdown&lt;/span&gt; &lt;span class='mi'&gt;10&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; 9&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now, we can define functions to do things that are normally only for regular lists that work with lazy lists, also. A good candidate is MAPCAR. Here&amp;#8217;s a version that works with lazy lists:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defun&lt;/span&gt; &lt;span class='nv'&gt;lmapcar&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;f&lt;/span&gt; &lt;span class='k'&gt;&amp;amp;rest&lt;/span&gt; &lt;span class='nv'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;notany&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nv'&gt;empty?&lt;/span&gt; &lt;span class='nv'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lcons&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;apply&lt;/span&gt; &lt;span class='nv'&gt;f&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;mapcar&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nv'&gt;head&lt;/span&gt; &lt;span class='nv'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
           &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;apply&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nv'&gt;lmapcar&lt;/span&gt; &lt;span class='nv'&gt;f&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;mapcar&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nv'&gt;tail&lt;/span&gt; &lt;span class='nv'&gt;lists&lt;/span&gt;&lt;span class='p'&gt;)))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;head&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lmapcar&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nb'&gt;+&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lazy-countdown&lt;/span&gt; &lt;span class='mi'&gt;10&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;countdown&lt;/span&gt; &lt;span class='mi'&gt;10&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; 20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Notice that LMAPCAR is lazy, too. It returns an LCONS (lazy list). In this way we can build up a collection of functions just like the normal functions on lists in Common Lisp, but ones that take and return lazy lists.&lt;/p&gt;

&lt;p&gt;Just like lazy sequences in other languages, these sequences can be infinite. Here&amp;#8217;s a function INTEGERS which builds an infinite lazy list of integers.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defun&lt;/span&gt; &lt;span class='nv'&gt;integers&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;lcons&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;integers&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;1+&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt;&lt;span class='p'&gt;))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;head&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;tail&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;tail&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;integers&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;))))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I have encoded this into a project which is available on github: &lt;a href='https://github.com/deliciousrobots/slow-jam'&gt;slow-jam&lt;/a&gt; . It is the above code with a few extra functions that take and/or return lazy sequences. Here are a few examples of things you can do with the library:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='c1'&gt;;; infinite sequences that print nicely on the REPL&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;range&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ETC...)&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;take&lt;/span&gt; &lt;span class='mi'&gt;10&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;range&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (0 1 2 3 4 5 6 7 8 9)&lt;/span&gt;

&lt;span class='c1'&gt;;; FILTER is lazy&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;take&lt;/span&gt; &lt;span class='mi'&gt;5&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;filter&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nb'&gt;evenp&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;range&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt; &lt;span class='mi'&gt;6&lt;/span&gt; &lt;span class='mi'&gt;8&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;One advantage of this approach is that the tail of the lazy list is never cached which means that, unless you use the TO-LIST function provided in the library to turn a lazy list into a normal list, all the elements of your lazylists (except the first) can be garbage collected. These lists never take much permanent memory. The downside is that results are not cached, and you may end up recalculating the same list elements more than once. For that reason, these lists should be built in using side-effect-free functions. If you do want to cache the contents of a lazy list, just call TO-LIST which returns real list and keep a reference to that.&lt;/p&gt;

&lt;p&gt;This is just one implementation of lazy sequences in Common Lisp. It is partially inspired by Clojure, Haskell, and SICP. If you like the &lt;a href='https://github.com/deliciousrobots/slow-jam'&gt;slow-jam&lt;/a&gt; library and want it to be better, report an issue or make a pull request at github.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Immutable Persistent Data Structures in Common Lisp</title>
      <link>http://blog.thezerobit.com/2012/07/21/immutable-persistent-data-structures-in-common-lisp.html</link>
      <pubDate>Sat, 21 Jul 2012 00:00:00 -0700</pubDate>
      <author>steveth45@gmail.com (Stephen A. Goss)</author>
      <guid isPermaLink="true">http://blog.thezerobit.com/2012/07/21/immutable-persistent-data-structures-in-common-lisp.html</guid>
      <category>programming</category>
      <category>lisp</category>
      <category>common-lisp</category>
      
      <description>&lt;h2 id='immutable_persistent_data_structures_in_common_lisp'&gt;Immutable Persistent Data Structures in Common Lisp&lt;/h2&gt;

&lt;h3 id='0_the_rationale'&gt;0. The Rationale&lt;/h3&gt;

&lt;p&gt;Clojure, Scala, and Haskell (and other languages) have recently brought the idea of immutable (and persistent) data structures into some amount of popularity. This is not a new idea, by any means, as Lisp has always supported this with its list structure, which is essentially a linked list. In Common Lisp and Scheme, lists are actually mutable but in practice, this is rarely a problem because it is generally considered bad form to go around mutating lists except under certain circumstances. Most Lisp books, tutorials and references encourage using lists in a functional style (that is, assuming and treating them as immutable structures).&lt;/p&gt;

&lt;p&gt;In Clojure, the big three data structures are the hashmap, vector, and set, which each come with their own literal syntax. Clojure also has normal lispy lists, too with language enforced immutability. These immutable data structures can be approximated with normal lists in Common Lisp with the caveat that they don&amp;#8217;t retain the more efficient performance characteristics of Clojure&amp;#8217;s data structures. There are a few libraries for Common Lisp which provide these structures with similar time and space complexity as Clojure&amp;#8217;s implementations. The one that I recommend is &lt;a href='http://common-lisp.net/project/fset/'&gt;FSet&lt;/a&gt; which, according to the Wayback Machine, has been around since at latest 2007.&lt;/p&gt;

&lt;p&gt;What&amp;#8217;s the point of learning to use these data structures in Common Lisp? Isn&amp;#8217;t Clojure better? Well, in a lot of ways, Clojure &lt;em&gt;is&lt;/em&gt; a better language and environment, but in a lot of ways, Common Lisp is better, too. I enjoy using both languages. I&amp;#8217;m not quite lucky enough to have a day-job that allows me write much code in a Lisp, so I use it for fun. Therefore, my criteria for languages that are fun tend to push me toward Common Lisp. I generally use SBCL or ClozureCL as implementations which are native (not bound the the JVM) and have a much faster startup time and interact easier with native libraries. I don&amp;#8217;t care much for the JVM, and I prefer native libraries to JVM libraries, which are themselves, often just JNI wrappers on native code. Tracebacks in SBCL and CCL are much easier to read than what you get with Clojure. I also prefer non-lazy to lazy.&lt;/p&gt;

&lt;p&gt;An aside on laziness: I like the idea of lazy collections, or iterators, or generators, or streams (from SICP). They can be useful for certain constructions, but they don&amp;#8217;t really enable anything amazing that you can&amp;#8217;t do otherwise, just with a slightly different algorithm. It&amp;#8217;s slower. Every implementation of Standard ML (not lazy) I&amp;#8217;ve tried has varied from just being somewhat to several times faster than Haskell where all computation is lazy. I think setting up all that delayed computation is expensive, and the only way I found to make Haskell perform within the same ball park as Standard ML, was to add hints here and there to get computations to go ahead and happen instead of building a stack of thunks. I don&amp;#8217;t have to encourage Standard ML to do a computation, it just does it. Same with Common Lisp. Life is much simpler and faster when computations just happen and nothing is lazy by default.&lt;/p&gt;

&lt;p&gt;So, Clojure has its advantages. One of those is a slight reduction in the number of parens with certain standard Lisp constructions like LET and COND. Also, the collection literals are nice. Clojure is a Lisp-1, so the shared namespace is generally better than Lisp-2&amp;#8217;s like Common Lisp. Even so, there are nice things about split function namespace, that is that you don&amp;#8217;t have to worry about shadowing built in functions. This is a problem in languages with a single namespece. I don&amp;#8217;t know how many programs in Python I&amp;#8217;ve seen that shadow the built in &amp;#8220;id&amp;#8221; function. It turns out that&amp;#8217;s a really popular name for a database column, and hence a variable name. In Common Lisp, you can name your variable &amp;#8220;list&amp;#8221; even through there is a standard function called &amp;#8220;list&amp;#8221;, none of this &amp;#8220;lst&amp;#8221; crap.&lt;/p&gt;

&lt;p&gt;TLDR; It&amp;#8217;s all a matter of taste, but for me Common Lisp is just a little more fun to hack in than Clojure.&lt;/p&gt;

&lt;h3 id='1_the_list'&gt;1. The List&lt;/h3&gt;

&lt;p&gt;I&amp;#8217;ll try to keep this short. A Common Lisp list is a linked list constructed of CONS cells. Each CONS has two parts the CAR and the CDR. The CAR generally contains a list element and the CDR contains the next CONS cell, or NIL, signifying the end of the list. An empty list is the same as NIL.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='c1'&gt;;; contruct a list with a single element, the keyword symbol :x&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cons&lt;/span&gt; &lt;span class='ss'&gt;:x&lt;/span&gt; &lt;span class='no'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (:x)&lt;/span&gt;

&lt;span class='c1'&gt;;; alternately:&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (:x)&lt;/span&gt;

&lt;span class='c1'&gt;;; or with quoting (bypass evaluation):&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;quote&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:x&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (:x)&lt;/span&gt;

&lt;span class='c1'&gt;;; shorthand for quoting is a single quote mark&lt;/span&gt;
&lt;span class='o'&gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:x&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (:x)&lt;/span&gt;

&lt;span class='c1'&gt;;; CAR and CDR extract the cells of the CONS&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;car&lt;/span&gt; &lt;span class='o'&gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:x&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; :x&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cdr&lt;/span&gt; &lt;span class='o'&gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:x&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; NIL&lt;/span&gt;

&lt;span class='c1'&gt;;; A list of three elements:&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cons&lt;/span&gt; &lt;span class='ss'&gt;:x&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cons&lt;/span&gt; &lt;span class='ss'&gt;:y&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cons&lt;/span&gt; &lt;span class='ss'&gt;:z&lt;/span&gt; &lt;span class='no'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (:x :y :z)&lt;/span&gt;
&lt;span class='c1'&gt;;; Also: (list :x :y :z) or &amp;#39;(:x :y :z)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So the way to use lists as an immutable, persistent data structure is that you can construct a new list with an element added to the front of the list without affecting the original, and the &amp;#8220;tail&amp;#8221; of the list is shared. Also, you can get the list minus the front element, just by taking the CDR of the list.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='nv'&gt;our-list&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cons&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='nv'&gt;our-list&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cons&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='nv'&gt;our-list&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cdr&lt;/span&gt; &lt;span class='nv'&gt;our-list&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='nv'&gt;our-list&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; ((0 1 2 3) (1 1 2 3) (2 3) (1 2 3))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In that example I took a list and first constructed a new list by adding a 0 to the front, then another new list by adding a 1 to the front, then I got a list without the first element, and then the original list, unscathed. No list was mutated and no space was wasted, as all these lists share the same last 2 or 3 CONS cells.&lt;/p&gt;

&lt;h3 id='2_vector__seq'&gt;2. Vector / SEQ&lt;/h3&gt;

&lt;p&gt;Of course, you might want to do something other than have an ordered sequence with the ability to add or remove elements to the front. In Clojure, you&amp;#8217;ve got the vector, which is an ordered sequence that allows you to add or remove elements anywhere in the list, and lookup arbitrary elements in O(log n) time and with shared structure. You can do the same thing in Common Lisp with normal lists but some of the operations will take O(n) time complexity and some operations will return a brand new list with no shared structure. Let&amp;#8217;s start with that and then show how to get Clojure-style complexity characteristics with the SEQ collection provided by the FSet library. For small enough sequences you might just want to use normal lists, and avoid the FSet dependency.&lt;/p&gt;

&lt;p&gt;In none of the following examples is any collection mutated, instead the value of the expression must be captured and used instead of the original, so when I say &amp;#8220;drop an element&amp;#8221;, I really mean &amp;#8220;return a new collection without an element&amp;#8221;, etc.&lt;/p&gt;

&lt;p&gt;You can remove an element from the end of a list with BUTLAST, a funny sounding function which basically creates a whole new list minus the last element. You can also specify a number of elements to remove from the end of the list.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;butlast&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (1 2)&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;butlast&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt; &lt;span class='mi'&gt;5&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (1 2 3)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can get the NTH element of a list:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;nth&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt; &lt;span class='mi'&gt;5&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can take a slice of a list with SUBSEQ:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;subseq&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt; &lt;span class='ss'&gt;:d&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (:B :C)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Or drop the first n elements with NTHCDR:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;nthcdr&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt; &lt;span class='ss'&gt;:d&lt;/span&gt; &lt;span class='ss'&gt;:e&lt;/span&gt; &lt;span class='ss'&gt;:f&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (:E :F)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you want to drop or add or change an element from the middle of the list you might have to write or use one these simple functions to do that:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defun&lt;/span&gt; &lt;span class='nv'&gt;drop-nth&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;n&lt;/span&gt; &lt;span class='nb'&gt;list&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;append&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;subseq&lt;/span&gt; &lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;nthcdr&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;1+&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nb'&gt;list&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;drop-nth&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt; &lt;span class='ss'&gt;:d&lt;/span&gt; &lt;span class='ss'&gt;:e&lt;/span&gt; &lt;span class='ss'&gt;:f&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (:A :B :C :E :F)&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defun&lt;/span&gt; &lt;span class='nv'&gt;add-nth&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;n&lt;/span&gt; &lt;span class='nv'&gt;elem&lt;/span&gt; &lt;span class='nb'&gt;list&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;append&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;subseq&lt;/span&gt; &lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cons&lt;/span&gt; &lt;span class='nv'&gt;elem&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;nthcdr&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt; &lt;span class='nb'&gt;list&lt;/span&gt;&lt;span class='p'&gt;))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;add-nth&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt; &lt;span class='ss'&gt;:bar&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt; &lt;span class='ss'&gt;:d&lt;/span&gt; &lt;span class='ss'&gt;:e&lt;/span&gt; &lt;span class='ss'&gt;:f&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (:A :B :C :BAR :D :E :F)&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defun&lt;/span&gt; &lt;span class='nv'&gt;set-nth&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;n&lt;/span&gt; &lt;span class='nv'&gt;elem&lt;/span&gt; &lt;span class='nb'&gt;list&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;append&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;subseq&lt;/span&gt; &lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cons&lt;/span&gt; &lt;span class='nv'&gt;elem&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;nthcdr&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;1+&lt;/span&gt; &lt;span class='nv'&gt;n&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='nb'&gt;list&lt;/span&gt;&lt;span class='p'&gt;))))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;set-nth&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt; &lt;span class='ss'&gt;:foo&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt; &lt;span class='ss'&gt;:d&lt;/span&gt; &lt;span class='ss'&gt;:e&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (:A :B :C :FOO :E)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now if you want the tree-structured, persistent version of that, use FSet&amp;#8217;s SEQ. If you are using Quicklisp (which I hope you are), you can load up FSet in the REPL like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;ql:quickload&lt;/span&gt; &lt;span class='ss'&gt;:fset&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;in-package&lt;/span&gt; &lt;span class='ss'&gt;:fset-user&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;There is a function, EMPTY-SEQ that creates an empty SEQ, and there&amp;#8217;s a macro SEQ which can be used to construct a SEQ with multiple elements:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;empty-seq&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #[ ]&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;seq&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #[ :A :B :C ] ;; this is how FSet pretty-prints sequences in the REPL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can get the first or last or nth element with FIRST, LAST and @:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;first&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;seq&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; :A&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;last&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;seq&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; :C&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;@&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;seq&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; :B&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can add or remove elements at the beginning or end of sequence with WITH-FIRST, WITH-LAST, LESS-FIRST, and LESS-LAST:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;with-first&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;seq&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:foo&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #[ :FOO :A :B :C ]&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;with-last&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;seq&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:foo&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #[ :A :B :C :FOO ]&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;less-first&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;seq&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #[ :B :C ]&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;less-last&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;seq&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #[ :A :B ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can replace an element, drop an element, or insert an element at a particular index with WITH, INSERT and LESS:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;with&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;seq&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='ss'&gt;:foo&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #[ :A :FOO :C ]&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;insert&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;seq&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='ss'&gt;:foo&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #[ :A :FOO :B :C ]&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;less&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;seq&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #[ :A :C ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='2_set'&gt;2. Set&lt;/h3&gt;

&lt;p&gt;In Common Lisp lists are also used to emulate sets. Not all operations will have the optimum time complexity, but it&amp;#8217;s generally adequate for most purposes.&lt;/p&gt;

&lt;p&gt;Common Lisp has various equality functions: EQ, EQL, EQUAL, and EQUALP. I will not summarize them here, but for the sake of consistency with Clojure, we&amp;#8217;ll probably want to consider two elements to be equal with EQUALP. Many Common Lisp functions take an optional :TEST parameter to specify which equality test function to use. All of the set theory related functions do.&lt;/p&gt;

&lt;p&gt;To test if a value is present in a set (really, just a list that we&amp;#8217;re treating as a set), there is the MEMBER function. It will return NIL if the value is not present (which is the only &amp;#8220;false&amp;#8221; value in Common Lisp) or the subset of the list starting with that value (which will be treated as &amp;#8220;true&amp;#8221; in conditional statements, etc) if it is present.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;member&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:test&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nb'&gt;equalp&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (:A :B :C)&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;member&lt;/span&gt; &lt;span class='ss'&gt;:d&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:test&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nb'&gt;equalp&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; NIL&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;member&lt;/span&gt; &lt;span class='o'&gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;asdf&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='o'&gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;asdf&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:test&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nb'&gt;equalp&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; ((&amp;quot;asdf&amp;quot;) :B :C)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can get the union or intersection of two sets with UNION and INTERSECTION:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;union&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:d&lt;/span&gt; &lt;span class='ss'&gt;:e&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:test&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nb'&gt;equalp&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (:C :B :D :E :A)&lt;/span&gt;
&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;intersection&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:d&lt;/span&gt; &lt;span class='ss'&gt;:e&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:test&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nb'&gt;equalp&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (:B :A)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can get all the elements from one list that do not exist in another list with SET-DIFFERENCE.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set-difference&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:d&lt;/span&gt; &lt;span class='ss'&gt;:e&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:test&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nb'&gt;equalp&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (:C)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can even check if a set is a subset of another set with SUBSETP.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;subsetp&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:d&lt;/span&gt; &lt;span class='ss'&gt;:e&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:test&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nb'&gt;equalp&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; NIL&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;subsetp&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:d&lt;/span&gt; &lt;span class='ss'&gt;:e&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:test&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nb'&gt;equalp&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; T&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The set of elements that exist in only one of two sets is constructed with SET-EXCLUSIVE-OR.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set-exclusive-or&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:d&lt;/span&gt; &lt;span class='ss'&gt;:e&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:test&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nb'&gt;equalp&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (:E :D :C)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Adding and removing elements from a list is accomplished with CONS and REMOVE:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cons&lt;/span&gt; &lt;span class='ss'&gt;:foo&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (:foo :a :b)&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;remove&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;elem&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;foo&amp;quot;&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;bar&amp;quot;&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;elem&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:test&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nb'&gt;equalp&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (&amp;quot;foo&amp;quot; &amp;quot;bar&amp;quot;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It&amp;#8217;s clear that Common Lisp was designed to use lists as sets when necessary, but under certain conditions you might want to use a more efficient implementation (say if you wanted to do a lot of membership tests in a larger set, and would benefit from O(log n) membership test instead of O(n)) you can use FSet&amp;#8217;s SET. You can construct an empty set with EMPTY-SET or pre-populate with the SET macro (which shadows the archaic and generally unused SET function built into Common Lisp).&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;empty-set&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #{ }&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #{ :A :B :C }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The FSet library comes with an equality function that is used automatically: EQUAL?. It is slightly better than EQUALP in that it will find two sets equal that are equivalent sets (same for other FSet collections).:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;equalp&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='no'&gt;NIL&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;equal?&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='no'&gt;T&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Membership is tested with CONTAINS?:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;contains?&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; T&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;contains?&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:d&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; NIL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;UNION, INTERSECTION, and SET-DIFFERENCE work as expected:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;union&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #{ :A :B :C }&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;intersection&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #{ :B }&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set-difference&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #{ :A }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Two tests exist: SUBSET? and DISJOINT?.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;subset?&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; T&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;subset?&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:d&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; NIL&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;disjoint?&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt; &lt;span class='ss'&gt;:d&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; T&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;disjoint?&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt; &lt;span class='ss'&gt;:d&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; NIL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Adding and removing elements from a SET is accomplished with WITH and LESS:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;with&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #{ :A :B :C }&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;less&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #{ :B :C }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='3_map'&gt;3. Map&lt;/h3&gt;

&lt;p&gt;There are two ways lists are used in Common Lisp to create mapping collections.&lt;/p&gt;

&lt;p&gt;The plist is just a list with every two elements representing a key and a value. It has one useful function, GETF which uses EQ for key equality and no way to use any other comparison, making it only useful for using symbols for keys:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;getf&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:name&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;Steve&amp;quot;&lt;/span&gt; &lt;span class='ss'&gt;:age&lt;/span&gt; &lt;span class='mi'&gt;33&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:name&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; &amp;quot;Steve&amp;quot;&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;getf&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:name&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;Steve&amp;quot;&lt;/span&gt; &lt;span class='ss'&gt;:age&lt;/span&gt; &lt;span class='mi'&gt;33&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:weight&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; NIL&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;getf&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:name&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;Steve&amp;quot;&lt;/span&gt; &lt;span class='ss'&gt;:age&lt;/span&gt; &lt;span class='mi'&gt;33&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='ss'&gt;:weight&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;some default&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; &amp;quot;some default&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Mappings can be changed or added by appending a key/value pair to the front of the list since GETF searches from the front:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;getf&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;append&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:name&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;Stephen&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:name&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;Steve&amp;quot;&lt;/span&gt; &lt;span class='ss'&gt;:age&lt;/span&gt; &lt;span class='mi'&gt;33&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='ss'&gt;:name&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; &amp;quot;Stephen&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You could easily build a repertoire of functions to do all the common operations you might want with plists, but there is another form called the alist which comes with a better set of operations built in. An alist is a list of cons cells with the key in the CAR and value in the CDR. When you have a CONS cell with a non-list in the CDR, it is called a dotted list and looks like this: &lt;code&gt;(car . cdr)&lt;/code&gt;. Alists can be constructed in a variety of ways:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cons&lt;/span&gt; &lt;span class='ss'&gt;:key&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;val&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cons&lt;/span&gt; &lt;span class='ss'&gt;:other-key&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;other-val&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; ((:KEY . &amp;quot;val&amp;quot;) (:OTHER-KEY . &amp;quot;other-val&amp;quot;))&lt;/span&gt;

&lt;span class='o'&gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='ss'&gt;:key&lt;/span&gt; &lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;val&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:other-key&lt;/span&gt; &lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;other-val&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; ((:KEY . &amp;quot;val&amp;quot;) (:OTHER-KEY . &amp;quot;other-val&amp;quot;))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;pairlis&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='ss'&gt;:key1&lt;/span&gt; &lt;span class='ss'&gt;:key2&lt;/span&gt; &lt;span class='ss'&gt;:key3&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;val1&amp;quot;&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;val2&amp;quot;&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;val3&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; ((:KEY3 . &amp;quot;val3&amp;quot;) (:KEY2 . &amp;quot;val2&amp;quot;) (:KEY1 . &amp;quot;val1&amp;quot;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The lookup function for alists is ASSOC which takes the :TEST parameter for key equality though it returns the entire matching CONS cell, not just the value. You can use CDR to extract the value.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;assoc&lt;/span&gt; &lt;span class='ss'&gt;:key&lt;/span&gt; &lt;span class='o'&gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='ss'&gt;:key&lt;/span&gt; &lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;val&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:other-key&lt;/span&gt; &lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;other-val&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='ss'&gt;:test&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nb'&gt;equalp&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; (:KEY . &amp;quot;val&amp;quot;)&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cdr&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;assoc&lt;/span&gt; &lt;span class='ss'&gt;:other-key&lt;/span&gt; &lt;span class='o'&gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='ss'&gt;:key&lt;/span&gt; &lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;val&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:other-key&lt;/span&gt; &lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;other-val&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='ss'&gt;:test&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nb'&gt;equalp&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; &amp;quot;other-val&amp;quot;&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;assoc&lt;/span&gt; &lt;span class='ss'&gt;:missing-key&lt;/span&gt; &lt;span class='o'&gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='ss'&gt;:key&lt;/span&gt; &lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;val&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:other-key&lt;/span&gt; &lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;other-val&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='ss'&gt;:test&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='nb'&gt;equalp&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; NIL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Like plists, key/val pairs can be added to alists by adding them to the front of the list. There is a helper function for this called ACONS:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;acons&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;foo&amp;quot;&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;bar&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;baz&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='s'&gt;&amp;quot;val&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; ((&amp;quot;foo&amp;quot; . &amp;quot;bar&amp;quot;) (&amp;quot;baz&amp;quot; . &amp;quot;val&amp;quot;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;There&amp;#8217;s no builtin function to remove keys from an alist, but we can write one easily enough:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defun&lt;/span&gt; &lt;span class='nv'&gt;alist-remove&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;alist&lt;/span&gt; &lt;span class='nv'&gt;key&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;remove-if&lt;/span&gt; &lt;span class='nf'&gt;#&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;lambda&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;cell&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;equalp&lt;/span&gt; &lt;span class='nv'&gt;key&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;car&lt;/span&gt; &lt;span class='nv'&gt;cell&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt; &lt;span class='nv'&gt;alist&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;alist-remove&lt;/span&gt; &lt;span class='o'&gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;((&lt;/span&gt;&lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='mi'&gt;100&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='o'&gt;.&lt;/span&gt; &lt;span class='mi'&gt;200&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; ((:B . 200))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Alists are probably an 80% solution, which is plenty for most situations, but FSet&amp;#8217;s maps are quite nice and give you that O(log n) lookup and update time complexity with the structural sharing that we&amp;#8217;ve grown to love. I&amp;#8217;ve found them as useful as Clojure&amp;#8217;s hashmaps. Like the other collections, there&amp;#8217;s a function EMPTY-MAP that&amp;#8217;s self explanatory and a macro MAP for constructing larger maps:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;empty-map&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #{| |}&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;map&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='mi'&gt;100&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='mi'&gt;200&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #{| (:A 100) (:B 200) |}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Like SETs, elements can be added or removed or accessed from FSet MAP collections with WITH, LESS and @.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;with&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;map&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='mi'&gt;100&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='mi'&gt;200&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #{| (:A 100) (:B 200) |}&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;less&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;map&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='mi'&gt;100&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:c&lt;/span&gt; &lt;span class='mi'&gt;200&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #{| (:A 100) |}&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;@&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;map&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='mi'&gt;100&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:c&lt;/span&gt; &lt;span class='mi'&gt;200&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='ss'&gt;:c&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; 200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id='4_conclusion_wbonus_feature'&gt;4. Conclusion w/bonus Feature&lt;/h3&gt;

&lt;p&gt;I only scratched the surface with the FSet library. There are more functions than the ones I listed and some of the ones I describe actually return multiple values, for example to signify if a key is present in case you are storing NIL as values, etc. I recommend the &lt;a href='http://common-lisp.net/project/fset/Site/FSet-Tutorial.html'&gt;FSet Tutorial&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;Lists in Common Lisp are really quite versatile and can approximate most other structures for limited sizes. The nice thing about the FSet library is that it always puts the collection as the first argument, so it is amenable to Clojure&amp;#8217;s threading macro: -&amp;gt; which I will translate here for your benefit into Common Lisp:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='cl'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;defmacro&lt;/span&gt; &lt;span class='nv'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='k'&gt;&amp;amp;optional&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;form&lt;/span&gt; &lt;span class='no'&gt;nil&lt;/span&gt; &lt;span class='nv'&gt;form-supplied-p&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='k'&gt;&amp;amp;rest&lt;/span&gt; &lt;span class='nv'&gt;more&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='nv'&gt;form-supplied-p&lt;/span&gt;
    &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='nv'&gt;more&lt;/span&gt;
      &lt;span class='o'&gt;`&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='nv'&gt;form&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;,@&lt;/span&gt;&lt;span class='nv'&gt;more&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
      &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;listp&lt;/span&gt; &lt;span class='nv'&gt;form&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
        &lt;span class='o'&gt;`&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;car&lt;/span&gt; &lt;span class='nv'&gt;form&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='nv'&gt;x&lt;/span&gt; &lt;span class='o'&gt;,@&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;cdr&lt;/span&gt; &lt;span class='nv'&gt;form&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
        &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;list&lt;/span&gt; &lt;span class='nv'&gt;form&lt;/span&gt; &lt;span class='nv'&gt;x&lt;/span&gt;&lt;span class='p'&gt;)))&lt;/span&gt;
    &lt;span class='nv'&gt;x&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;

&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;empty-map&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;with&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt; &lt;span class='mi'&gt;100&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;with&lt;/span&gt; &lt;span class='ss'&gt;:b&lt;/span&gt; &lt;span class='mi'&gt;200&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;less&lt;/span&gt; &lt;span class='ss'&gt;:a&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt;
&lt;span class='c1'&gt;;;--&amp;gt; #{| (:B 200) |}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</description>
    </item>
    

  </channel>
</rss>
