<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://lisper.in/feed/lisp.xml" rel="self" type="application/atom+xml" /><link href="https://lisper.in/" rel="alternate" type="text/html" /><updated>2024-10-26T11:45:16+00:00</updated><id>https://lisper.in/feed/lisp.xml</id><title type="html">Lisper.in | Lisp</title><subtitle>Essays on programming, technology and other things</subtitle><author><name>Chaitanya Gupta</name></author><entry><title type="html">Do you start with a struct or a class?</title><link href="https://lisper.in/do-you-start-with-a-struct-or-a-class" rel="alternate" type="text/html" title="Do you start with a struct or a class?" /><published>2022-03-14T00:00:00+00:00</published><updated>2022-03-14T00:00:00+00:00</updated><id>https://lisper.in/do-you-start-with-a-struct-or-class</id><content type="html" xml:base="https://lisper.in/do-you-start-with-a-struct-or-a-class"><![CDATA[<p>When creating a new compound data type in Common Lisp, do you make it a struct
or a class? Especially if you are still exploring things, and do not know how
it will evolve.</p>

<p>For some time after I learned CL, I’d always go for a struct. After all,
<code class="language-plaintext highlighter-rouge">defstruct</code> is so easy to work with – you get so many useful accessors for
free!</p>

<div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defstruct</span> <span class="nv">foo</span>
  <span class="nv">a</span>
  <span class="nv">b</span><span class="p">)</span>
</code></pre></div></div>

<p>This gives us the type <code class="language-plaintext highlighter-rouge">FOO</code>, the functions <code class="language-plaintext highlighter-rouge">MAKE-FOO</code>, <code class="language-plaintext highlighter-rouge">COPY-FOO</code> and <code class="language-plaintext highlighter-rouge">FOO-P</code>
and the slot accessing functions <code class="language-plaintext highlighter-rouge">FOO-A</code> and <code class="language-plaintext highlighter-rouge">FOO-B</code> out of the box.</p>

<p>Compare that to the equivalent <code class="language-plaintext highlighter-rouge">defclass</code> and the only thing you get is the
type. There’s no copying function, the type needs to be passed around to
<code class="language-plaintext highlighter-rouge">MAKE-INSTANCE</code>, <code class="language-plaintext highlighter-rouge">TYPEP</code> and don’t even get me started on the verbosity of
<code class="language-plaintext highlighter-rouge">SLOT-VALUE</code>.</p>

<p>That said, at least this problem can be solved by using macros like <code class="language-plaintext highlighter-rouge">WITH-SLOTS</code>
or <code class="language-plaintext highlighter-rouge">defclass*</code> (readily available on Quicklisp).</p>

<p>However, there’s still the issue of performance. Because there’s no dynamic
dispatch, structs are usually faster than classes - plus their functions can be
inlined, and structs themselves can also be stack allocated.</p>

<p>What’s not there to like?</p>

<p>The big problem with structs, especially when you are still exploring things, is
modifications. Change the above struct to the following:</p>

<div class="language-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defstruct</span> <span class="nv">foo</span>
  <span class="nv">x</span>
  <span class="nv">a</span>
  <span class="nv">b</span><span class="p">)</span>
</code></pre></div></div>

<p>And SBCL will immediately complain with this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>WARNING: change in instance length of class FOO:
  current length: 2
  new length: 3

debugger invoked on a SIMPLE-ERROR in thread
#&lt;THREAD "main thread" RUNNING {1004AC0203}&gt;:
  attempt to redefine the STRUCTURE-OBJECT class FOO incompatibly with the
  current definition

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [CONTINUE           ] Use the new definition of FOO, invalidating
                           already-loaded code and instances.
  1: [RECKLESSLY-CONTINUE] Use the new definition of FOO as if it were
                           compatible, allowing old accessors to use new
                           instances and allowing new accessors to use old
                           instances.
  2: [ABORT              ] Exit debugger, returning to top level.
</code></pre></div></div>

<p>For your own sake, just abort (restart 2) or continue (restart 0). In no case
shall ye recklessly continue, because then you are just asking for trouble – ok
maybe try it just for fun, but don’t do this in production!</p>

<p>Classes, on the other hand, are <a href="http://clhs.lisp.se/Body/f_upda_1.htm">born to be
redefined</a>. Add a new slot, or remove an
existing one, your instances will keep working just fine.</p>

<p>And while classes may not be as performant as structs, their performance is good
enough most of the time, even more so when you are exploring
things. <a href="http://lispm.de/docs/Publications/Common%20Lisp/CLOS%20and%20Efficiency/">Here’s</a>
a good collection of articles on CLOS efficiency.</p>

<p>In conclusion, my opinion on this matter has done a 180-degree turn and today I
default to using a <code class="language-plaintext highlighter-rouge">defclass</code> when exploring new compound types.</p>]]></content><author><name>Chaitanya Gupta</name></author><category term="lisp" /><summary type="html"><![CDATA[When creating a new compound data type in Common Lisp, do you make it a struct or a class? Especially if you are still exploring things, and do not know how it will evolve.]]></summary></entry><entry><title type="html">Optimizing array operations for multiple element types</title><link href="https://lisper.in/optimizing-array-ops" rel="alternate" type="text/html" title="Optimizing array operations for multiple element types" /><published>2019-12-21T00:00:00+00:00</published><updated>2019-12-21T00:00:00+00:00</updated><id>https://lisper.in/optimizing-array-ops</id><content type="html" xml:base="https://lisper.in/optimizing-array-ops"><![CDATA[<p>While working on <a href="https://github.com/chaitanyagupta/qbase64">qbase64</a>, I stumbled over a peculiar problem: I wanted it to
work as fast as possible when optimized array types (<code class="language-plaintext highlighter-rouge">SIMPLE-ARRAY</code>,
<code class="language-plaintext highlighter-rouge">SIMLPE-BASE-STRING</code>, etc.) were passed to the encoding/decoding routines, but I
also wanted to support the more general types.</p>

<p>For example, the core encoding routine in qbase64, <code class="language-plaintext highlighter-rouge">%ENCODE</code>, which looks
something like this (simplified):</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">%encode</span> <span class="p">(</span><span class="nv">bytes</span> <span class="nb">string</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">loop</span> <span class="c1">;; over bytes and write to string</span>
     <span class="o">...</span><span class="p">))</span>
</code></pre></div></div>

<p>goes through the <code class="language-plaintext highlighter-rouge">BYTES</code> array, taking groups of 3 octets each and writes the
encoded group of 4 characters into <code class="language-plaintext highlighter-rouge">STRING</code>.</p>

<p>If I declared its types like this:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">%encode</span> <span class="p">(</span><span class="nv">bytes</span> <span class="nb">string</span><span class="p">)</span>
  <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">type</span> <span class="p">(</span><span class="kt">simple-array</span> <span class="p">(</span><span class="kt">unsigned-byte</span> <span class="mi">8</span><span class="p">))</span> <span class="nv">bytes</span><span class="p">))</span>
  <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">type</span> <span class="kt">simple-base-string</span> <span class="nb">string</span><span class="p">))</span>
  <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">optimize</span> <span class="nv">speed</span><span class="p">))</span>
  <span class="p">(</span><span class="nb">loop</span> <span class="o">...</span><span class="p">))</span>
</code></pre></div></div>

<p>SBCL would produce very fast code, but the function would no longer work for
either <code class="language-plaintext highlighter-rouge">ARRAY</code> or <code class="language-plaintext highlighter-rouge">STRING</code>:</p>

<p>And if I was to redefine the routine with more general types:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">%encode</span> <span class="p">(</span><span class="nv">bytes</span> <span class="nb">string</span><span class="p">)</span>
  <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">type</span> <span class="nc">array</span> <span class="nv">bytes</span><span class="p">))</span>
  <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">type</span> <span class="nb">string</span> <span class="nb">string</span><span class="p">))</span>
  <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">optimize</span> <span class="nv">speed</span><span class="p">))</span>
  <span class="p">(</span><span class="nb">loop</span> <span class="o">...</span><span class="p">))</span>
</code></pre></div></div>

<p>the code produced would be significantly slower.</p>

<p>My experience with <a href="https://en.wikipedia.org/wiki/Generic_programming">generics</a> is limited, but it seemed that generics could
solve this problem elegantly. However, Common Lisp doesn’t have generics, but it
does support macros, so I came up with an ugly-but-gets-the-job-done hack.</p>

<p>I created a macro, <a href="https://github.com/chaitanyagupta/qbase64/blob/6374899aec189600e6b7b77c89009d0835154b93/utils.lisp#L49">DEFUN/TD</a>, that would take all the different type
combinations I wanted to optimize and support upfront:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">defun/td</span> <span class="nv">%encode</span> <span class="p">(</span><span class="nv">bytes</span> <span class="nb">string</span><span class="p">)</span>
   <span class="p">(((</span><span class="nv">bytes</span> <span class="p">(</span><span class="kt">simple-array</span> <span class="p">(</span><span class="kt">unsigned-byte</span> <span class="mi">8</span><span class="p">)))</span> <span class="p">(</span><span class="nb">string</span> <span class="kt">simple-base-string</span><span class="p">))</span>
    <span class="p">((</span><span class="nv">bytes</span> <span class="p">(</span><span class="kt">simple-array</span> <span class="p">(</span><span class="kt">unsigned-byte</span> <span class="mi">8</span><span class="p">)))</span> <span class="p">(</span><span class="nb">string</span> <span class="kt">simple-string</span><span class="p">))</span>
    <span class="p">((</span><span class="nv">bytes</span> <span class="nc">array</span><span class="p">)</span>                            <span class="p">(</span><span class="nb">string</span> <span class="nb">string</span><span class="p">)))</span>
  <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">optimize</span> <span class="nv">speed</span><span class="p">))</span>
  <span class="p">(</span><span class="nb">loop</span> <span class="o">...</span><span class="p">))</span>
</code></pre></div></div>

<p>and generate code which would dispatch over the type combinations, then use
<a href="http://www.lispworks.com/documentation/HyperSpec/Body/s_locall.htm"><code class="language-plaintext highlighter-rouge">LOCALLY</code></a> to declare the types and splice the body in:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">%encode</span> <span class="p">(</span><span class="nv">bytes</span> <span class="nb">string</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">cond</span>
    <span class="p">((</span><span class="nb">and</span> <span class="p">(</span><span class="nb">typep</span> <span class="nv">bytes</span> <span class="o">'</span><span class="p">(</span><span class="kt">simple-array</span> <span class="p">(</span><span class="kt">unsigned-byte</span> <span class="mi">8</span><span class="p">)))</span>
          <span class="p">(</span><span class="nb">typep</span> <span class="nb">string</span> <span class="ss">'simple-base-string</span><span class="p">))</span>
     <span class="p">(</span><span class="k">locally</span>
       <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">type</span> <span class="nv">bytes</span> <span class="p">(</span><span class="kt">simple-array</span> <span class="p">(</span><span class="kt">unsigned-byte</span> <span class="mi">8</span><span class="p">))))</span>
       <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">type</span> <span class="nb">string</span> <span class="kt">simple-base-string</span><span class="p">))</span>
       <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">optimize</span> <span class="nv">speed</span><span class="p">))</span>
       <span class="p">(</span><span class="nb">loop</span> <span class="o">...</span><span class="p">)))</span>
    <span class="p">((</span><span class="nb">and</span> <span class="p">(</span><span class="nb">typep</span> <span class="nv">bytes</span> <span class="o">'</span><span class="p">(</span><span class="kt">simple-array</span> <span class="p">(</span><span class="kt">unsigned-byte</span> <span class="mi">8</span><span class="p">)))</span>
          <span class="p">(</span><span class="nb">typep</span> <span class="nb">string</span> <span class="ss">'simple-string</span><span class="p">))</span>
     <span class="p">(</span><span class="k">locally</span>
       <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">type</span> <span class="nv">bytes</span> <span class="p">(</span><span class="kt">simple-array</span> <span class="p">(</span><span class="kt">unsigned-byte</span> <span class="mi">8</span><span class="p">))))</span>
       <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">type</span> <span class="nb">string</span> <span class="kt">simple-string</span><span class="p">))</span>
       <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">optimize</span> <span class="nv">speed</span><span class="p">))</span>
       <span class="p">(</span><span class="nb">loop</span> <span class="o">...</span><span class="p">)))</span>
    <span class="p">((</span><span class="nb">and</span> <span class="p">(</span><span class="nb">typep</span> <span class="nv">bytes</span> <span class="ss">'array</span><span class="p">)</span>
          <span class="p">(</span><span class="nb">typep</span> <span class="nb">string</span> <span class="ss">'string</span><span class="p">))</span>
     <span class="p">(</span><span class="k">locally</span>
       <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">type</span> <span class="nv">bytes</span> <span class="nc">array</span><span class="p">))</span>
       <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">type</span> <span class="nb">string</span> <span class="nb">string</span><span class="p">))</span>
       <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">optimize</span> <span class="nv">speed</span><span class="p">))</span>
       <span class="p">(</span><span class="nb">loop</span> <span class="o">...</span><span class="p">)))</span>
    <span class="p">(</span><span class="no">t</span> <span class="p">(</span><span class="nb">error</span> <span class="s">"Unsupported type combination"</span><span class="p">))))</span>
</code></pre></div></div>

<p>The result is more generated code and an increase in the size of the Lisp image,
but now the loop is well optimized for each type combination given to
<code class="language-plaintext highlighter-rouge">DEFUN/TD</code>. The run-time dispatch might incur a slight penalty, but it is more
than offset by the gains made.</p>

<h3 id="alternatives">Alternatives</h3>

<p>This was a fairly interesting problem that I hadn’t dealt with before,
nevertheless it looked like a fairly common one, so I asked on the cl-pro
list a couple of years ago how others solved this; <a href="https://github.com/markcox80">Mark Cox</a> pointed me to a
few libraries:</p>

<ul>
  <li><a href="https://github.com/markcox80/template-function">template-function</a></li>
  <li><a href="https://github.com/markcox80/specialization-store">specialization-store</a></li>
  <li><a href="https://github.com/guicho271828/inlined-generic-function">inlined-generic-function</a></li>
  <li><a href="https://github.com/cosmos72/cl-parametric-types">cl-parametric-types</a></li>
</ul>

<p>All of these are quite interesting and attack more or less the same problem in
different ways.</p>

<p>Is there a trick or two that I’ve missed? Feel free to tell me.</p>]]></content><author><name>Chaitanya Gupta</name></author><category term="lisp" /><summary type="html"><![CDATA[While working on qbase64, I stumbled over a peculiar problem: I wanted it to work as fast as possible when optimized array types (SIMPLE-ARRAY, SIMLPE-BASE-STRING, etc.) were passed to the encoding/decoding routines, but I also wanted to support the more general types.]]></summary></entry><entry><title type="html">LOAD-TIME-VALUE and prepared queries in Postmodern</title><link href="https://lisper.in/load-time-value" rel="alternate" type="text/html" title="LOAD-TIME-VALUE and prepared queries in Postmodern" /><published>2019-02-11T00:00:00+00:00</published><updated>2019-02-11T00:00:00+00:00</updated><id>https://lisper.in/load-time-value</id><content type="html" xml:base="https://lisper.in/load-time-value"><![CDATA[<p>The Common Lisp library <a href="http://marijnhaverbeke.nl/postmodern/">Postmodern</a> defines a macro called <code class="language-plaintext highlighter-rouge">PREPARE</code> that
creates <a href="https://www.postgresql.org/docs/11/sql-prepare.html">prepared statements</a> for a PostgreSQL connection. It takes a SQL
query with placeholders (<code class="language-plaintext highlighter-rouge">$1</code>, <code class="language-plaintext highlighter-rouge">$2</code>, etc.) as input and returns a function which
takes one argument for every placeholder and executes the query.</p>

<p>The first time I used it, I did something like this:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">run-query</span> <span class="p">(</span><span class="nv">id</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">funcall</span> <span class="p">(</span><span class="nv">prepare</span> <span class="s">"SELECT * FROM foo WHERE id = $1"</span><span class="p">)</span> <span class="nv">id</span><span class="p">))</span>
</code></pre></div></div>

<p>Soon after, I realized that running this function every time would generate a
new prepared statement instead of re-using the old one. Let’s look at the macro
expansion:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">macroexpand-1</span> <span class="o">'</span><span class="p">(</span><span class="nv">prepare</span> <span class="s">"SELECT * FROM foo WHERE id = $1"</span><span class="p">))</span>
<span class="nv">==&gt;</span>
<span class="p">(</span><span class="nv">LET</span> <span class="p">((</span><span class="nv">POSTMODERN::STATEMENT-ID</span> <span class="p">(</span><span class="nv">POSTMODERN::NEXT-STATEMENT-ID</span><span class="p">))</span>
      <span class="p">(</span><span class="nv">QUERY</span> <span class="s">"SELECT * FROM foo WHERE id = $1"</span><span class="p">))</span>
  <span class="p">(</span><span class="nv">LAMBDA</span> <span class="p">(</span><span class="nv">&amp;REST</span> <span class="nv">POSTMODERN::PARAMS</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">POSTMODERN::ENSURE-PREPARED</span> <span class="vg">*DATABASE*</span> <span class="nv">POSTMODERN::STATEMENT-ID</span> <span class="nv">QUERY</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">POSTMODERN::ALL-ROWS</span>
     <span class="p">(</span><span class="nv">CL-POSTGRES:EXEC-PREPARED</span> <span class="vg">*DATABASE*</span> <span class="nv">POSTMODERN::STATEMENT-ID</span>
                                <span class="nv">POSTMODERN::PARAMS</span>
                                <span class="ss">'CL-POSTGRES:LIST-ROW-READER</span><span class="p">))))</span>
<span class="nv">T</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">ENSURE-PREPARED</code> checks if a statement with the given statement-id
exists for the current connection. If yes, it will be re-used, else a new one is
created with the given query.</p>

<p>The problem is that the macro generates a new statement id every time it is
run. This was a bit surprising, but the fix was simple: capture the function
returned by <code class="language-plaintext highlighter-rouge">PREPARE</code> once, and use that instead.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defparameter</span> <span class="vg">*prepared*</span> <span class="p">(</span><span class="nv">prepare</span> <span class="s">"SELECT * FROM foo WHERE id = $1"</span><span class="p">))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">run-query</span> <span class="p">(</span><span class="nv">id</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">funcall</span> <span class="vg">*prepared*</span> <span class="nv">id</span><span class="p">))</span>
</code></pre></div></div>

<p>You can also use Postmodern’s <code class="language-plaintext highlighter-rouge">DEFPREPARED</code> instead, which similarly defines a
new function at the top-level.</p>

<p>This works well, but now are using top-level forms instead of the
nicely encapsulated single form we used earlier.</p>

<p>To fix this, we can use <a href="http://clhs.lisp.se/Body/s_ld_tim.htm"><code class="language-plaintext highlighter-rouge">LOAD-TIME-VALUE</code></a>.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">run-query</span> <span class="p">(</span><span class="nv">id</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">funcall</span> <span class="p">(</span><span class="k">load-time-value</span> <span class="p">(</span><span class="nv">prepare</span> <span class="s">"SELECT * FROM foo WHERE id = $1"</span><span class="p">))</span> <span class="nv">id</span><span class="p">))</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">LOAD-TIME-VALUE</code> is a special operator that</p>

<ol>
  <li>Evaluates the form in the null lexical environment</li>
  <li>Delays evaluation of the form until load time</li>
  <li><strong>If compiled</strong>, it ensures that the form is evaluated only once</li>
</ol>

<p>By wrapping <code class="language-plaintext highlighter-rouge">PREPARE</code> inside <code class="language-plaintext highlighter-rouge">LOAD-TIME-VALUE</code>, we get back our encapsulation
while ensuring that a new prepared statement is generated only once (per
connection), until the next time <code class="language-plaintext highlighter-rouge">RUN-QUERY</code> is recompiled.</p>

<h2 id="convenience">Convenience</h2>

<p>To avoid the need to wrap <code class="language-plaintext highlighter-rouge">PREPARE</code> every time, we can create a converience
macro and use that instead:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defmacro</span> <span class="nv">prepared-query</span> <span class="p">(</span><span class="nv">query</span> <span class="k">&amp;optional</span> <span class="p">(</span><span class="nb">format</span> <span class="ss">:rows</span><span class="p">))</span>
  <span class="o">`</span><span class="p">(</span><span class="k">load-time-value</span> <span class="p">(</span><span class="nv">prepare</span> <span class="o">,</span><span class="nv">query</span> <span class="o">,</span><span class="nb">format</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">run-query</span> <span class="p">(</span><span class="nv">id</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">funcall</span> <span class="p">(</span><span class="nv">prepared-query</span> <span class="s">"SELECT * FROM foo WHERE id = $1"</span><span class="p">)</span> <span class="nv">id</span><span class="p">))</span>
</code></pre></div></div>

<h2 id="caveats">Caveats</h2>

<p>This only works for compiled code. As mentioned earlier, the form wrapped inside
<code class="language-plaintext highlighter-rouge">LOAD-TIME-VALUE</code> is evaluated once only if you compile it. If uncompiled, it is
evaluated every time so this solution will not work there.</p>

<p>Another thing to remember about <code class="language-plaintext highlighter-rouge">LOAD-TIME-VALUE</code> is that the form is evaluated
in the null lexical environment. So the form cannot use any lexically scoped
variables like in the example below:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">run-query</span> <span class="p">(</span><span class="nv">table</span> <span class="nv">id</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">funcall</span> <span class="p">(</span><span class="k">load-time-value</span>
            <span class="p">(</span><span class="nv">prepare</span> <span class="p">(</span><span class="nb">format</span> <span class="no">nil</span> <span class="s">"SELECT * FROM ~A WHERE id = $1"</span> <span class="nv">table</span><span class="p">)))</span>
           <span class="nv">id</span><span class="p">))</span>
</code></pre></div></div>

<p>Evaluating this will signal that the variable <code class="language-plaintext highlighter-rouge">TABLE</code> is unbound.</p>]]></content><author><name>Chaitanya Gupta</name></author><category term="lisp" /><summary type="html"><![CDATA[The Common Lisp library Postmodern defines a macro called PREPARE that creates prepared statements for a PostgreSQL connection. It takes a SQL query with placeholders ($1, $2, etc.) as input and returns a function which takes one argument for every placeholder and executes the query.]]></summary></entry><entry><title type="html">Writing a natural language date and time parser</title><link href="https://lisper.in/nlp-date-parser" rel="alternate" type="text/html" title="Writing a natural language date and time parser" /><published>2019-01-01T00:00:00+00:00</published><updated>2019-01-01T00:00:00+00:00</updated><id>https://lisper.in/nlp-date-parser</id><content type="html" xml:base="https://lisper.in/nlp-date-parser"><![CDATA[<p>In the <a href="https://deftask.com">deftask</a> blog I described how it lets users 
search for tasks easily <a href="https://blog.deftask.com/why-are-date-based-searches-so-hard/">by using natural language date
queries</a>. It
accomplishes this by using a natural language date and time parser I wrote a
long time ago called <a href="https://github.com/chaitanyagupta/chronicity">Chronicity</a>.</p>

<p>But how exactly does Chronicity work? In this post, we’ll dig into its innards
and get a sense of the steps involved in writing it.</p>

<p>If you want to hack into Chronicity, or write your own NLP date parser, this
might help.</p>

<p><em>Note:</em> credit for Chronicity’s architecture goes to the Ruby library
<a href="https://github.com/mojombo/chronic">Chronic</a>. It served both as an inspiration
and as the implementation reference.</p>

<p>Broadly, Chronicity follows these steps to parse date and time strings:</p>

<ol id="markdown-toc">
  <li><a href="#normalize-text" id="markdown-toc-normalize-text">Normalize text</a></li>
  <li><a href="#tokenize" id="markdown-toc-tokenize">Tokenize</a></li>
  <li><a href="#pre-process-tokens" id="markdown-toc-pre-process-tokens">Pre-process tokens</a></li>
  <li><a href="#pattern-matching" id="markdown-toc-pattern-matching">Pattern matching</a></li>
  <li><a href="#returning-the-result" id="markdown-toc-returning-the-result">Returning the result</a></li>
</ol>

<h2 id="normalize-text">Normalize text</h2>

<p>We normalize the text before tokenizing it by doing the following:</p>

<ol>
  <li>Lower case the string</li>
  <li>Convert numeric words (like “one”, “ten”, “third”, etc.) to the corresponding
 numbers</li>
  <li>Replace all the common synonyms of a word or phrase so that tokenizing
becomes simpler.</li>
</ol>

<p>All of this is accomplished by the <a href="https://github.com/chaitanyagupta/chronicity/blob/v0.4.1/src/chronicity.lisp#L75"><code class="language-plaintext highlighter-rouge">PRE-NORMALIZE</code></a> function. To
convert numeric words to numbers the <a href="https://github.com/chaitanyagupta/chronicity/blob/v0.4.1/src/numerize.lisp#L67"><code class="language-plaintext highlighter-rouge">NUMERIZE</code></a> function is
used. One caveat: do not immediately normalize the term “second” – it can either
mean the ordinal number or the unit of time. So we wait until after tokenization
(see <a href="#pre-process-tokens">pre-process tokens</a>) to resolve this ambiguity.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">CHRONICITY&gt;</span> <span class="p">(</span><span class="nv">pre-normalize</span> <span class="s">"tomorrow at seven"</span><span class="p">)</span>
<span class="s">"next day at 7"</span>

<span class="nv">CHRONICITY&gt;</span> <span class="p">(</span><span class="nv">pre-normalize</span> <span class="s">"20 days ago"</span><span class="p">)</span>
<span class="s">"20 days past"</span>
</code></pre></div></div>

<h2 id="tokenize">Tokenize</h2>

<p>Next we assign a token to each word in the normalized text.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defclass</span> <span class="nv">token</span> <span class="p">()</span>
  <span class="p">((</span><span class="nv">word</span> <span class="ss">:initarg</span> <span class="ss">:word</span>
         <span class="ss">:reader</span> <span class="nv">token-word</span><span class="p">)</span>
   <span class="p">(</span><span class="nv">tags</span> <span class="ss">:initarg</span> <span class="ss">:tags</span>
         <span class="ss">:initform</span> <span class="no">nil</span>
         <span class="ss">:accessor</span> <span class="nv">token-tags</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">create-token</span> <span class="p">(</span><span class="nv">word</span> <span class="k">&amp;rest</span> <span class="nv">tags</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">make-instance</span> <span class="ss">'token</span>
                 <span class="ss">:word</span> <span class="nv">word</span>
                 <span class="ss">:tags</span> <span class="nv">tags</span><span class="p">))</span>
</code></pre></div></div>

<p>As you can see, besides the word, a token also contains a list of tags. Each tag
indicates a possible way to interpret the given word or number. Take the phrase
“20 days ago”. The number 20 can be interpreted in many ways:</p>

<ul>
  <li>It might refer to the 20th day of the month</li>
  <li>It might be the year 2020</li>
  <li>Or maybe just the number 20 (which is what is actually meant in the given
phrase)</li>
  <li>It could also refer to the time 8 PM in 24-hour format (20:00 hours)</li>
</ul>

<p>Remember, we are still in the tokenization phase so we don’t know which
interpretation is correct. So we will assign all four tags to the token for this
number.</p>

<p>Each tag is a subclass of the <code class="language-plaintext highlighter-rouge">TAG</code> class, which is defined as follows.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defclass</span> <span class="nv">tag</span> <span class="p">()</span>
  <span class="p">((</span><span class="k">type</span> <span class="ss">:initarg</span> <span class="ss">:type</span>
         <span class="ss">:reader</span> <span class="nv">tag-type</span><span class="p">)</span>
   <span class="p">(</span><span class="nv">now</span> <span class="ss">:initarg</span> <span class="ss">:now</span>
        <span class="ss">:accessor</span> <span class="nv">tag-now</span>
        <span class="ss">:initform</span> <span class="no">nil</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">create-tag</span> <span class="p">(</span><span class="nc">class</span> <span class="k">type</span> <span class="k">&amp;key</span> <span class="nv">now</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">make-instance</span> <span class="nc">class</span> <span class="ss">:type</span> <span class="k">type</span> <span class="ss">:now</span> <span class="nv">now</span><span class="p">))</span>
</code></pre></div></div>

<p>The slot <code class="language-plaintext highlighter-rouge">TYPE</code> is a misnomer – it actually indicates the designated value of
the token for this tag. For example, the <code class="language-plaintext highlighter-rouge">TYPE</code> for the year 2020 above will
be the integer 2020. For the time 8 PM it will be an object denoting the time.</p>

<p>The slot <code class="language-plaintext highlighter-rouge">NOW</code> has the current timestamp. It is used by some tag classes like
<code class="language-plaintext highlighter-rouge">REPEATER</code> for date-time computations (discussed later).</p>

<p>The various subclasses of <code class="language-plaintext highlighter-rouge">TAG</code> are:</p>

<ul>
  <li><a href="https://github.com/chaitanyagupta/chronicity/blob/v0.4.1/src/separator.lisp"><code class="language-plaintext highlighter-rouge">SEPARATOR</code></a> – Things like slash “/”, dash “-“, “in”, “at”, “on”,
etc.</li>
  <li><a href="https://github.com/chaitanyagupta/chronicity/blob/v0.4.1/src/ordinal.lisp"><code class="language-plaintext highlighter-rouge">ORDINAL</code></a> – Numbers like 1st, 2nd, 3rd, etc.</li>
  <li><a href="https://github.com/chaitanyagupta/chronicity/blob/v0.4.1/src/scalar.lisp"><code class="language-plaintext highlighter-rouge">SCALAR</code></a> – Simple numbers like 1, 5, 10, etc. It is further
 subclassed by <code class="language-plaintext highlighter-rouge">SCALAR-DAY</code> (1-31), <code class="language-plaintext highlighter-rouge">SCALAR-MONTH</code> (1-12) and <code class="language-plaintext highlighter-rouge">SCALAR-YEAR</code>. A
 token for any number will usually contain the SCALAR tag plus one or more of
 the subclassed tags as applicable.</li>
  <li><a href="https://github.com/chaitanyagupta/chronicity/blob/v0.4.1/src/pointer.lisp"><code class="language-plaintext highlighter-rouge">POINTER</code></a> – Indicates whether we are looking forwards (“hence”,
 “after”, “from”) or backwards (“ago”, “before”). These words are normalized
 to “future” and “past” before they are tagged.</li>
  <li><a href="https://github.com/chaitanyagupta/chronicity/blob/v0.4.1/src/grabber.lisp"><code class="language-plaintext highlighter-rouge">GRABBER</code></a> – The terms “this”, “last” and “next” (as in this month
or last month).</li>
  <li><a href="https://github.com/chaitanyagupta/chronicity/blob/v0.4.1/src/repeater.lisp"><code class="language-plaintext highlighter-rouge">REPEATER</code></a> – Most of the date and time terms are tagged using this
 class. This is described in more detail below.</li>
</ul>

<p>There are a number of <a href="https://github.com/chaitanyagupta/chronicity/tree/v0.4.1/src/repeaters">subclasses</a> of <code class="language-plaintext highlighter-rouge">REPEATER</code> to
indicate the numerous date and time terms. For example:</p>

<ul>
  <li>Unit names like “year”, “month”, “week”, “day”, etc., use the subclasses
 <code class="language-plaintext highlighter-rouge">REPEATER-YEAR</code>, <code class="language-plaintext highlighter-rouge">REPEATER-MONTH</code>, <code class="language-plaintext highlighter-rouge">REPEATER-WEEK</code>, <code class="language-plaintext highlighter-rouge">REPEATER-DAY</code>.</li>
  <li><code class="language-plaintext highlighter-rouge">REPEATER-MONTH-NAME</code> is used to indicate month names like “jan” or “january”.</li>
  <li><code class="language-plaintext highlighter-rouge">REPEATER-DAY-NAME</code> indicates day names like “monday”.</li>
  <li><code class="language-plaintext highlighter-rouge">REPEATER-TIME</code> is used to indicate time strings like 20:00.</li>
  <li>Parts of the day like AM, PM, morning, evening use the subclass
 <code class="language-plaintext highlighter-rouge">REPEATER-DAY-PORTION</code>.</li>
</ul>

<p>In addition, all the <code class="language-plaintext highlighter-rouge">REPEATER</code> subclasses need to implement a few methods that
are needed for date-time computations.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">R-NEXT</code> – Given a repeater and a pointer i.e. <code class="language-plaintext highlighter-rouge">:PAST</code> or <code class="language-plaintext highlighter-rouge">:FUTURE</code>, returns a
 time span in the immediate past or future relative to the <code class="language-plaintext highlighter-rouge">NOW</code> slot. For
 example, assume the date in <code class="language-plaintext highlighter-rouge">NOW</code> is 31st December 2018.
    <ul>
      <li><code class="language-plaintext highlighter-rouge">(r-next repeater :past)</code> for a <code class="language-plaintext highlighter-rouge">REPEATER-MONTH</code> will return a time span
 starting 1st November 2018 and ending at 30th November.</li>
      <li><code class="language-plaintext highlighter-rouge">(r-next repeater :future)</code> will return a span for all of January 2019.</li>
      <li>Similarly, for a <code class="language-plaintext highlighter-rouge">REPEATER-DAY</code> this would have returned 30th December for
 <code class="language-plaintext highlighter-rouge">:PAST</code> and 1st January for the <code class="language-plaintext highlighter-rouge">:FUTURE</code> pointer.</li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">R-THIS</code> is similar to <code class="language-plaintext highlighter-rouge">R-NEXT</code> except it works in the current context. The
 width of the span also depends on whether direction of the pointer.
    <ul>
      <li><code class="language-plaintext highlighter-rouge">(r-this repeater :past)</code> for a <code class="language-plaintext highlighter-rouge">REPEATER-DAY</code> will return a span from the
 start of day until now.</li>
      <li><code class="language-plaintext highlighter-rouge">(r-this repeater :future)</code> will return a span from now until the end of
 day.</li>
      <li><code class="language-plaintext highlighter-rouge">(r-this repeater :none)</code> will return the whole day today.</li>
    </ul>
  </li>
  <li><code class="language-plaintext highlighter-rouge">R-OFFSET</code> – Given a span, a pointer and an amount, returns a new span offset
 from the given span. The offset is roughly the amount mulitplied by the width
 of the repeater.</li>
</ul>

<p>Now we can put the whole tokenization and tagging piece together:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">tokenize</span> <span class="p">(</span><span class="nv">text</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">mapcar</span> <span class="nf">#'</span><span class="nv">create-token</span>
          <span class="p">(</span><span class="nv">cl-ppcre:split</span> <span class="err">#</span><span class="nv">?r</span><span class="s">"\s+"</span> <span class="nv">text</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">tokenize-and-tag</span> <span class="p">(</span><span class="nv">text</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">tokens</span> <span class="p">(</span><span class="nv">tokenize</span> <span class="nv">text</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">loop</span>
       <span class="nv">for</span> <span class="k">type</span> <span class="nv">in</span> <span class="p">(</span><span class="nb">list</span> <span class="ss">'repeater</span> <span class="ss">'grabber</span> <span class="ss">'pointer</span> <span class="ss">'scalar</span> <span class="ss">'ordinal</span> <span class="ss">'separator</span><span class="p">)</span>
       <span class="nb">do</span> <span class="p">(</span><span class="nv">scan-tokens</span> <span class="k">type</span> <span class="nv">tokens</span><span class="p">))</span>
    <span class="nv">tokens</span><span class="p">))</span>
</code></pre></div></div>

<p>As you can see, computing the tags for each token is accomplished by the
<code class="language-plaintext highlighter-rouge">SCAN-TOKENS</code>. This is a generic function specialized on the class name of the
tag.</p>

<p>One of the methods implementing <code class="language-plaintext highlighter-rouge">SCAN-TOKENS</code> is shown below.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defmethod</span> <span class="nv">scan-tokens</span> <span class="p">((</span><span class="nv">tag</span> <span class="p">(</span><span class="nb">eql</span> <span class="ss">'grabber</span><span class="p">))</span> <span class="nv">tokens</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">scan-map</span> <span class="o">'</span><span class="p">((</span><span class="s">"last"</span> <span class="ss">:last</span><span class="p">)</span>
                    <span class="p">(</span><span class="s">"this"</span> <span class="ss">:this</span><span class="p">)</span>
                    <span class="p">(</span><span class="s">"next"</span> <span class="ss">:next</span><span class="p">))))</span>
    <span class="p">(</span><span class="nb">dolist</span> <span class="p">(</span><span class="nv">token</span> <span class="nv">tokens</span> <span class="nv">tokens</span><span class="p">)</span>
      <span class="p">(</span><span class="nb">loop</span>
         <span class="nv">for</span> <span class="p">(</span><span class="nv">regex</span> <span class="nv">value</span><span class="p">)</span> <span class="nv">in</span> <span class="nv">scan-map</span>
         <span class="nb">when</span> <span class="p">(</span><span class="nv">cl-ppcre:scan</span> <span class="nv">regex</span> <span class="p">(</span><span class="nv">token-word</span> <span class="nv">token</span><span class="p">))</span>
         <span class="nb">do</span> <span class="p">(</span><span class="nv">tag</span> <span class="p">(</span><span class="nv">create-tag</span> <span class="ss">'grabber</span> <span class="nv">value</span><span class="p">)</span> <span class="nv">token</span><span class="p">)))))</span>

<span class="p">(</span><span class="nb">defmethod</span> <span class="nv">tag</span> <span class="p">(</span><span class="nv">tag</span> <span class="nv">token</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">push</span> <span class="nv">tag</span> <span class="p">(</span><span class="nv">token-tags</span> <span class="nv">token</span><span class="p">)))</span>
</code></pre></div></div>

<p>Going back to our original example, for the text “20 days ago”, these
are the tags set for each token (after normalization).</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Token      Tags
-----      ----
20         [SCALAR-YEAR, SCALAR-DAY, SCALAR, REPEATER-TIME]
days       [REPEATER-DAY]
past       [POINTER]
</code></pre></div></div>

<h2 id="pre-process-tokens">Pre-process tokens</h2>

<p>We are almost ready to run pattern matching to figure out the input date, but
first, we need to resolve the ambiguity related to the term second  that we
faced during normalization. At that time, we did not convert it to the number 2 
since it could refer to either the unit of time or the number.</p>

<p>Now with tokenization done, we resolve this ambiguity with a simple hack: if the
term second is followed by a repeater (i.e. month, day, year, january, etc.), we
assume that it is the ordinal number 2nd and not the unit of time. See
<a href="https://github.com/chaitanyagupta/chronicity/blob/v0.4.1/src/chronicity.lisp#L109"><code class="language-plaintext highlighter-rouge">PRE-PROCESS-TOKENS</code></a> for more details.</p>

<h2 id="pattern-matching">Pattern matching</h2>

<p>The last piece of the puzzle is pattern matching. Armed with tokens and their
corresponding tags, we define several date and time patterns that we know of and
try to match them to their input tokens.</p>

<p>First we name a few pattern classes – each pattern we define belongs to one of
these classes.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">DATE</code> – patterns that match an absolute date and time e.g. “1st January”,
 “January 1 at 2 PM”, etc.</li>
  <li><code class="language-plaintext highlighter-rouge">ANCHOR</code> – patterns that typically involve a grabber e.g. “yesterday”,
 “tuesday” “last week”, etc.</li>
  <li><code class="language-plaintext highlighter-rouge">ARROW</code> – patterns like “2 days from now”, “3 weeks ago”, etc.</li>
  <li><code class="language-plaintext highlighter-rouge">NARROW</code> – patterns like “1st day this month”, “3rd wednesday in 2007”, etc.</li>
  <li><code class="language-plaintext highlighter-rouge">TIME</code> – simple time patterns like “2 PM”, “14:30”, etc.</li>
</ul>

<p>A pattern, at its simplest, is just a list of tag classes. A list of input
tokens successfully matches a pattern if, for every token, at least one of its
tags is an instance of the tag class mentioned at the corresponding position in
the pattern. For example, the text “20 days ago” had these tags:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Token      Tags
-----      ----
20         [SCALAR-YEAR, SCALAR-DAY, SCALAR, REPEATER-TIME]
days       [REPEATER-DAY]
past       [POINTER]
</code></pre></div></div>

<p>It will match any of these patterns:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">scalar</span> <span class="nv">repeater</span> <span class="nv">pointer</span><span class="p">)</span>
<span class="p">(</span><span class="nv">scalar</span> <span class="nv">repeater-day</span> <span class="nv">pointer</span><span class="p">)</span>
<span class="p">((</span><span class="nv">?</span> <span class="nv">scalar</span><span class="p">)</span> <span class="nv">repeater</span> <span class="nv">pointer</span><span class="p">)</span>
</code></pre></div></div>

<p>The last example shows a pattern with an optional tag – <code class="language-plaintext highlighter-rouge">(? scalar)</code>. It will
match tokens with or without the scalar e.g. both “20 days ago” and “week ago”
will match.</p>

<p>Our pattern matching engine also allows us to match an entire pattern class. For
example,</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">repeater-month-name</span> <span class="nv">scalar-day</span> <span class="p">(</span><span class="nv">?</span> <span class="nv">separator-at</span><span class="p">)</span> <span class="p">(</span><span class="nv">?</span> <span class="nv">p</span> <span class="nb">time</span><span class="p">))</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">(? p time)</code> here means that any pattern that belongs to the <code class="language-plaintext highlighter-rouge">TIME</code> pattern
class can match. So all of “January 1 at 12:30”, “January 1 at 2 PM” and
“January 1 at 6 in the evening” will match without us needing to duplicate all
the time patterns.</p>

<p><em>Note:</em> There’s one limitation – a pattern class can only be specified at the
end of a pattern in Chronicity. So a pattern like <code class="language-plaintext highlighter-rouge">(repeater (p time) pointer)</code>
won’t work. This will be fixed in the future.</p>

<p>Each pattern has a handler function that decides how to convert the matching
tokens to a date span.</p>

<p>A pattern and its handler function are defined using the
<a href="https://github.com/chaitanyagupta/chronicity/blob/v0.4.1/src/handlers.lisp#L29"><code class="language-plaintext highlighter-rouge">DEFINE-HANDLER</code></a> macro. It assigns one or more patterns to a
pattern class, and if either of these patterns match, the function body is
run. Its general form is:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">define-handler</span> <span class="p">(</span><span class="nv">pattern-class</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">tokens-var</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">pattern1</span> <span class="nv">pattern2</span> <span class="o">...</span><span class="p">)</span>
  <span class="o">...</span> <span class="nv">body</span> <span class="o">...</span>
  <span class="p">)</span>
</code></pre></div></div>

<p>An example handler is shown below.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">define-handler</span> <span class="p">(</span><span class="nv">date</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">tokens</span><span class="p">)</span>
    <span class="p">((</span><span class="nv">repeater-month-name</span> <span class="nv">scalar-year</span><span class="p">))</span>
  <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">month-name</span> <span class="p">(</span><span class="nv">token-tag-type</span> <span class="ss">'repeater-month-name</span> <span class="p">(</span><span class="nb">first</span> <span class="nv">tokens</span><span class="p">)))</span>
         <span class="p">(</span><span class="nv">month</span> <span class="p">(</span><span class="nv">month-index</span> <span class="nv">month-name</span><span class="p">))</span>
         <span class="p">(</span><span class="nv">year</span> <span class="p">(</span><span class="nv">token-tag-type</span> <span class="ss">'scalar-year</span> <span class="p">(</span><span class="nb">second</span> <span class="nv">tokens</span><span class="p">)))</span>
         <span class="p">(</span><span class="nv">start</span> <span class="p">(</span><span class="nv">make-date</span> <span class="nv">year</span> <span class="nv">month</span><span class="p">)))</span>
    <span class="p">(</span><span class="nv">make-span</span> <span class="nv">start</span> <span class="p">(</span><span class="nv">datetime-incr</span> <span class="nv">start</span> <span class="ss">:month</span><span class="p">))))</span>
</code></pre></div></div>

<p>Most handler functions will use make use of the the repeater methods <code class="language-plaintext highlighter-rouge">R-NEXT</code>,
<code class="language-plaintext highlighter-rouge">R-THIS</code> and <code class="language-plaintext highlighter-rouge">R-OFFSET</code> that we described above.</p>

<p>Chronicity implements this pattern matching logic in the
<a href="https://github.com/chaitanyagupta/chronicity/blob/v0.4.1/src/handlers.lisp#L88"><code class="language-plaintext highlighter-rouge">TOKENS-TO-SPAN</code></a> function. All the patterns and their handler
functions are defined inside <a href="https://github.com/chaitanyagupta/chronicity/blob/v0.4.1/src/handler-defs.lisp">handler-defs.lisp</a>. Patterns defined earlier in
the file get precedence over those defined later. If you add, remove or modify a
handler, you should reload the whole file rather than just evaluating that
handler’s definition.</p>

<h2 id="returning-the-result">Returning the result</h2>

<p>Finally, we put everything together.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">parse</span> <span class="p">(</span><span class="nv">text</span> <span class="k">&amp;key</span> <span class="p">(</span><span class="nv">guess</span> <span class="no">t</span><span class="p">))</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">tokens</span> <span class="p">(</span><span class="nv">tokenize-and-tag</span> <span class="p">(</span><span class="nv">pre-normalize</span> <span class="nv">text</span><span class="p">))))</span>
    <span class="p">(</span><span class="nv">pre-process-tokens</span> <span class="nv">tokens</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">values</span> <span class="p">(</span><span class="nv">guess-span</span> <span class="p">(</span><span class="nv">tokens-to-span</span> <span class="nv">tokens</span><span class="p">)</span> <span class="nv">guess</span><span class="p">)</span> <span class="nv">tokens</span><span class="p">)))</span>
</code></pre></div></div>

<p>By default <code class="language-plaintext highlighter-rouge">PARSE</code> will return a timestamp instead of a time span. This depends
on the value passed to the <code class="language-plaintext highlighter-rouge">:GUESS</code> keyword – see the <code class="language-plaintext highlighter-rouge">GUESS-SPAN</code> function to
see how it is interpreted. If you want to return a time span send <code class="language-plaintext highlighter-rouge">NIL</code> instead.</p>

<p>The second value that this function returns is the list of tokens alongwith all
its tags. This is useful for debugging Chronicity results in the REPL.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">CHRONICITY&gt;</span> <span class="p">(</span><span class="nv">parse</span> <span class="s">"20 days ago"</span><span class="p">)</span>
<span class="nv">@2018-12-12T12:01:53.758578+05:30</span>
<span class="p">(</span><span class="err">#</span><span class="nv">&lt;TOKEN</span> <span class="mi">20</span> <span class="nv">[SCALAR-YEAR,</span> <span class="nv">SCALAR-DAY,</span> <span class="nv">SCALAR,</span> <span class="nv">REPEATER-TIME]</span> <span class="nv">{1007639243}&gt;</span>
 <span class="err">#</span><span class="nv">&lt;TOKEN</span> <span class="nv">days</span> <span class="nv">[REPEATER-DAY]</span> <span class="nv">{10076AF5D3}&gt;</span> <span class="err">#</span><span class="nv">&lt;TOKEN</span> <span class="nv">past</span> <span class="nv">[POINTER]</span> <span class="nv">{1007553443}&gt;</span><span class="p">)</span>

<span class="nv">CHRONICITY&gt;</span> <span class="p">(</span><span class="nv">parse</span> <span class="s">"20 days ago"</span> <span class="ss">:guess</span> <span class="no">nil</span><span class="p">)</span>
<span class="err">#</span><span class="nv">&lt;SPAN</span> <span class="nv">2018-12-12T00:00:00.000000+05:30..2018-12-13T00:00:00.000000+05:30&gt;</span>
<span class="p">(</span><span class="err">#</span><span class="nv">&lt;TOKEN</span> <span class="mi">20</span> <span class="nv">[SCALAR-YEAR,</span> <span class="nv">SCALAR-DAY,</span> <span class="nv">SCALAR,</span> <span class="nv">REPEATER-TIME]</span> <span class="nv">{1001B78BC3}&gt;</span>
 <span class="err">#</span><span class="nv">&lt;TOKEN</span> <span class="nv">days</span> <span class="nv">[REPEATER-DAY]</span> <span class="nv">{1001B78C03}&gt;</span> <span class="err">#</span><span class="nv">&lt;TOKEN</span> <span class="nv">past</span> <span class="nv">[POINTER]</span> <span class="nv">{1001B78C43}&gt;</span><span class="p">)</span>
</code></pre></div></div>

<p>The actual <code class="language-plaintext highlighter-rouge">PARSE</code> function has a few more bells and whistles than the one
defined here:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">:ENDIAN-PREFERENCE</code> to parse ambiguous dates as dd/mm (<code class="language-plaintext highlighter-rouge">:LITTLE</code>) or mm/dd
(<code class="language-plaintext highlighter-rouge">:MIDDLE</code>)</li>
  <li><code class="language-plaintext highlighter-rouge">:AMBIGUOUS-TIME-RANGE</code> to specify whether a time like 5:00 is in the morning
(AM) or evening (PM).</li>
  <li><code class="language-plaintext highlighter-rouge">:CONTEXT</code> can be <code class="language-plaintext highlighter-rouge">:PAST</code>, <code class="language-plaintext highlighter-rouge">:FUTURE</code> or <code class="language-plaintext highlighter-rouge">:NONE</code>. This determines the time span
returned for strings like “this day”. See the definition of <code class="language-plaintext highlighter-rouge">R-THIS</code> above.</li>
</ul>]]></content><author><name>Chaitanya Gupta</name></author><category term="lisp" /><summary type="html"><![CDATA[In the deftask blog I described how it lets users search for tasks easily by using natural language date queries. It accomplishes this by using a natural language date and time parser I wrote a long time ago called Chronicity.]]></summary></entry><entry><title type="html">Promises and Lisp</title><link href="https://lisper.in/promises" rel="alternate" type="text/html" title="Promises and Lisp" /><published>2014-12-23T00:00:00+00:00</published><updated>2014-12-23T00:00:00+00:00</updated><id>https://lisper.in/promises</id><content type="html" xml:base="https://lisper.in/promises"><![CDATA[<p>While I had seen promises before, I didn’t really understand their
significance until I read Domenic Denicola’s
<a href="https://blog.domenic.me/youre-missing-the-point-of-promises/">You’re Missing the Point of Promises</a>. Its an
enlightening essay and I highly recommend reading it. Ever since, I
have looked to use promises where possible. I have also thought a bit
about how one might use these constructs in Common Lisp.</p>

<h3 id="contents">Contents</h3>

<ul>
  <li><a href="#the-point-of-promises">The point of promises</a></li>
  <li><a href="#promises-in-lisp">Promises in Lisp</a></li>
  <li><a href="#macros">Macros</a></li>
  <li><a href="#putting-things-together">Putting things together</a></li>
</ul>

<h2 id="the-point-of-promises">The point of promises</h2>

<p>Here’s a brief summary: a promise is an object that acts as a proxy
for a result that is initially unknown, usually because the
computation of its value is yet incomplete.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup> In other words, they
allow you to transform an async program from continuation passing
style:<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup></p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">getTweetsFor</span><span class="p">(</span><span class="dl">"</span><span class="s2">domenic</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">results</span><span class="p">)</span> <span class="p">{</span>
  <span class="c1">// the rest of your code goes here.</span>
<span class="p">});</span>
</code></pre></div></div>

<p>to one where your functions return an object which represents the
eventual results of that operation:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">promiseForTweets</span> <span class="o">=</span> <span class="nx">getTweetsFor</span><span class="p">(</span><span class="dl">"</span><span class="s2">domenic</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">promiseForTweets</span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">results</span><span class="p">)</span> <span class="p">{</span>
  <span class="c1">// success handler</span>
<span class="p">},</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
  <span class="c1">// error handler</span>
<span class="p">});</span>
</code></pre></div></div>
<center><i>Source: [You're Missing the Point of Promises][domenic-promises]</i></center>

<p>The function <code class="language-plaintext highlighter-rouge">then</code> allows you to add a success and an error handler
to a promise. When the promise is fulfilled (i.e. the computation
completes successfully), the result is passed to the success
handler. And if the promise fails (the computation errors out), the
error is sent to the error handler.</p>

<p>There’s more though. <code class="language-plaintext highlighter-rouge">then</code> returns a new promise. That promise is
fulfilled when the relevant handler returns successfully and gets
rejected when it errors out. In addition, if the handler itself
returns a promise, the state of the promise returned by <code class="language-plaintext highlighter-rouge">then</code> depends
on this new promise.</p>

<p>All of this allows you to write asynchronous code:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">getTweetsFor</span><span class="p">(</span><span class="dl">"</span><span class="s2">domenic</span><span class="dl">"</span><span class="p">)</span> <span class="c1">// promise-returning function</span>
  <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">tweets</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">shortUrls</span> <span class="o">=</span> <span class="nx">parseTweetsForUrls</span><span class="p">(</span><span class="nx">tweets</span><span class="p">);</span>
    <span class="kd">var</span> <span class="nx">mostRecentShortUrl</span> <span class="o">=</span> <span class="nx">shortUrls</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
    <span class="k">return</span> <span class="nx">expandUrlUsingTwitterApi</span><span class="p">(</span><span class="nx">mostRecentShortUrl</span><span class="p">);</span> <span class="c1">// promise-returning function</span>
  <span class="p">})</span>
  <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">httpGet</span><span class="p">)</span> <span class="c1">// promise-returning function</span>
  <span class="p">.</span><span class="nx">then</span><span class="p">(</span>
    <span class="kd">function</span> <span class="p">(</span><span class="nx">responseBody</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Most recent link text:</span><span class="dl">"</span><span class="p">,</span> <span class="nx">responseBody</span><span class="p">);</span>
    <span class="p">},</span>
    <span class="kd">function</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">"</span><span class="s2">Error with the twitterverse:</span><span class="dl">"</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
    <span class="p">}</span>
  <span class="p">);</span>
</code></pre></div></div>

<p>that parallels the synchronous code:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">try</span> <span class="p">{</span>
  <span class="kd">var</span> <span class="nx">tweets</span> <span class="o">=</span> <span class="nx">getTweetsFor</span><span class="p">(</span><span class="dl">"</span><span class="s2">domenic</span><span class="dl">"</span><span class="p">);</span> <span class="c1">// blocking</span>
  <span class="kd">var</span> <span class="nx">shortUrls</span> <span class="o">=</span> <span class="nx">parseTweetsForUrls</span><span class="p">(</span><span class="nx">tweets</span><span class="p">);</span>
  <span class="kd">var</span> <span class="nx">mostRecentShortUrl</span> <span class="o">=</span> <span class="nx">shortUrls</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
  <span class="kd">var</span> <span class="nx">responseBody</span> <span class="o">=</span> <span class="nx">httpGet</span><span class="p">(</span><span class="nx">expandUrlUsingTwitterApi</span><span class="p">(</span><span class="nx">mostRecentShortUrl</span><span class="p">));</span> <span class="c1">// blocking x 2</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Most recent link text:</span><span class="dl">"</span><span class="p">,</span> <span class="nx">responseBody</span><span class="p">);</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">"</span><span class="s2">Error with the twitterverse: </span><span class="dl">"</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<center><i>Source: [You're Missing the Point of Promises][domenic-promises]</i></center>

<p>which is much nicer than the callback hell that you get otherwise.</p>

<p>What I have summarized here doesn’t really do justice to the subject,
so if all of this is not very clear, do go through
<a href="https://blog.domenic.me/youre-missing-the-point-of-promises/">Domenic’s post</a> to get a better idea.</p>

<h2 id="promises-in-lisp">Promises in Lisp</h2>

<p>Before we look at promises in Lisp, its worth seeing what a
synchronous version of the Javascript code above might look like in
Common Lisp:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">handler-case</span>
    <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">tweets</span> <span class="p">(</span><span class="nv">get-tweets-for</span> <span class="nv">user</span><span class="p">))</span>
           <span class="p">(</span><span class="nv">short-urls</span> <span class="p">(</span><span class="nv">parse-tweets-for-urls</span> <span class="nv">tweets</span><span class="p">))</span>
           <span class="p">(</span><span class="nv">expanded-url</span> <span class="p">(</span><span class="nv">expand-url-using-twitter-api</span> <span class="p">(</span><span class="nb">elt</span> <span class="nv">short-urls</span> <span class="mi">0</span><span class="p">)))</span>
           <span class="p">(</span><span class="nv">response-body</span> <span class="p">(</span><span class="nv">http-get</span> <span class="nv">expanded-url</span><span class="p">)))</span>
      <span class="p">(</span><span class="nb">format</span> <span class="no">t</span> <span class="s">"Most recent link text: ~A~%"</span> <span class="nv">response-body</span><span class="p">))</span>
  <span class="p">(</span><span class="nb">error</span> <span class="p">(</span><span class="nv">c</span><span class="p">)</span> <span class="p">(</span><span class="nb">format</span> <span class="no">t</span> <span class="s">"Got error: ~A~%"</span> <span class="nv">c</span><span class="p">)))</span>
</code></pre></div></div>

<p>Assume that we have an implementation of promises like the one
described above<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup>, how would our promises based code look?</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">then</span> <span class="p">(</span><span class="nv">then</span> <span class="p">(</span><span class="nv">then</span> <span class="p">(</span><span class="nv">get-tweets-for</span> <span class="nv">user</span><span class="p">)</span>
                  <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">tweets</span><span class="p">)</span>
                    <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">short-urls</span> <span class="p">(</span><span class="nv">parse-tweets-for-urls</span> <span class="nv">tweets</span><span class="p">)))</span>
                      <span class="p">(</span><span class="nv">expand-url-using-twitter-api</span> <span class="p">(</span><span class="nb">elt</span> <span class="nv">short-urls</span> <span class="mi">0</span><span class="p">)))))</span>
            <span class="nf">#'</span><span class="nv">http-get</span><span class="p">)</span>
      <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">body</span><span class="p">)</span>
        <span class="p">(</span><span class="nb">format</span> <span class="no">t</span> <span class="s">"Most recent link text: ~A~%"</span> <span class="nv">body</span><span class="p">))</span>
      <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nb">error</span><span class="p">)</span>
        <span class="p">(</span><span class="nb">format</span> <span class="no">t</span> <span class="s">"Got an error: ~A~%"</span> <span class="nb">error</span><span class="p">)))</span>
</code></pre></div></div>

<p>Certainly not as good as Javascript. We could do a little better by
binding the promises in a <code class="language-plaintext highlighter-rouge">LET*</code>:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">tweets-promise</span> <span class="p">(</span><span class="nv">get-tweets-for</span> <span class="nv">user</span><span class="p">))</span>
       <span class="p">(</span><span class="nv">short-urls-promise</span> <span class="p">(</span><span class="nv">then</span> <span class="nv">tweets-promise</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">tweets</span><span class="p">)</span>
                                                  <span class="p">(</span><span class="nv">parse-tweets-for-urls</span> <span class="nv">tweets</span><span class="p">))))</span>
       <span class="p">(</span><span class="nv">expanded-url-promise</span> <span class="p">(</span><span class="nv">then</span> <span class="nv">short-urls-promise</span>
                                   <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">short-urls</span><span class="p">)</span>
                                     <span class="p">(</span><span class="nv">expand-url-using-twitter-api</span> <span class="p">(</span><span class="nb">elt</span> <span class="nv">short-urls</span> <span class="mi">0</span><span class="p">)))))</span>
       <span class="p">(</span><span class="nv">response-body-promise</span> <span class="p">(</span><span class="nv">then</span> <span class="nv">expanded-url-promise</span> <span class="nf">#'</span><span class="nv">http-get</span><span class="p">)))</span>
  <span class="p">(</span><span class="nv">then</span> <span class="nv">response-body-promise</span>
        <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">response-body</span><span class="p">)</span>
          <span class="p">(</span><span class="nb">format</span> <span class="no">t</span> <span class="s">"Most recent link text: ~A~%"</span> <span class="nv">response-body</span><span class="p">))</span>
        <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nb">error</span><span class="p">)</span>
          <span class="p">(</span><span class="nb">format</span> <span class="no">t</span> <span class="s">"Got an error: ~A~%"</span> <span class="nb">error</span><span class="p">))))</span>
</code></pre></div></div>

<p>But the result still leaves a lot to be desired. If only Lisp had the
dot notation like Javascript…</p>

<h2 id="macros">Macros</h2>

<p>Lisp doesn’t have the dot notation, but it does have another trick up
its sleeve – macros. Can macros help us bridge the gap between the
synchronous and async variants?</p>

<p>Let’s start with a simple macro, <code class="language-plaintext highlighter-rouge">PROMISE-VALUES-BIND</code>:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defmacro</span> <span class="nv">promise-values-bind</span> <span class="p">(</span><span class="nv">var-list</span> <span class="nv">form</span> <span class="k">&amp;body</span> <span class="nv">body</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nb">values</span> <span class="p">(</span><span class="nb">gensym</span> <span class="s">"VALUES-"</span><span class="p">)))</span>
    <span class="o">`</span><span class="p">(</span><span class="k">multiple-value-call</span>
         <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="k">&amp;rest</span> <span class="o">,</span><span class="nb">values</span><span class="p">)</span>
           <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nv">promisep</span> <span class="p">(</span><span class="nb">first</span> <span class="o">,</span><span class="nb">values</span><span class="p">))</span>
               <span class="p">(</span><span class="nv">then</span> <span class="p">(</span><span class="nb">first</span> <span class="o">,</span><span class="nb">values</span><span class="p">)</span>
                           <span class="p">(</span><span class="k">lambda</span> <span class="o">,</span><span class="nv">var-list</span>
                             <span class="o">,@</span><span class="nv">body</span><span class="p">))</span>
               <span class="p">(</span><span class="nb">destructuring-bind</span> <span class="o">,</span><span class="nv">var-list</span>
                   <span class="o">,</span><span class="nb">values</span>
                 <span class="o">,@</span><span class="nv">body</span><span class="p">)))</span>
       <span class="o">,</span><span class="nv">form</span><span class="p">)))</span>
</code></pre></div></div>

<p>This macro is quite similar to <code class="language-plaintext highlighter-rouge">MULTIPLE-VALUE-BIND</code>. It evalues the
given <code class="language-plaintext highlighter-rouge">form</code>, and binds its values to the variables in <code class="language-plaintext highlighter-rouge">var-list</code>. If
the <code class="language-plaintext highlighter-rouge">form</code> returned a promise as its first value, then instead of
binding immediately, it waits for the promise to be fulfilled and
binds <code class="language-plaintext highlighter-rouge">var-list</code> to the resolved values.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">promise-values-bind</span> <span class="p">(</span><span class="nv">quotient</span> <span class="nv">remainder</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">values</span> <span class="mi">10</span> <span class="mi">3</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">format</span> <span class="no">t</span> <span class="s">"First: ~A, Second: ~A~%"</span> <span class="nv">quotient</span> <span class="nv">remainder</span><span class="p">))</span>
<span class="c1">;; =&gt;</span>
<span class="c1">; First: 10, Second: 3</span>
<span class="nv">NIL</span>


<span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">promise</span> <span class="p">(</span><span class="nv">make-promise</span><span class="p">)))</span>
  <span class="p">(</span><span class="nv">promise-values-bind</span> <span class="p">(</span><span class="nv">quotient</span> <span class="nv">remainder</span><span class="p">)</span>
      <span class="nv">promise</span>
    <span class="p">(</span><span class="nb">format</span> <span class="no">t</span> <span class="s">"First: ~A, Second: ~A~%"</span> <span class="nv">quotient</span> <span class="nv">remainder</span><span class="p">))</span>
  <span class="nv">promise</span><span class="p">)</span>
<span class="c1">;; =&gt;</span>
<span class="err">#</span><span class="nv">&lt;PROMISE</span> <span class="nv">Un</span> <span class="nv">{1004F93643}&gt;</span>

<span class="p">(</span><span class="nv">fulfill</span> <span class="nb">*</span> <span class="mi">10</span> <span class="mi">3</span><span class="p">)</span>
<span class="c1">;; =&gt;</span>
<span class="c1">; First: 10, Second: 3</span>
<span class="nv">NIL</span>
</code></pre></div></div>

<p>Using <code class="language-plaintext highlighter-rouge">PROMISE-VALUES-BIND</code>, we write a promise based variant of
<code class="language-plaintext highlighter-rouge">PROGN</code>. We will give it the same name but define it in a new package,
<code class="language-plaintext highlighter-rouge">PCL</code>.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defmacro</span> <span class="nv">pcl:progn</span> <span class="p">(</span><span class="k">&amp;body</span> <span class="nv">forms</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">cond</span> <span class="p">((</span><span class="nb">null</span> <span class="nv">forms</span><span class="p">)</span> <span class="no">nil</span><span class="p">)</span>
        <span class="p">((</span><span class="nb">null</span> <span class="p">(</span><span class="nb">rest</span> <span class="nv">forms</span><span class="p">))</span> <span class="p">(</span><span class="nb">first</span> <span class="nv">forms</span><span class="p">))</span>
        <span class="p">(</span><span class="no">t</span> <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">x</span> <span class="p">(</span><span class="nb">gensym</span> <span class="s">"X-"</span><span class="p">)))</span>
             <span class="o">`</span><span class="p">(</span><span class="nv">promise-values-bind</span> <span class="p">(</span><span class="k">&amp;rest</span> <span class="o">,</span><span class="nv">x</span><span class="p">)</span>
                  <span class="o">,</span><span class="p">(</span><span class="nb">first</span> <span class="nv">forms</span><span class="p">)</span>
                <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">ignore</span> <span class="o">,</span><span class="nv">x</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">pcl:progn</span> <span class="o">,@</span><span class="p">(</span><span class="nb">rest</span> <span class="nv">forms</span><span class="p">)))))))</span>
</code></pre></div></div>

<p>Just like its CL counterpart, <code class="language-plaintext highlighter-rouge">PCL:PROGN</code> evaluates the given forms
sequentially. However if any of the forms returns a promise, this
macro waits for the promise to be resolved before evaluating the next
form.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">start</span> <span class="p">(</span><span class="nb">get-universal-time</span><span class="p">)))</span>
  <span class="p">(</span><span class="k">flet</span> <span class="p">((</span><span class="nv">delta-now</span> <span class="p">()</span> 
           <span class="p">(</span><span class="nb">format</span> <span class="no">t</span> <span class="s">"~&amp;t + ~A sec~%"</span> <span class="p">(</span><span class="nb">-</span> <span class="p">(</span><span class="nb">get-universal-time</span><span class="p">)</span> <span class="nv">start</span><span class="p">))))</span>
    <span class="p">(</span><span class="nv">pcl:progn</span> <span class="p">(</span><span class="nb">princ</span> <span class="mi">1</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">delta-now</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">pcl:sleep</span> <span class="mi">2</span><span class="p">)</span>
               <span class="p">(</span><span class="nb">princ</span> <span class="mi">2</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">delta-now</span><span class="p">)</span>
               <span class="p">(</span><span class="nb">princ</span> <span class="mi">3</span><span class="p">))))</span>
<span class="c1">; 1</span>
<span class="c1">; t + 0 sec</span>
<span class="c1">; 2</span>
<span class="c1">; t + 2 sec</span>
<span class="c1">; 3</span>
</code></pre></div></div>

<p>The function <code class="language-plaintext highlighter-rouge">PCL:SLEEP</code> schedules a timer on a runloop and returns a
promise that is resolved when the timer expires. In this example, the
last two forms are executed only after the promise returned by
<code class="language-plaintext highlighter-rouge">PCL:SLEEP</code> is resolved.</p>

<p>Moreover, if any form signals an error, or any promise is rejected,
the remaining forms are not evaluated.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">start</span> <span class="p">(</span><span class="nb">get-universal-time</span><span class="p">)))</span>
  <span class="p">(</span><span class="k">flet</span> <span class="p">((</span><span class="nv">delta-now</span> <span class="p">()</span> 
           <span class="p">(</span><span class="nb">format</span> <span class="no">t</span> <span class="s">"~&amp;t + ~A sec~%"</span> <span class="p">(</span><span class="nb">-</span> <span class="p">(</span><span class="nb">get-universal-time</span><span class="p">)</span> <span class="nv">start</span><span class="p">))))</span>
    <span class="p">(</span><span class="nv">pcl:progn</span> <span class="p">(</span><span class="nb">princ</span> <span class="mi">1</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">delta-now</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">pcl:sleep</span> <span class="mi">2</span><span class="p">)</span>
               <span class="p">(</span><span class="nb">princ</span> <span class="mi">2</span><span class="p">)</span>
               <span class="p">(</span><span class="nb">error</span> <span class="s">"foo"</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">delta-now</span><span class="p">)</span>
               <span class="p">(</span><span class="nb">princ</span> <span class="mi">3</span><span class="p">))))</span>
<span class="c1">; 1</span>
<span class="c1">; t + 0 sec</span>
<span class="c1">; 2</span>
<span class="c1">;; At this point, the debugger is invoked with #&lt;SIMPLE-ERROR "foo" {1007381233}&gt;</span>
</code></pre></div></div>

<p>Next up is <code class="language-plaintext highlighter-rouge">PCL:LET*</code>, our variant of <code class="language-plaintext highlighter-rouge">LET*</code>. Bindings are performed
sequentially, and if an init-form returns a promise, the binding is
delayed until the promise is resolved. Also, the body of <code class="language-plaintext highlighter-rouge">PCL:LET*</code> is
evaluated within the context of <code class="language-plaintext highlighter-rouge">PCL:PROGN</code> instead of <code class="language-plaintext highlighter-rouge">PROGN</code>.<sup id="fnref:4" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup></p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defmacro</span> <span class="nv">pcl:let*</span> <span class="p">(</span><span class="nv">bindings</span> <span class="k">&amp;body</span> <span class="nv">body</span><span class="p">)</span>
  <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">null</span> <span class="nv">bindings</span><span class="p">)</span>
      <span class="o">`</span><span class="p">(</span><span class="nv">pcl:progn</span> <span class="o">,@</span><span class="nv">body</span><span class="p">)</span>
      <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">binding</span> <span class="p">(</span><span class="nb">first</span> <span class="nv">bindings</span><span class="p">)))</span>
        <span class="o">`</span><span class="p">(</span><span class="nv">promise-values-bind</span> <span class="p">(</span><span class="o">,</span><span class="p">(</span><span class="nb">first</span> <span class="nv">binding</span><span class="p">))</span>
             <span class="o">,</span><span class="p">(</span><span class="nb">second</span> <span class="nv">binding</span><span class="p">)</span>
           <span class="p">(</span><span class="nv">pcl:let*</span> <span class="o">,</span><span class="p">(</span><span class="nb">rest</span> <span class="nv">bindings</span><span class="p">)</span>
             <span class="o">,@</span><span class="nv">body</span><span class="p">)))))</span>

<span class="p">(</span><span class="nv">pcl:let*</span> <span class="p">((</span><span class="nv">a</span> <span class="p">(</span><span class="nv">pcl:progn</span> <span class="p">(</span><span class="nv">pcl:sleep</span> <span class="mi">1</span><span class="p">)</span> <span class="mi">10</span><span class="p">))</span>
           <span class="p">(</span><span class="nv">b</span> <span class="p">(</span><span class="nv">pcl:progn</span> <span class="p">(</span><span class="nv">pcl:sleep</span> <span class="mi">2</span><span class="p">)</span> <span class="mi">20</span><span class="p">)))</span>
  <span class="p">(</span><span class="nb">print</span> <span class="p">(</span><span class="nb">+</span> <span class="nv">a</span> <span class="nv">b</span><span class="p">)))</span>
<span class="c1">; 30</span>
</code></pre></div></div>

<p>And <code class="language-plaintext highlighter-rouge">PCL:HANDLER-CASE</code> is the promised counterpart of <code class="language-plaintext highlighter-rouge">HANDLER-CASE</code>.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defmacro</span> <span class="nv">pcl:handler-case</span> <span class="p">(</span><span class="nv">expression</span> <span class="k">&amp;rest</span> <span class="nv">clauses</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nb">values</span> <span class="p">(</span><span class="nb">gensym</span> <span class="s">"VALUES-"</span><span class="p">))</span>
        <span class="p">(</span><span class="nv">c</span> <span class="p">(</span><span class="nb">gensym</span> <span class="s">"C-"</span><span class="p">))</span>
        <span class="p">(</span><span class="nv">clauses</span> <span class="p">(</span><span class="nb">mapcar</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">clause</span><span class="p">)</span>
                           <span class="p">(</span><span class="nb">destructuring-bind</span> <span class="p">(</span><span class="k">type</span> <span class="p">(</span><span class="k">&amp;rest</span> <span class="nv">vars</span><span class="p">)</span> <span class="k">&amp;body</span> <span class="nv">body</span><span class="p">)</span>
                               <span class="nv">clause</span>
                             <span class="o">`</span><span class="p">(</span><span class="o">,</span><span class="k">type</span> <span class="o">,</span><span class="nv">vars</span> <span class="p">(</span><span class="nv">pcl:progn</span> <span class="o">,@</span><span class="nv">body</span><span class="p">))))</span>
                         <span class="nv">clauses</span><span class="p">)))</span>
    <span class="o">`</span><span class="p">(</span><span class="nb">handler-case</span>
         <span class="p">(</span><span class="k">multiple-value-call</span>
             <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="k">&amp;rest</span> <span class="o">,</span><span class="nb">values</span><span class="p">)</span>
               <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nv">promisep</span> <span class="p">(</span><span class="nb">first</span> <span class="o">,</span><span class="nb">values</span><span class="p">))</span>
                   <span class="p">(</span><span class="nv">then</span> <span class="p">(</span><span class="nb">first</span> <span class="o">,</span><span class="nb">values</span><span class="p">)</span>
                         <span class="no">nil</span>
                         <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="o">,</span><span class="nv">c</span><span class="p">)</span>
                           <span class="p">(</span><span class="nb">handler-case</span> <span class="p">(</span><span class="nb">signal</span> <span class="o">,</span><span class="nv">c</span><span class="p">)</span>
                             <span class="o">,@</span><span class="nv">clauses</span><span class="p">)))</span>
                   <span class="p">(</span><span class="nb">values-list</span> <span class="o">,</span><span class="nb">values</span><span class="p">)))</span>
           <span class="o">,</span><span class="nv">expression</span><span class="p">)</span>
       <span class="o">,@</span><span class="nv">clauses</span><span class="p">)))</span>
</code></pre></div></div>

<h2 id="putting-things-together">Putting things together</h2>

<p>With these macros in place, its time to see the result. Our promise
based async code looks like this:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">pcl:handler-case</span>
    <span class="p">(</span><span class="nv">pcl:let*</span> <span class="p">((</span><span class="nv">tweets</span> <span class="p">(</span><span class="nv">get-tweets-for</span> <span class="nv">user</span><span class="p">))</span>
               <span class="p">(</span><span class="nv">short-urls</span> <span class="p">(</span><span class="nv">parse-tweets-for-urls</span> <span class="nv">tweets</span><span class="p">))</span>
               <span class="p">(</span><span class="nv">expanded-url</span> <span class="p">(</span><span class="nv">expand-url-using-twitter-api</span> <span class="p">(</span><span class="nb">elt</span> <span class="nv">short-urls</span> <span class="mi">0</span><span class="p">)))</span>
               <span class="p">(</span><span class="nv">response-body</span> <span class="p">(</span><span class="nv">http-get</span> <span class="nv">expanded-url</span><span class="p">)))</span>
      <span class="p">(</span><span class="nb">format</span> <span class="no">t</span> <span class="s">"Most recent link text: ~A~%"</span> <span class="nv">response-body</span><span class="p">))</span>
  <span class="p">(</span><span class="nb">error</span> <span class="p">(</span><span class="nv">c</span><span class="p">)</span> <span class="p">(</span><span class="nb">format</span> <span class="no">t</span> <span class="s">"Got error: ~A~%"</span> <span class="nv">c</span><span class="p">)))</span>
</code></pre></div></div>

<p>Except for the change in symbol packages, our async code looks
<em>identical</em> to the synchronous code. While the rest of the world waits
for the language gods to provide the right
<a href="http://davidwalsh.name/async-generators">syntactic tools</a>, Lispers can just write macros 😄</p>

<p>These were just three forms, we can go a lot further than this. Add
promised counterparts for a few more special forms and macros like
<code class="language-plaintext highlighter-rouge">UNWIND-PROTECT</code>, <code class="language-plaintext highlighter-rouge">LAMBDA</code>, <code class="language-plaintext highlighter-rouge">DEFUN</code>, <code class="language-plaintext highlighter-rouge">IF</code>, etc. and you end up with a
set that starts to become useful.</p>

<p>Add promised variants of blocking I/O functions like <code class="language-plaintext highlighter-rouge">READ-CHAR</code>,
<code class="language-plaintext highlighter-rouge">WRITE-CHAR</code>, <code class="language-plaintext highlighter-rouge">READ-BYTES</code>, etc. and you end up with a nice little
async I/O framework.<sup id="fnref:5" role="doc-noteref"><a href="#fn:5" class="footnote" rel="footnote">5</a></sup></p>

<p>Debugging is a bit of a challenge with promises. Backtraces become
pretty much useless, although that’s usually the case with callback
hell too. Its also not as convenient to step through an async program
as it is with synchronous code.</p>

<p>However, all said and done, the combination of macros and promises
still holds great promise 😉</p>

<p>Source code to accompany this post is available on
<a href="https://github.com/chaitanyagupta/promises">github</a>. It contains a working implementation of promises,
though you shouldn’t use it to write any serious code (try
<a href="http://orthecreedence.github.io/blackbird/">Blackbird</a> if you want a practical implementation of promises).</p>

<p><i>Discuss on <a href="https://news.ycombinator.com/item?id=8788277">Hacker News</a> or
<a href="http://www.reddit.com/r/lisp/comments/2q6elh/promises_and_lisp/">/r/lisp</a>.</i></p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>Definition from <a href="http://en.wikipedia.org/wiki/Futures_and_promises">Wikipedia</a> <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>Source for the Javascript code examples and most of the content in the first section is Domenic’s <a href="https://blog.domenic.me/youre-missing-the-point-of-promises/">aforementioned post</a>. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>Since Lisp functions can return multiple values, the success handler for the <code class="language-plaintext highlighter-rouge">THEN</code> block in Lisp could be sent multiple arguments instead of just one. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:4" role="doc-endnote">
      <p>Handling of the body in <code class="language-plaintext highlighter-rouge">PCL:LET*</code> is incomplete here. <code class="language-plaintext highlighter-rouge">LET/LET*</code> allow optional <a href="http://www.lispworks.com/documentation/HyperSpec/Body/s_declar.htm#declare">DECLARE</a> forms to precede the body, so <code class="language-plaintext highlighter-rouge">PCL:LET*</code> should too. I have chosen to ignore this but it shouldn’t be very hard to do. <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:5" role="doc-endnote">
      <p>Not sure if such a framework exists in CL today. <a href="https://github.com/orthecreedence/cl-async">cl-async</a> seems to do some of it but not all. <a href="#fnref:5" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Chaitanya Gupta</name></author><category term="lisp" /><summary type="html"><![CDATA[While I had seen promises before, I didn’t really understand their significance until I read Domenic Denicola’s You’re Missing the Point of Promises. Its an enlightening essay and I highly recommend reading it. Ever since, I have looked to use promises where possible. I have also thought a bit about how one might use these constructs in Common Lisp.]]></summary></entry><entry><title type="html">Reader Macros in Common Lisp</title><link href="https://lisper.in/reader-macros" rel="alternate" type="text/html" title="Reader Macros in Common Lisp" /><published>2014-03-03T00:00:00+00:00</published><updated>2014-03-03T00:00:00+00:00</updated><id>https://lisper.in/reader-macros</id><content type="html" xml:base="https://lisper.in/reader-macros"><![CDATA[<p><em>This post originally appeared as a <a href="https://gist.github.com/chaitanyagupta/9324402">github gist</a>.</em></p>

<p>Reader macros are perhaps not as famous as ordinary macros. While macros are a great way to create your own DSL, reader macros provide even greater flexibility by allowing you to create entirely new syntax on top of Lisp.</p>

<p>Paul Graham explains them very well in <a href="http://www.paulgraham.com/onlisp.html">On Lisp</a> (Chapter 17, Read-Macros):</p>

<blockquote>
  <p>The three big moments in a Lisp expression’s life are read-time, compile-time, and runtime. Functions are in control at runtime. Macros give us a chance to perform transformations on programs at compile-time. …read-macros… do their work at read-time.</p>
</blockquote>

<blockquote>
  <p>Macros and read-macros see your program at different stages. Macros get hold of the program when it has already been parsed into Lisp objects by the reader, and read-macros operate on a program while it is still text. However, by invoking read on this text, a read-macro can, if it chooses, get parsed Lisp objects as well. Thus read-macros are at least as powerful as ordinary macros.</p>
</blockquote>

<p>(Note that read-macros and reader macros mean the same thing)</p>

<p>The Lisp reader is the thing that parses and translates raw text into an AST. In Lisp, the AST is better known as an s-expression (or sexp) – its either an <a href="http://www.lispworks.com/documentation/HyperSpec/Body/t_atom.htm">atom</a> or a <a href="http://www.lispworks.com/documentation/HyperSpec/Body/t_list.htm">list</a>.</p>

<p>Reader macros allow you to modify the behaviour of the Lisp reader.</p>

<h3 id="contents">Contents</h3>

<ul>
  <li><a href="#invoking-the-lisp-reader">Invoking the Lisp reader</a></li>
  <li><a href="#quote">Quote</a></li>
  <li><a href="#json">JSON</a></li>
  <li><a href="#refining-the-json-reader">Refining the JSON reader</a></li>
  <li><a href="#packaging-the-new-syntax">Packaging the new syntax</a></li>
  <li><a href="#conclusion">Conclusion</a></li>
  <li><a href="#notes">Notes</a></li>
</ul>

<h2 id="invoking-the-lisp-reader">Invoking the Lisp reader</h2>

<p>Not only can you modify the behaviour of the Lisp reader, you can also invoke it. The simplest way to invoke the Lisp reader is to call the function <a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_rd_rd.htm"><code class="language-plaintext highlighter-rouge">READ</code></a>. When you call <code class="language-plaintext highlighter-rouge">READ</code> with no arguments, it reads text from the standard input and returns an s-expression as soon as it fully parses one.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; (read)
;; Provide this input: foo
FOO

&gt; (read)
;; Input: (foo 1 2 3)
(FOO 1 2 3)
</code></pre></div></div>

<p>The full syntax of <code class="language-plaintext highlighter-rouge">READ</code> looks like this:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">read</span> <span class="k">&amp;optional</span> <span class="nv">input-stream</span> <span class="nv">eof-error-p</span> <span class="nv">eof-value</span> <span class="nv">recursive-p</span><span class="p">)</span> <span class="nv">=&gt;</span> <span class="nv">object</span>
</code></pre></div></div>

<p>All the arguments to <code class="language-plaintext highlighter-rouge">READ</code> are optional. The first is the input stream; <code class="language-plaintext highlighter-rouge">eof-error-p</code> and <code class="language-plaintext highlighter-rouge">eof-value</code> specify end of file handling; <code class="language-plaintext highlighter-rouge">recursive-p</code> should be set to true whenever <code class="language-plaintext highlighter-rouge">READ</code> is called from inside another call to <code class="language-plaintext highlighter-rouge">READ</code>. When implementing reader macros, <code class="language-plaintext highlighter-rouge">recursive-p</code> should always be true.</p>

<h2 id="quote">Quote</h2>

<p>One of the simplest (and earliest) examples of a reader macro in Lisp is the single quote character <code class="language-plaintext highlighter-rouge">'</code>. This reader macro translates an expression of the form <code class="language-plaintext highlighter-rouge">'&lt;some-form&gt;</code> into <code class="language-plaintext highlighter-rouge">(quote &lt;some-form&gt;)</code>.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="ss">'foo</span>       <span class="c1">;; translated to (quote foo)</span>
<span class="o">'</span><span class="p">(</span><span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span><span class="p">)</span>   <span class="c1">;; translated to (quote (1 2 3))</span>
</code></pre></div></div>

<p>Simply put, the single quote character <code class="language-plaintext highlighter-rouge">'</code> is a little bit of syntactic sugar added on top of Lisp. Reader macros do just that – allow you to add syntactic sugar to Lisp. What makes them so powerful is that, just like ordinay macros, you write reader macros in Lisp itself. For example, <code class="language-plaintext highlighter-rouge">'</code> could be defined as:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">single-quote-reader</span> <span class="p">(</span><span class="nc">stream</span> <span class="nb">char</span><span class="p">)</span>
   <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">ignore</span> <span class="nb">char</span><span class="p">))</span>
   <span class="p">(</span><span class="nb">list</span> <span class="p">(</span><span class="k">quote</span> <span class="k">quote</span><span class="p">)</span> <span class="p">(</span><span class="nb">read</span> <span class="nc">stream</span> <span class="no">t</span> <span class="no">nil</span> <span class="no">t</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">set-macro-character</span> <span class="sc">#\'</span> <span class="nf">#'</span><span class="nv">single-quote-reader</span><span class="p">)</span>
</code></pre></div></div>

<p><a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_set_ma.htm"><code class="language-plaintext highlighter-rouge">SET-MACRO-CHARACTER</code></a> makes the Lisp reader associate the single quote character <code class="language-plaintext highlighter-rouge">'</code> with the function <code class="language-plaintext highlighter-rouge">single-quote-reader</code>. Whenever the reader encounters <code class="language-plaintext highlighter-rouge">'</code>, it calls <code class="language-plaintext highlighter-rouge">single-quote-reader</code>. This function takes two arguments – the input stream and the character in the stream that triggered the call. <code class="language-plaintext highlighter-rouge">char</code> will always be <code class="language-plaintext highlighter-rouge">'</code> in this case.</p>

<p>Let’s trace step by step how this works. Assume we call <code class="language-plaintext highlighter-rouge">READ</code> on the following form:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; (read)
;; Input: 'foo
</code></pre></div></div>

<p>When <code class="language-plaintext highlighter-rouge">READ</code> is invoked, this is how the input stream looks:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>'foo
^
</code></pre></div></div>

<p>The current position of the stream is denoted by <code class="language-plaintext highlighter-rouge">^</code>. When <code class="language-plaintext highlighter-rouge">READ</code> is called, the next character in the stream is the quote. The reader reads this character, looks for its reader macro function, finds <code class="language-plaintext highlighter-rouge">single-quote-reader</code> and calls it. Just before <code class="language-plaintext highlighter-rouge">single-quote-reader</code> is called, this is how the stream looks:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>'foo
 ^
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">single-quote-reader</code> calls <code class="language-plaintext highlighter-rouge">READ</code> again. The inner call to <code class="language-plaintext highlighter-rouge">READ</code> returns the symbol <code class="language-plaintext highlighter-rouge">foo</code>, so the return value of this function is the sexp <code class="language-plaintext highlighter-rouge">(quote foo)</code> (usually printed by the Lisp printer as <code class="language-plaintext highlighter-rouge">'foo</code>).</p>

<p>After <code class="language-plaintext highlighter-rouge">single-quote-reader</code> returns, the stream pointer moves beyond <code class="language-plaintext highlighter-rouge">foo</code>. [1]</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>'foo
    ^
</code></pre></div></div>

<h2 id="json">JSON</h2>

<p>Let’s work with a more complicated example. Let’s make the Lisp reader recognize <a href="http://json.org/">JSON</a> syntax.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; [1, 2, "foo"]
#(1 2 "foo")

&gt; { "foo": 1, "bar": 2 }
#&lt;HASH-TABLE :TEST EQUAL :COUNT 2 {1004EA5DD3}&gt;
</code></pre></div></div>

<p>We define a few constants to work with.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defconstant</span> <span class="nv">+left-bracket+</span> <span class="sc">#\[</span><span class="p">)</span>
<span class="p">(</span><span class="nb">defconstant</span> <span class="nv">+right-bracket+</span> <span class="sc">#\]</span><span class="p">)</span>
<span class="p">(</span><span class="nb">defconstant</span> <span class="nv">+left-brace+</span> <span class="sc">#\{</span><span class="p">)</span>
<span class="p">(</span><span class="nb">defconstant</span> <span class="nv">+right-brace+</span> <span class="sc">#\}</span><span class="p">)</span>
<span class="p">(</span><span class="nb">defconstant</span> <span class="nv">+comma+</span> <span class="sc">#\,</span><span class="p">)</span>
<span class="p">(</span><span class="nb">defconstant</span> <span class="nv">+colon+</span> <span class="sc">#\:</span><span class="p">)</span>
</code></pre></div></div>

<p>To read JSON arrays, we dispatch the left bracket to <code class="language-plaintext highlighter-rouge">read-left-bracket</code>.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">read-left-bracket</span> <span class="p">(</span><span class="nc">stream</span> <span class="nb">char</span><span class="p">)</span>
  <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">ignore</span> <span class="nb">char</span><span class="p">))</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="vg">*readtable*</span> <span class="p">(</span><span class="nb">copy-readtable</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+comma+</span> <span class="ss">'read-separator</span><span class="p">)</span>
    <span class="o">...</span>
    <span class="p">))</span>

<span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+left-bracket+</span> <span class="ss">'read-left-bracket</span><span class="p">)</span>
</code></pre></div></div>

<p>Note that I haven’t provided a complete definition for <code class="language-plaintext highlighter-rouge">read-left-bracket</code> yet. The <a href="http://www.lispworks.com/documentation/HyperSpec/Body/02_aa.htm">readtable</a> is an object that stores the association between characters and their reader macro functions, if any. <a href="http://www.lispworks.com/documentation/HyperSpec/Body/v_rdtabl.htm"><code class="language-plaintext highlighter-rouge">*READTABLE*</code></a> is a <a href="http://www.gigamonkeys.com/book/variables.html#dynamic-aka-special-variables">dynamic variable</a> that specifies the current readtable. <code class="language-plaintext highlighter-rouge">read-left-bracket</code> binds the current readtable to a copy of itself, and causes the comma character <code class="language-plaintext highlighter-rouge">,</code> to be associated with <code class="language-plaintext highlighter-rouge">read-separator</code> (which we will see shortly). The reason we copy and rebind the current readtable is to avoid clobbering the readtable entry for comma outside of the dynamic scope of <code class="language-plaintext highlighter-rouge">read-left-bracket</code>.</p>

<p>Here’s the complete definition for <code class="language-plaintext highlighter-rouge">read-left-bracket</code>:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">read-next-object</span> <span class="p">(</span><span class="nv">separator</span> <span class="nv">delimiter</span>
                         <span class="k">&amp;optional</span> <span class="p">(</span><span class="nv">input-stream</span> <span class="vg">*standard-input*</span><span class="p">))</span>
  <span class="p">(</span><span class="k">flet</span> <span class="p">((</span><span class="nv">peek-next-char</span> <span class="p">()</span> <span class="p">(</span><span class="nb">peek-char</span> <span class="no">t</span> <span class="nv">input-stream</span> <span class="no">t</span> <span class="no">nil</span> <span class="no">t</span><span class="p">))</span>
         <span class="p">(</span><span class="nv">discard-next-char</span> <span class="p">()</span> <span class="p">(</span><span class="nb">read-char</span> <span class="nv">input-stream</span> <span class="no">t</span> <span class="no">nil</span> <span class="no">t</span><span class="p">)))</span>
    <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">and</span> <span class="nv">delimiter</span> <span class="p">(</span><span class="nb">char=</span> <span class="p">(</span><span class="nv">peek-next-char</span><span class="p">)</span> <span class="nv">delimiter</span><span class="p">))</span>
        <span class="p">(</span><span class="k">progn</span>
          <span class="p">(</span><span class="nv">discard-next-char</span><span class="p">)</span>
          <span class="no">nil</span><span class="p">)</span>
        <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">object</span> <span class="p">(</span><span class="nb">read</span> <span class="nv">input-stream</span> <span class="no">t</span> <span class="no">nil</span> <span class="no">t</span><span class="p">))</span>
               <span class="p">(</span><span class="nv">next-char</span> <span class="p">(</span><span class="nv">peek-next-char</span><span class="p">)))</span>
          <span class="p">(</span><span class="nb">cond</span>
            <span class="p">((</span><span class="nb">char=</span> <span class="nv">next-char</span> <span class="nv">separator</span><span class="p">)</span> <span class="p">(</span><span class="nv">discard-next-char</span><span class="p">))</span>
            <span class="p">((</span><span class="nb">and</span> <span class="nv">delimiter</span> <span class="p">(</span><span class="nb">char=</span> <span class="nv">next-char</span> <span class="nv">delimiter</span><span class="p">))</span> <span class="no">nil</span><span class="p">)</span>
            <span class="p">(</span><span class="no">t</span> <span class="p">(</span><span class="nb">error</span> <span class="s">"Unexpected next char: ~S"</span> <span class="nv">next-char</span><span class="p">)))</span>
          <span class="nv">object</span><span class="p">))))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">read-left-bracket</span> <span class="p">(</span><span class="nc">stream</span> <span class="nb">char</span><span class="p">)</span>
  <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">ignore</span> <span class="nb">char</span><span class="p">))</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="vg">*readtable*</span> <span class="p">(</span><span class="nb">copy-readtable</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+comma+</span> <span class="ss">'read-separator</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">loop</span>
       <span class="nv">for</span> <span class="nv">object</span> <span class="nb">=</span> <span class="p">(</span><span class="nv">read-next-object</span> <span class="nv">+comma+</span> <span class="nv">+right-bracket+</span> <span class="nc">stream</span><span class="p">)</span>
       <span class="nv">while</span> <span class="nv">object</span>
       <span class="nv">collect</span> <span class="nv">object</span> <span class="nv">into</span> <span class="nv">objects</span>
       <span class="nv">finally</span> <span class="p">(</span><span class="nb">return</span> <span class="o">`</span><span class="p">(</span><span class="nb">vector</span> <span class="o">,@</span><span class="nv">objects</span><span class="p">)))))</span>
</code></pre></div></div>

<p>The bulk of the work of reading JSON objects is done by <code class="language-plaintext highlighter-rouge">read-next-object</code> – <code class="language-plaintext highlighter-rouge">read-left-bracket</code> calls this function repeatedly until it returns <code class="language-plaintext highlighter-rouge">NIL</code>. The list of objects is then transformed into <code class="language-plaintext highlighter-rouge">(vector obj1 obj2 ...)</code> which, at runtime, will return a Lisp vector.</p>

<p><code class="language-plaintext highlighter-rouge">read-next-object</code> takes three arguments: a delimiter, which indicates the end of a JSON array or object (i.e. right bracket or right brace); a separator, which separates objects inside a JSON array (comma) or object (comma or colon) and an optional stream argument that defaults to standard input. When <code class="language-plaintext highlighter-rouge">read-next-object</code> is first called inside an array the stream would be positioned just before the first object.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[1, 2, "foo"]
 ^
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">read-next-object</code> parses and returns the first object (the number <code class="language-plaintext highlighter-rouge">1</code> in this case), and positions the stream before the next object, discarding the separator. If there was any whitespace before the first object, it would be discarded.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[1, 2, "foo"]
   ^
</code></pre></div></div>

<p>This cycle repeats until <code class="language-plaintext highlighter-rouge">read-next-object</code> reads the last object in the array, <code class="language-plaintext highlighter-rouge">"foo"</code>. Since the next non-whitespace character after reading <code class="language-plaintext highlighter-rouge">"foo"</code> is not the separator but rather the delimiter, <code class="language-plaintext highlighter-rouge">read-next-object</code> returns <code class="language-plaintext highlighter-rouge">"foo"</code> but doesn’t try to read past the delimiter.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[1, 2, "foo"]
            ^
</code></pre></div></div>

<p>The last call to <code class="language-plaintext highlighter-rouge">read-next-object</code> notices that the next character is the delimiter. It moves the stream past the delimiter and returns <code class="language-plaintext highlighter-rouge">NIL</code>, which indicates to <code class="language-plaintext highlighter-rouge">read-left-bracket</code> that all the objects in the array have been read. Since the stream pointer is now positioned after the delimiter, the reader is now free to read a new object from the input stream.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[1, 2, "foo"]
             ^
</code></pre></div></div>

<p>This is how we define <code class="language-plaintext highlighter-rouge">read-separator</code>, the reader macro function for comma. This function signals an error whenever it is called – it is never meant to be called directly by the reader.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">read-separator</span> <span class="p">(</span><span class="nc">stream</span> <span class="nb">char</span><span class="p">)</span>
  <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">ignore</span> <span class="nc">stream</span><span class="p">))</span>
  <span class="p">(</span><span class="nb">error</span> <span class="s">"Separator ~S shouldn't be read alone"</span> <span class="nb">char</span><span class="p">))</span>
</code></pre></div></div>

<p>You might ask, if the separator is never meant to be read directly by the reader, why bother associating it with a macro function? The thing is, its not the macro function that’s important – what we really want to do is tell the Lisp reader that the separator is a <em>terminating</em> macro character. If this were not done, the Lisp reader could unwittingly treat the separator as part of the last object if there was no whitespace between the two. e.g. in <code class="language-plaintext highlighter-rouge">[foo, ...]</code>, the first object would be read as <code class="language-plaintext highlighter-rouge">foo,</code> instead of <code class="language-plaintext highlighter-rouge">foo</code> if comma was not a terminating macro character. [2]</p>

<p>Lastly, we also need to define a macro function for the right bracket. This needs to be done for the same reason we needed to define a macro function for the separator – so that we can tell the Lisp reader that it is a terminating macro character.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">read-delimiter</span> <span class="p">(</span><span class="nc">stream</span> <span class="nb">char</span><span class="p">)</span>
  <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">ignore</span> <span class="nc">stream</span><span class="p">))</span>
  <span class="p">(</span><span class="nb">error</span> <span class="s">"Delimiter ~S shouldn't be read alone"</span> <span class="nb">char</span><span class="p">))</span>

<span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+right-bracket+</span> <span class="ss">'read-delimiter</span><span class="p">)</span>
</code></pre></div></div>

<p>Now we have everything in place to read a JSON array in Lisp. Time for some tests.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; []
#()

&gt; [1, 2, 3]
#(1 2 3)

&gt; [ "foo", "bar", "baz" ]
#("foo" "bar" "baz")

&gt; [1, 2, "foo"]
#(1 2 "foo")
</code></pre></div></div>

<p>Since we recursively call <code class="language-plaintext highlighter-rouge">READ</code> to read individual objects, nesting also works.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; [1, 2, [3, 4]]
#(1 2 #(3 4))
</code></pre></div></div>

<p>We can even use Lisp forms inside a JSON array, and they will work just fine.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; (let ((x 123) (y "foo")) [x, y])
#(123 "foo")
</code></pre></div></div>

<p>Remember that you can invoke the reader by calling <code class="language-plaintext highlighter-rouge">READ</code>, so you can always see the generated sexp for yourself.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; (read)
;; Input: [1, 2, "foo"]
(VECTOR 1 2 "foo")

&gt; (read)
;; Input: (let ((x 123) (y "foo")) [x, y])
(LET ((X 123) (Y "foo"))
  (VECTOR X Y))
</code></pre></div></div>

<p>Reading an object is not that different from reading an array. First we define a convenience function to create Lisp hash tables which will be used by <code class="language-plaintext highlighter-rouge">read-left-brace</code>, the macro function for the left brace.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">create-json-hash-table</span> <span class="p">(</span><span class="k">&amp;rest</span> <span class="nv">pairs</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nc">hash-table</span> <span class="p">(</span><span class="nb">make-hash-table</span> <span class="ss">:test</span> <span class="nf">#'</span><span class="nb">equal</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">loop</span> <span class="nv">for</span> <span class="p">(</span><span class="nv">key</span> <span class="o">.</span> <span class="nv">value</span><span class="p">)</span> <span class="nv">in</span> <span class="nv">pairs</span>
       <span class="nb">do</span> <span class="p">(</span><span class="nb">setf</span> <span class="p">(</span><span class="nb">gethash</span> <span class="nv">key</span> <span class="nc">hash-table</span><span class="p">)</span> <span class="nv">value</span><span class="p">))</span>
    <span class="nc">hash-table</span><span class="p">))</span>
</code></pre></div></div>

<p>And here’s <code class="language-plaintext highlighter-rouge">read-left-brace</code>. Note that this function also relies on <code class="language-plaintext highlighter-rouge">read-next-object</code> to get the bulk of its work done.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">read-left-brace</span> <span class="p">(</span><span class="nc">stream</span> <span class="nb">char</span><span class="p">)</span>
  <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">ignore</span> <span class="nb">char</span><span class="p">))</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="vg">*readtable*</span> <span class="p">(</span><span class="nb">copy-readtable</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+comma+</span> <span class="ss">'read-separator</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+colon+</span> <span class="ss">'read-separator</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">loop</span>
       <span class="nv">for</span> <span class="nv">key</span> <span class="nb">=</span> <span class="p">(</span><span class="nv">read-next-object</span> <span class="nv">+colon+</span> <span class="nv">+right-brace+</span> <span class="nc">stream</span><span class="p">)</span>
       <span class="nv">while</span> <span class="nv">key</span>
       <span class="nv">for</span> <span class="nv">value</span> <span class="nb">=</span> <span class="p">(</span><span class="nv">read-next-object</span> <span class="nv">+comma+</span> <span class="nv">+right-brace+</span> <span class="nc">stream</span><span class="p">)</span>
       <span class="nv">collect</span> <span class="o">`</span><span class="p">(</span><span class="nb">cons</span> <span class="o">,</span><span class="nv">key</span> <span class="o">,</span><span class="nv">value</span><span class="p">)</span> <span class="nv">into</span> <span class="nv">pairs</span>
       <span class="nv">finally</span> <span class="p">(</span><span class="nb">return</span> <span class="o">`</span><span class="p">(</span><span class="nv">create-json-hash-table</span> <span class="o">,@</span><span class="nv">pairs</span><span class="p">)))))</span>

<span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+left-brace+</span> <span class="ss">'read-left-brace</span><span class="p">)</span>
</code></pre></div></div>

<p>Finally, we also associate right brace with a macro function.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+right-brace+</span> <span class="ss">'read-delimiter</span><span class="p">)</span>
</code></pre></div></div>

<p>Time for some more tests.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CL-USER&gt; {}
#&lt;HASH-TABLE :TEST EQUAL :COUNT 0 {1005EEEBE3}&gt;

&gt; { "foo": 1, "bar": 2, "baz": 3 }
#&lt;HASH-TABLE :TEST EQUAL :COUNT 3 {1004DC3953}&gt;
</code></pre></div></div>

<p>We can also nest objects and arrays.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; [{"foo": 1}, "bar", {"baz": [2, 3]}]
#(#&lt;HASH-TABLE :TEST EQUAL :COUNT 1 {10062D4D83}&gt; "bar"
  #&lt;HASH-TABLE :TEST EQUAL :COUNT 1 {10062D5283}&gt;)
</code></pre></div></div>

<p>The generated sexp:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; (read)
{ "foo": 1, "bar": 2, "baz": 3 }
(CREATE-JSON-HASH-TABLE (CONS "foo" 1) (CONS "bar" 2) (CONS "baz" 3))
</code></pre></div></div>

<h2 id="refining-the-json-reader">Refining the JSON reader</h2>

<h3 id="true-false-null">true, false, null</h3>

<p>Our JSON reader can handle numbers, strings, objects and arrays fairly well. However, it can still not handle three primitives in JSON – <code class="language-plaintext highlighter-rouge">true</code>, <code class="language-plaintext highlighter-rouge">false</code>, and <code class="language-plaintext highlighter-rouge">null</code>. This is fairly easy to fix. When the reader encounters these JSON primitives, it interprets them as Lisp symbols. All we have to do is transform these into an appropriate Lisp value. To this end, we define a function <code class="language-plaintext highlighter-rouge">transform-primitive</code>.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">transform-primitive</span> <span class="p">(</span><span class="nv">value</span><span class="p">)</span>
  <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">symbolp</span> <span class="nv">value</span><span class="p">)</span>
      <span class="p">(</span><span class="nb">cond</span>
        <span class="p">((</span><span class="nb">string-equal</span> <span class="p">(</span><span class="nb">symbol-name</span> <span class="nv">value</span><span class="p">)</span> <span class="s">"true"</span><span class="p">)</span> <span class="no">t</span><span class="p">)</span>
        <span class="p">((</span><span class="nb">string-equal</span> <span class="p">(</span><span class="nb">symbol-name</span> <span class="nv">value</span><span class="p">)</span> <span class="s">"false"</span><span class="p">)</span> <span class="no">nil</span><span class="p">)</span>
        <span class="p">((</span><span class="nb">string-equal</span> <span class="p">(</span><span class="nb">symbol-name</span> <span class="nv">value</span><span class="p">)</span> <span class="s">"null"</span><span class="p">)</span> <span class="no">nil</span><span class="p">)</span>
        <span class="p">(</span><span class="no">t</span> <span class="nv">value</span><span class="p">))</span>
      <span class="nv">value</span><span class="p">))</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">transform-primitive</code> transforms both <code class="language-plaintext highlighter-rouge">false</code> and <code class="language-plaintext highlighter-rouge">null</code> from JSON to <code class="language-plaintext highlighter-rouge">NIL</code> in Lisp. That’s because in Lisp, the two are represented by the same value. You can always choose a different representation if you want.</p>

<p>We can start using <code class="language-plaintext highlighter-rouge">transform-primitive</code> in our reader macro functions now.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">read-left-bracket</span> <span class="p">(</span><span class="nc">stream</span> <span class="nb">char</span><span class="p">)</span>
  <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">ignore</span> <span class="nb">char</span><span class="p">))</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="vg">*readtable*</span> <span class="p">(</span><span class="nb">copy-readtable</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+comma+</span> <span class="ss">'read-separator</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">loop</span>
       <span class="nv">for</span> <span class="nv">object</span> <span class="nb">=</span> <span class="p">(</span><span class="nv">read-next-object</span> <span class="nv">+comma+</span> <span class="nv">+right-bracket+</span> <span class="nc">stream</span><span class="p">)</span>
       <span class="nv">while</span> <span class="nv">object</span>
       <span class="nv">collect</span> <span class="p">(</span><span class="nv">transform-primitive</span> <span class="nv">object</span><span class="p">)</span> <span class="nv">into</span> <span class="nv">objects</span>
       <span class="nv">finally</span> <span class="p">(</span><span class="nb">return</span> <span class="o">`</span><span class="p">(</span><span class="nb">vector</span> <span class="o">,@</span><span class="nv">objects</span><span class="p">)))))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">read-left-brace</span> <span class="p">(</span><span class="nc">stream</span> <span class="nb">char</span><span class="p">)</span>
  <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">ignore</span> <span class="nb">char</span><span class="p">))</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="vg">*readtable*</span> <span class="p">(</span><span class="nb">copy-readtable</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+comma+</span> <span class="ss">'read-separator</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+colon+</span> <span class="ss">'read-separator</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">loop</span>
       <span class="nv">for</span> <span class="nv">key</span> <span class="nb">=</span> <span class="p">(</span><span class="nv">read-next-object</span> <span class="nv">+colon+</span> <span class="nv">+right-brace+</span> <span class="nc">stream</span><span class="p">)</span>
       <span class="nv">while</span> <span class="nv">key</span>
       <span class="nv">for</span> <span class="nv">value</span> <span class="nb">=</span> <span class="p">(</span><span class="nv">read-next-object</span> <span class="nv">+comma+</span> <span class="nv">+right-brace+</span> <span class="nc">stream</span><span class="p">)</span>
       <span class="nv">collect</span> <span class="o">`</span><span class="p">(</span><span class="nb">cons</span> <span class="o">,</span><span class="nv">key</span> <span class="o">,</span><span class="p">(</span><span class="nv">transform-primitive</span> <span class="nv">value</span><span class="p">))</span> <span class="nv">into</span> <span class="nv">pairs</span>
       <span class="nv">finally</span> <span class="p">(</span><span class="nb">return</span> <span class="o">`</span><span class="p">(</span><span class="nv">create-json-hash-table</span> <span class="o">,@</span><span class="nv">pairs</span><span class="p">)))))</span>
</code></pre></div></div>

<p>Let’s test this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; [true, false, null]
#(T NIL NIL)
</code></pre></div></div>

<h3 id="object-keys">Object keys</h3>

<p>While JSON requires that object keys be strict JSON strings (with surrounding double quotes, etc.), Javascript on the other hand doesn’t. Object keys in Javascript don’t need to be surrounded by double quotes.</p>

<p>When we try to use this syntax with our reader, we get an error.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; { foo: 1 }
; Evaluation aborted on #&lt;UNBOUND-VARIABLE FOO {1003AC8E03}&gt;.
</code></pre></div></div>

<p>A look at the generated sexp makes clear why we get the runtime thinks <code class="language-plaintext highlighter-rouge">foo</code> is unbound.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; (read)
;; Input: { foo: 1 }
(CREATE-JSON-HASH-TABLE (CONS FOO 1))
</code></pre></div></div>

<p>This is also easy to fix using the <code class="language-plaintext highlighter-rouge">stringify-key</code> function.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">stringify-key</span> <span class="p">(</span><span class="nv">key</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">etypecase</span> <span class="nv">key</span>
    <span class="p">(</span><span class="nc">symbol</span> <span class="p">(</span><span class="nb">string-downcase</span> <span class="p">(</span><span class="nb">string</span> <span class="nv">key</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">string</span> <span class="nv">key</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">read-left-brace</span> <span class="p">(</span><span class="nc">stream</span> <span class="nb">char</span><span class="p">)</span>
  <span class="p">(</span><span class="k">declare</span> <span class="p">(</span><span class="k">ignore</span> <span class="nb">char</span><span class="p">))</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="vg">*readtable*</span> <span class="p">(</span><span class="nb">copy-readtable</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+comma+</span> <span class="ss">'read-separator</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+colon+</span> <span class="ss">'read-separator</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">loop</span>
       <span class="nv">for</span> <span class="nv">key</span> <span class="nb">=</span> <span class="p">(</span><span class="nv">read-next-object</span> <span class="nv">+colon+</span> <span class="nv">+right-brace+</span> <span class="nc">stream</span><span class="p">)</span>
       <span class="nv">while</span> <span class="nv">key</span>
       <span class="nv">for</span> <span class="nv">value</span> <span class="nb">=</span> <span class="p">(</span><span class="nv">read-next-object</span> <span class="nv">+comma+</span> <span class="nv">+right-brace+</span> <span class="nc">stream</span><span class="p">)</span>
       <span class="nv">collect</span> <span class="o">`</span><span class="p">(</span><span class="nb">cons</span> <span class="o">,</span><span class="p">(</span><span class="nv">stringify-key</span> <span class="nv">key</span><span class="p">)</span> <span class="o">,</span><span class="p">(</span><span class="nv">transform-primitive</span> <span class="nv">value</span><span class="p">))</span> <span class="nv">into</span> <span class="nv">pairs</span>
       <span class="nv">finally</span> <span class="p">(</span><span class="nb">return</span> <span class="o">`</span><span class="p">(</span><span class="nv">create-json-hash-table</span> <span class="o">,@</span><span class="nv">pairs</span><span class="p">)))))</span>
</code></pre></div></div>

<p>Some tests:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; { foo: 1 }
#&lt;HASH-TABLE :TEST EQUAL :COUNT 1 {1004248763}&gt;

&gt; (read)
;; Input: { foo: 1 }
(JSON-READER::CREATE-JSON-HASH-TABLE (CONS "foo" 1))
</code></pre></div></div>

<h3 id="package-marker">Package marker</h3>

<p>One problem with <code class="language-plaintext highlighter-rouge">read-left-brace</code> is that, within its dymanic scope, it overrides the macro function for colon. The <a href="http://www.lispworks.com/documentation/HyperSpec/Body/02_aab.htm">standard readtable</a> in Lisp defines colon to be a package marker for symbols. What this means is that, when parsing a JSON object, we will face problems if a symbol contains a colon.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; { foo: cl:pi }
; Evaluation aborted on #&lt;SIMPLE-ERROR "Unexpected next char: ~S" {10043B7083}&gt;.
</code></pre></div></div>

<p>Again, this is not very hard to fix. I will leave that as an exercise to the reader.</p>

<h2 id="packaging-the-new-syntax">Packaging the new syntax</h2>

<p>Apart from creating new functions, we also directly change the current readtable when associating macro functions with characters:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+left-bracket+</span> <span class="ss">'read-left-bracket</span><span class="p">)</span>
<span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+right-bracket+</span> <span class="ss">'read-delimiter</span><span class="p">)</span>
<span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+left-brace+</span> <span class="ss">'read-left-brace</span><span class="p">)</span>
<span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+right-brace+</span> <span class="ss">'read-delimiter</span><span class="p">)</span>
</code></pre></div></div>

<p>If we were to package the JSON reader in a library and add these lines as toplevel forms in the library’s source code, we would clobber the user’s current readtable when the library source was loaded. This is not desirable. What we want instead is to provide user with a hook to enable/disable JSON syntax at will.</p>

<p>So instead of adding these as toplevel forms, we could provide them inside a function:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">enable-json-syntax</span> <span class="p">()</span>
  <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+left-bracket+</span> <span class="ss">'read-left-bracket</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+right-bracket+</span> <span class="ss">'read-delimiter</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+left-brace+</span> <span class="ss">'read-left-brace</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+right-brace+</span> <span class="ss">'read-delimiter</span><span class="p">))</span>
</code></pre></div></div>

<p>Now, when users want to enable JSON syntax from the REPL, they could simply call <code class="language-plaintext highlighter-rouge">enable-json-syntax</code>.</p>

<p>Enabling this syntax inside a source file is a bit trickier. Let’s assume we write our file like this:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;;; foo.lisp</span>

<span class="p">(</span><span class="nb">in-package</span> <span class="ss">#:foobar</span><span class="p">)</span>

<span class="p">(</span><span class="nv">enable-json-syntax</span><span class="p">)</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">foobar</span> <span class="p">()</span>
  <span class="nv">[</span><span class="s">"foo"</span><span class="o">,</span> <span class="s">"bar"</span><span class="nv">]</span><span class="p">)</span>
</code></pre></div></div>

<p>Consider what happens when this file is loaded using <code class="language-plaintext highlighter-rouge">(load (compile-file "foo.lisp"))</code>. <code class="language-plaintext highlighter-rouge">enable-json-syntax</code> will only get called during <code class="language-plaintext highlighter-rouge">LOAD</code>. However, by then, it is too late.</p>

<p>Remember that reader macros only work at read-time i.e. when the reader is translating raw text into Lisp s-expressions. In the example above, the definition for <code class="language-plaintext highlighter-rouge">foobar</code> was translated from raw text to sexp during <a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_cmp_fi.htm"><code class="language-plaintext highlighter-rouge">COMPILE-FILE</code></a> and not <a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_load.htm"><code class="language-plaintext highlighter-rouge">LOAD</code></a>. So what we really want is to run <code class="language-plaintext highlighter-rouge">enable-json-syntax</code> during <code class="language-plaintext highlighter-rouge">COMPILE-FILE</code> instead of <code class="language-plaintext highlighter-rouge">LOAD</code>. The simplest way to achieve this is to wrap the function call inside an <a href="http://www.lispworks.com/documentation/HyperSpec/Body/s_eval_w.htm"><code class="language-plaintext highlighter-rouge">EVAL-WHEN</code></a>:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;;; foo.lisp</span>

<span class="p">(</span><span class="nb">in-package</span> <span class="ss">#:foobar</span><span class="p">)</span>

<span class="p">(</span><span class="k">eval-when</span> <span class="p">(</span><span class="ss">:compile-toplevel</span> <span class="ss">:load-toplevel</span> <span class="ss">:execute</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">enable-json-syntax</span><span class="p">))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">foobar</span> <span class="p">()</span>
  <span class="nv">[</span><span class="s">"foo"</span><span class="o">,</span> <span class="s">"bar"</span><span class="nv">]</span><span class="p">)</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">EVAL-WHEN</code> ensures that <code class="language-plaintext highlighter-rouge">enable-json-syntax</code> is called during <code class="language-plaintext highlighter-rouge">COMPILE-FILE</code> <em>and</em> <code class="language-plaintext highlighter-rouge">LOAD</code>, so you get sane behaviour with both <code class="language-plaintext highlighter-rouge">(load (compile-file "foo.lisp"))</code> and <code class="language-plaintext highlighter-rouge">(load "foo.lisp")</code>.</p>

<p>However, this still suffers from two problems:</p>

<ol>
  <li>
    <p>There is no way to undo this – we can’t provide a <code class="language-plaintext highlighter-rouge">disable-json-syntax</code> because we don’t keep track of the previous macro functions for these characters, if any.</p>
  </li>
  <li>
    <p>This still clobbers the current readtable. It might not as be a big problem when a user calls this function directly on the REPL, however since the current readtable is passed as is during <code class="language-plaintext highlighter-rouge">LOAD</code> and <code class="language-plaintext highlighter-rouge">COMPILE-FILE</code>, any modifications to the readtable will persist globally even after these operations finish.</p>
  </li>
</ol>

<p>Both these problems are solved by making a slight modification to <code class="language-plaintext highlighter-rouge">enable-json-syntax</code>.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defvar</span> <span class="vg">*previous-readtables*</span> <span class="no">nil</span><span class="p">)</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">enable-json-syntax</span> <span class="p">()</span>
  <span class="p">(</span><span class="nb">push</span> <span class="vg">*readtable*</span> <span class="vg">*previous-readtables*</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="vg">*readtable*</span> <span class="p">(</span><span class="nb">copy-readtable</span><span class="p">))</span>
  <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+left-bracket+</span> <span class="ss">'read-left-bracket</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+right-bracket+</span> <span class="ss">'read-delimiter</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+left-brace+</span> <span class="ss">'read-left-brace</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+right-brace+</span> <span class="ss">'read-delimiter</span><span class="p">))</span>
</code></pre></div></div>

<p>We maintain a stack of previous readtables. When <code class="language-plaintext highlighter-rouge">enable-json-syntax</code> is called, the current readtable is pushed on the stack of previous readtables and a copy is made the current readtable. This ensures that subsequent modifications to the readtable are made on our copy and not the readtable that we inherited.</p>

<p>Now we can provide a simple way to disable JSON syntax.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">disable-json-syntax</span> <span class="p">()</span>
  <span class="p">(</span><span class="k">setq</span> <span class="vg">*readtable*</span> <span class="p">(</span><span class="nb">pop</span> <span class="vg">*previous-readtables*</span><span class="p">)))</span>
</code></pre></div></div>

<p>Note: we must ensure that any call to <code class="language-plaintext highlighter-rouge">enable-json-syntax</code> is balanced with a subsequent call to <code class="language-plaintext highlighter-rouge">disable-json-syntax</code>. If we don’t, the stack of previous readtables will get corrupted.</p>

<p>This solves the first problem, but what about the second? Due to an interesting peculiarity of <code class="language-plaintext highlighter-rouge">LOAD</code> and <code class="language-plaintext highlighter-rouge">COMPILE-FILE</code> – both of these functions bind <code class="language-plaintext highlighter-rouge">*READTABLE*</code> to its current value before working on the file – <code class="language-plaintext highlighter-rouge">(setq *readtable* (copy-readtable))</code> by itself is enough to ensure that modifications do not persist after these operations finish. In fact, if we only ever call <code class="language-plaintext highlighter-rouge">enable-json-syntax</code> and <code class="language-plaintext highlighter-rouge">disable-json-syntax</code> from source files and never from the REPL directly, we don’t need to manage the stack of previous readtables at all since dynamic binding takes care of this for us.</p>

<p>Finally, it might be a bit cumbersome for your users to write <code class="language-plaintext highlighter-rouge">(eval-when (:compile-toplevel :load-toplevel ...))</code> all the time, so we could redefine these functions as macros.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defmacro</span> <span class="nv">enable-json-syntax</span> <span class="p">()</span>
  <span class="o">'</span><span class="p">(</span><span class="k">eval-when</span> <span class="p">(</span><span class="ss">:compile-toplevel</span> <span class="ss">:load-toplevel</span> <span class="ss">:execute</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">push</span> <span class="vg">*readtable*</span> <span class="vg">*previous-readtables*</span><span class="p">)</span>
    <span class="p">(</span><span class="k">setq</span> <span class="vg">*readtable*</span> <span class="p">(</span><span class="nb">copy-readtable</span><span class="p">))</span>
    <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+left-bracket+</span> <span class="ss">'read-left-bracket</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+right-bracket+</span> <span class="ss">'read-delimiter</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+left-brace+</span> <span class="ss">'read-left-brace</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">set-macro-character</span> <span class="nv">+right-brace+</span> <span class="ss">'read-delimiter</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defmacro</span> <span class="nv">disable-json-syntax</span> <span class="p">()</span>
  <span class="o">'</span><span class="p">(</span><span class="k">eval-when</span> <span class="p">(</span><span class="ss">:compile-toplevel</span> <span class="ss">:load-toplevel</span> <span class="ss">:execute</span><span class="p">)</span>
    <span class="p">(</span><span class="k">setq</span> <span class="vg">*readtable*</span> <span class="p">(</span><span class="nb">pop</span> <span class="vg">*previous-readtables*</span><span class="p">))))</span>
</code></pre></div></div>

<p>Your users can now enable/disable JSON syntax at will using these two macros. As long as calls to <code class="language-plaintext highlighter-rouge">enable-json-syntax</code> and <code class="language-plaintext highlighter-rouge">disable-json-syntax</code> are balanced, this will work well both on the REPL and in a source file. For reference, here’s how a user source file might look with these definitions in place:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;;; foo.lisp</span>

<span class="p">(</span><span class="nb">in-package</span> <span class="ss">#:foobar</span><span class="p">)</span>

<span class="p">(</span><span class="nv">enable-json-syntax</span><span class="p">)</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">foobar</span> <span class="p">()</span>
  <span class="nv">[</span><span class="s">"foo"</span><span class="o">,</span> <span class="s">"bar"</span><span class="nv">]</span><span class="p">)</span>

<span class="c1">;; Write more definitions</span>

<span class="p">(</span><span class="nv">disable-json-syntax</span><span class="p">)</span>
</code></pre></div></div>

<p>It is worth mentioning <a href="http://common-lisp.net/project/named-readtables/">Named-Readtables</a> here. This is a library designed to make readtable management as easy as package management. If you are providing a custom reader syntax in your library, consider using Named-Readtables.</p>

<p><em>(Thanks to <a href="http://www.reddit.com/r/lisp/comments/1zfim8/reader_macros_in_common_lisp/cfueii9">handle0174</a> and <a href="http://www.reddit.com/r/lisp/comments/1zfim8/reader_macros_in_common_lisp/cft6mw2">xach</a> for suggestions)</em></p>

<h2 id="conclusion">Conclusion</h2>

<p>Reader macros are a powerful way to expand Lisp’s syntax in new and wonderful ways. However with great power comes great responsibility, so you should learn to use them with great care. For example, while a JSON reader was a good exercise in understanding reader macros, I would never use it in real world for the simple reason that easier alternatives already exist. e.g. a plain list or even a vector literal:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>'(1 2 3)
#(1 2 3)
</code></pre></div></div>

<p>Another disadvantage of inventing new syntax is that it doesn’t work well with existing development tools. e.g. JSON array and object syntax doesn’t work very well with lisp and paredit modes in Emacs – even simple operations like <code class="language-plaintext highlighter-rouge">C-M-f</code> and <code class="language-plaintext highlighter-rouge">C-M-b</code> (to go forward or backward sexp) don’t work very well.</p>

<p>There is a saying that goes along these lines: where a function will do, don’t use a macro. A corollary for reader macros could be: where a sexp will do, don’t use a reader macro. Yes, it might be a subjective call, but think twice before using a reader macro.</p>

<p>However, when done right, reader macros can work wonders. Take a look at <a href="http://weitz.de/cl-interpol/">cl-interpol</a> [3], which adds support for string interpolation to Common Lisp, so you can easily embed newlines in strings or even create regexes more simply.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; #?"foo\nbar"
"foo
bar"

&gt; #?/\bfoo\b/
"\\bfoo\\b"
</code></pre></div></div>

<p>A few other possible use cases for reader macros are:</p>

<ul>
  <li>increase compatibility with foreign code e.g. Objective-C like calls</li>
  <li>infix syntax</li>
  <li>rule system syntax</li>
  <li>embedded SQL</li>
</ul>

<p><em>(Thanks to <a href="http://www.reddit.com/r/lisp/comments/1zfim8/reader_macros_in_common_lisp/cft6i1z">lispm</a>)</em></p>

<p>Source code used in this post is available in a <a href="/src/reader-macros/json-reader.lisp">json-reader.lisp</a>. A battery of <a href="/src/reader-macros/test.lisp">tests</a> is also provided.</p>

<h2 id="notes">Notes</h2>

<ol>
  <li>
    <p>I have not covered how <code class="language-plaintext highlighter-rouge">READ</code> handles whitespace following the Lisp expression. When you provide <code class="language-plaintext highlighter-rouge">'foo</code> as input on the standard input, you need to follow it up with the a newline character. <code class="language-plaintext highlighter-rouge">READ</code> will read past the newline character in this case; so the stream position after <code class="language-plaintext highlighter-rouge">single-quote-reader</code> will actually go past the newline</p>
  </li>
  <li>
    <p>Actually, comma is already <a href="http://www.lispworks.com/documentation/HyperSpec/Body/02_dg.htm">defined</a> in the standard readtable as a terminating macro character – it is a part of the <a href="http://www.lispworks.com/documentation/HyperSpec/Body/02_df.htm">backquote syntax</a>. So technically, we could have done without associating comma with <code class="language-plaintext highlighter-rouge">read-separator</code>.</p>
  </li>
  <li>
    <p>Technically, cl-interpol doesn’t define a new reader macro, it installs <code class="language-plaintext highlighter-rouge">?</code> (question mark) as a “sub character” of the standard <a href="http://www.lispworks.com/documentation/HyperSpec/Body/02_dh.htm">dispatching macro character</a> <code class="language-plaintext highlighter-rouge">#</code> (sharpsign). Dispatching macro characters are a special class of reader macros which allow you to “make the most of the ASCII character set; one can only have so many one-character read-macros.” (On Lisp, Chapter 17, Read-Macros)</p>
  </li>
</ol>]]></content><author><name>Chaitanya Gupta</name></author><category term="lisp" /><summary type="html"><![CDATA[This post originally appeared as a github gist.]]></summary></entry><entry><title type="html">Common Lisp: A Tutorial on Conditions and Restarts</title><link href="https://lisper.in/restarts" rel="alternate" type="text/html" title="Common Lisp: A Tutorial on Conditions and Restarts" /><published>2008-05-06T00:00:00+00:00</published><updated>2008-05-06T00:00:00+00:00</updated><id>https://lisper.in/restarts</id><content type="html" xml:base="https://lisper.in/restarts"><![CDATA[<p><em>This post originally appeared on <a href="http://chaitanyagupta.com">chaitanyagupta.com</a>.</em></p>

<p>Common Lisp’s condition system, with its exceptions and restarts, is one of its unique features. Unfortunately, there aren’t many good tutorials explaining this concept very well. One good introduction to this is the chapter on conditions and restarts in Peter Seibel’s excellent book, <a href="http://gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html">Practical Common Lisp</a>. This tutorial assumes some knowledge of the condition system, so you might want to read that chapter before proceeding. Another good read is Kent Pitman’s paper, <a href="http://www.nhplace.com/kent/Papers/Condition-Handling-2001.html">Condition Handling in the Lisp Language Family</a>.</p>

<p>I’ll attempt to show how effective CL’s condition system can be, with a validator for CSV (comma-separated values) files. The validator will check that all the fields in each row of the file are valid (according to some defined criteria).</p>

<h3 id="contents">Contents</h3>

<ul>
  <li><a href="#the-csv">The CSV</a></li>
  <li><a href="#signaling-validation-errors">Signaling validation errors</a></li>
  <li><a href="#parsing-the-csv">Parsing the CSV</a></li>
  <li><a href="#the-validator-(sans-the-restarts)">The Validator (sans the restarts)</a></li>
  <li><a href="#putting-restarts-in-place">Putting restarts in place</a></li>
  <li><a href="#starting-all-over-again">Starting all over again</a></li>
  <li><a href="#handling-restarts">Handling restarts</a></li>
  <li><a href="#conclusion">Conclusion</a></li>
</ul>

<h2 id="the-csv">The CSV</h2>

<p>The first row of the CSV will be a comma-separated list of headers, followed by rows with each column corresponding to the headers in the first row. A sample file looks like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rating,url,visitors,date
4,http://chaitanyagupta.com/home,1233445,2000-01-01
5,http://chaitanyagupta.com/blog,33333,2006-02-02
5,http://chaitanyagupta.com/code,2121212,2007-03-03
</code></pre></div></div>

<p>First we write functions to validate fields for the four headers we used above: <code class="language-plaintext highlighter-rouge">rating</code>, <code class="language-plaintext highlighter-rouge">url</code>, <code class="language-plaintext highlighter-rouge">visitors</code>, and <code class="language-plaintext highlighter-rouge">date</code>. Note that these functions depend on <a href="http://weitz.de/cl-ppcre">CL-PPCRE</a>.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">validate-url</span> <span class="p">(</span><span class="nb">string</span><span class="p">)</span>
  <span class="s">"The URL of the page; should start with http:// or https://."</span>
  <span class="p">(</span><span class="nb">unless</span> <span class="p">(</span><span class="nv">cl-ppcre:scan</span> <span class="s">"^https?://"</span> <span class="nb">string</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">csv-error</span> <span class="s">"URL invalid."</span> <span class="ss">:value</span> <span class="nb">string</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">validate-rating</span> <span class="p">(</span><span class="nb">string</span><span class="p">)</span>
  <span class="s">"String should contain an integer between 1 and 5, inclusive."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">rating</span> <span class="p">(</span><span class="nb">parse-integer</span> <span class="nb">string</span> <span class="ss">:junk-allowed</span> <span class="no">t</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">unless</span> <span class="p">(</span><span class="nb">and</span> <span class="p">(</span><span class="nb">integerp</span> <span class="nv">rating</span><span class="p">)</span> <span class="p">(</span><span class="nb">&lt;=</span> <span class="mi">1</span> <span class="nv">rating</span> <span class="mi">5</span><span class="p">))</span>
      <span class="p">(</span><span class="nv">csv-error</span> <span class="s">"Rating not an integer in range."</span> <span class="ss">:value</span> <span class="nb">string</span><span class="p">))))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">validate-visitors</span> <span class="p">(</span><span class="nb">string</span><span class="p">)</span>
  <span class="s">"The number of visitors to the page; string should contain an
integer more than or equal to zero."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">visitors</span> <span class="p">(</span><span class="nb">parse-integer</span> <span class="nb">string</span> <span class="ss">:junk-allowed</span> <span class="no">nil</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">unless</span> <span class="p">(</span><span class="nb">and</span> <span class="p">(</span><span class="nb">integerp</span> <span class="nv">visitors</span><span class="p">)</span> <span class="p">(</span><span class="nb">&gt;=</span> <span class="nv">visitors</span> <span class="mi">0</span><span class="p">))</span>
      <span class="p">(</span><span class="nv">csv-error</span> <span class="s">"Number of visitors invalid."</span> <span class="ss">:value</span> <span class="nb">string</span><span class="p">))))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">validate-date</span> <span class="p">(</span><span class="nb">string</span><span class="p">)</span>
  <span class="s">"The published date of the URL. Should be in yyyy-mm-dd format."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">split</span> <span class="p">(</span><span class="nv">cl-ppcre:split</span> <span class="s">"-"</span> <span class="nb">string</span><span class="p">)))</span>
    <span class="p">(</span><span class="k">flet</span> <span class="p">((</span><span class="nv">valid-number-of-digits-p</span> <span class="p">(</span><span class="nb">string</span> <span class="nv">n</span><span class="p">)</span>
             <span class="p">(</span><span class="nb">and</span> <span class="p">(</span><span class="nb">every</span> <span class="nf">#'</span><span class="nb">digit-char-p</span> <span class="nb">string</span><span class="p">)</span>
                  <span class="p">(</span><span class="nb">=</span> <span class="p">(</span><span class="nb">length</span> <span class="nb">string</span><span class="p">)</span> <span class="nv">n</span><span class="p">))))</span>
      <span class="p">(</span><span class="nb">unless</span> <span class="p">(</span><span class="nb">and</span> <span class="p">(</span><span class="nv">valid-number-of-digits-p</span> <span class="p">(</span><span class="nb">first</span> <span class="nv">split</span><span class="p">)</span> <span class="mi">4</span><span class="p">)</span>
                   <span class="p">(</span><span class="nv">valid-number-of-digits-p</span> <span class="p">(</span><span class="nb">second</span> <span class="nv">split</span><span class="p">)</span> <span class="mi">2</span><span class="p">)</span>
                   <span class="p">(</span><span class="nv">valid-number-of-digits-p</span> <span class="p">(</span><span class="nb">third</span> <span class="nv">split</span><span class="p">)</span> <span class="mi">2</span><span class="p">))</span>
        <span class="p">(</span><span class="nv">csv-error</span> <span class="s">"Published date not in valid format."</span> <span class="ss">:value</span> <span class="nb">string</span><span class="p">)))))</span>
</code></pre></div></div>

<p>All these functions take a string as an argument, and if it doesn’t satisfy the validation criteria, an error is signalled using the function <code class="language-plaintext highlighter-rouge">csv-error</code>. This is defined next.</p>

<h2 id="signaling-validation-errors">Signaling validation errors</h2>

<p>The function <code class="language-plaintext highlighter-rouge">csv-error</code> signals a condition of type <code class="language-plaintext highlighter-rouge">csv-error</code>, both of which are defined below.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">define-condition</span> <span class="nv">csv-error</span> <span class="p">(</span><span class="nb">error</span><span class="p">)</span>
  <span class="p">((</span><span class="nv">message</span>
    <span class="ss">:initarg</span> <span class="ss">:message</span>
    <span class="ss">:accessor</span> <span class="nv">csv-error-message</span>
    <span class="ss">:initform</span> <span class="no">nil</span>
    <span class="ss">:documentation</span> <span class="s">"Text message indicating what went wrong with the validation."</span><span class="p">)</span>
   <span class="p">(</span><span class="nv">value</span>
    <span class="ss">:initarg</span> <span class="ss">:value</span>
    <span class="ss">:accessor</span> <span class="nv">csv-error-value</span>
    <span class="ss">:initform</span> <span class="no">nil</span>
    <span class="ss">:documentation</span> <span class="s">"The value of the field for which the error is signalled."</span><span class="p">)</span>
   <span class="p">(</span><span class="nv">line-number</span>
    <span class="ss">:initarg</span> <span class="ss">:line-number</span>
    <span class="ss">:accessor</span> <span class="nv">csv-error-line-number</span>
    <span class="ss">:initform</span> <span class="no">nil</span>
    <span class="ss">:documentation</span> <span class="s">"The line number of the row in for the error was signalled."</span><span class="p">)))</span>

<span class="c1">;; Do something more useful than the default printer behaviour</span>
<span class="p">(</span><span class="nb">defmethod</span> <span class="nb">print-object</span> <span class="p">((</span><span class="nv">object</span> <span class="nv">csv-error</span><span class="p">)</span> <span class="nc">stream</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">print-unreadable-object</span> <span class="p">(</span><span class="nv">object</span> <span class="nc">stream</span> <span class="ss">:type</span> <span class="no">t</span> <span class="ss">:identity</span> <span class="no">t</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">format</span> <span class="nc">stream</span> <span class="s">"~@[L~A ~]~S~@[: ~S~]"</span>
            <span class="p">(</span><span class="nv">csv-error-line-number</span> <span class="nv">object</span><span class="p">)</span>
            <span class="p">(</span><span class="nv">csv-error-message</span> <span class="nv">object</span><span class="p">)</span>
            <span class="p">(</span><span class="nv">csv-error-value</span> <span class="nv">object</span><span class="p">))))</span>

<span class="c1">;; We use this function to signal our validation error</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">csv-error</span> <span class="p">(</span><span class="nv">message</span> <span class="k">&amp;key</span> <span class="nv">value</span> <span class="nv">line-number</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">error</span> <span class="ss">'csv-error</span>
         <span class="ss">:message</span> <span class="nv">message</span>
         <span class="ss">:value</span> <span class="nv">value</span>
         <span class="ss">:line-number</span> <span class="nv">line-number</span><span class="p">))</span>
</code></pre></div></div>

<h2 id="parsing-the-csv">Parsing the CSV</h2>

<p>The parser converts raw CSV text into a list of lists – each item in these lists corresponds to a field in the CSV.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">parse-csv-file</span> <span class="p">(</span><span class="nv">file</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">with-open-file</span> <span class="p">(</span><span class="nv">f</span> <span class="nv">file</span> <span class="ss">:direction</span> <span class="ss">:input</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">loop</span>
       <span class="nv">for</span> <span class="nv">line</span> <span class="nb">=</span> <span class="p">(</span><span class="nb">read-line</span> <span class="nv">f</span> <span class="no">nil</span><span class="p">)</span>
       <span class="nv">while</span> <span class="nv">line</span>
       <span class="nv">collect</span> <span class="p">(</span><span class="nv">cl-ppcre:split</span> <span class="s">","</span> <span class="nv">line</span><span class="p">))))</span>
</code></pre></div></div>

<h2 id="the-validator-sans-the-restarts">The Validator (sans the restarts)</h2>

<p>Finally, we get down to writing the validator, <code class="language-plaintext highlighter-rouge">validate-csv</code>. If the validation is succesful (i.e. all the fields in the CSV are valid), the function returns normally. If any invalid field is present, an error will be signalled (using the validator functions defined above).</p>

<p>This version of the validator doesn’t contain any restarts though.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">validate-csv</span> <span class="p">(</span><span class="nv">file</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">destructuring-bind</span> <span class="p">(</span><span class="nv">headers</span> <span class="o">.</span> <span class="nv">rows</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">parse-csv-file</span> <span class="nv">file</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">loop</span>
       <span class="nv">for</span> <span class="nv">row</span> <span class="nv">in</span> <span class="nv">rows</span>
       <span class="nv">for</span> <span class="nv">line-number</span> <span class="nv">upfrom</span> <span class="mi">2</span>
       <span class="nb">do</span>
       <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">/=</span> <span class="p">(</span><span class="nb">length</span> <span class="nv">row</span><span class="p">)</span> <span class="p">(</span><span class="nb">length</span> <span class="nv">headers</span><span class="p">))</span>
         <span class="p">(</span><span class="nv">csv-error</span> <span class="s">"Number of fields doesn't equal number of headers."</span>
                    <span class="ss">:line-number</span> <span class="nv">line-number</span><span class="p">))</span>
       <span class="p">(</span><span class="nb">handler-bind</span>
           <span class="c1">;; Set the LINE-NUMBER slot of the signalled</span>
           <span class="c1">;; csv-error. Note that since this clause returns normally,</span>
           <span class="c1">;; the error doesn't stop here, it goes "up" the stack</span>
           <span class="p">((</span><span class="nv">csv-error</span> <span class="nf">#'</span><span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">c</span><span class="p">)</span>
                           <span class="p">(</span><span class="nb">setf</span> <span class="p">(</span><span class="nv">csv-error-line-number</span> <span class="nv">c</span><span class="p">)</span> <span class="nv">line-number</span><span class="p">))))</span>
         <span class="p">(</span><span class="nb">loop</span>
            <span class="nv">for</span> <span class="nv">header</span> <span class="nv">in</span> <span class="nv">headers</span>
            <span class="nv">for</span> <span class="nv">field</span> <span class="nv">in</span> <span class="nv">row</span>
            <span class="nb">do</span> <span class="p">(</span><span class="nv">validate-field</span> <span class="nv">header</span> <span class="nv">field</span><span class="p">))))))</span>

<span class="c1">;; Takes a header name and a string value as arguments; checks the</span>
<span class="c1">;; validity of the value by calling the appropriate validator function</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">validate-field</span> <span class="p">(</span><span class="nv">header</span> <span class="nv">value</span><span class="p">)</span>
  <span class="p">(</span><span class="k">flet</span> <span class="p">((</span><span class="nv">header-matches</span> <span class="p">(</span><span class="nb">string</span><span class="p">)</span>
           <span class="p">(</span><span class="nb">string-equal</span> <span class="nv">header</span> <span class="nb">string</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">cond</span>
      <span class="p">((</span><span class="nv">header-matches</span> <span class="s">"url"</span><span class="p">)</span> <span class="p">(</span><span class="nv">validate-url</span> <span class="nv">value</span><span class="p">))</span>
      <span class="p">((</span><span class="nv">header-matches</span> <span class="s">"rating"</span><span class="p">)</span> <span class="p">(</span><span class="nv">validate-rating</span> <span class="nv">value</span><span class="p">))</span>
      <span class="p">((</span><span class="nv">header-matches</span> <span class="s">"visitors"</span><span class="p">)</span> <span class="p">(</span><span class="nv">validate-visitors</span> <span class="nv">value</span><span class="p">))</span>
      <span class="p">((</span><span class="nv">header-matches</span> <span class="s">"date"</span><span class="p">)</span> <span class="p">(</span><span class="nv">validate-date</span> <span class="nv">value</span><span class="p">))</span>
      <span class="p">(</span><span class="no">t</span> <span class="p">(</span><span class="nv">csv-error</span> <span class="s">"Invalid header."</span> <span class="ss">:value</span> <span class="nv">header</span><span class="p">)))))</span>
</code></pre></div></div>

<h2 id="putting-restarts-in-place">Putting restarts in place</h2>

<p>There are a few actions we can take once an “invalid” field has been detected (i.e. a <code class="language-plaintext highlighter-rouge">csv-error</code> is signalled), e.g. we can abort the validation, we can continue validation on the next row, or we continue validation with the remaining fields in the same row (to name just a few).</p>

<p>Aborting the validation is as simple as invoking the <code class="language-plaintext highlighter-rouge">ABORT</code> restart in the debugger, or doing something like this:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">handler-case</span> <span class="p">(</span><span class="k">progn</span>
                <span class="p">(</span><span class="nv">validate-csv</span> <span class="s">"~/tmp/test.csv"</span><span class="p">)</span>
                <span class="ss">:success</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">csv-error</span> <span class="p">()</span> <span class="ss">:failure</span><span class="p">))</span>
</code></pre></div></div>

<p>To continue validation on the same row, or the next one, we add a couple of restarts using the <code class="language-plaintext highlighter-rouge">with-simple-restart</code> macro:</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">validate-csv</span> <span class="p">(</span><span class="nv">file</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">destructuring-bind</span> <span class="p">(</span><span class="nv">headers</span> <span class="o">.</span> <span class="nv">rows</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">parse-csv-file</span> <span class="nv">file</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">loop</span>
       <span class="nv">for</span> <span class="nv">row</span> <span class="nv">in</span> <span class="nv">rows</span>
       <span class="nv">for</span> <span class="nv">line-number</span> <span class="nv">upfrom</span> <span class="mi">2</span>
       <span class="nb">do</span>
       <span class="c1">;; If this restart is invoked, validation will continue on</span>
       <span class="c1">;; the next row</span>
       <span class="p">(</span><span class="nb">with-simple-restart</span> <span class="p">(</span><span class="nv">continue-next-row</span> <span class="s">"Continue validation on next row."</span><span class="p">)</span>
         <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">/=</span> <span class="p">(</span><span class="nb">length</span> <span class="nv">row</span><span class="p">)</span> <span class="p">(</span><span class="nb">length</span> <span class="nv">headers</span><span class="p">))</span>
           <span class="p">(</span><span class="nv">csv-error</span> <span class="s">"Number of fields doesn't equal number of headers."</span>
                      <span class="ss">:line-number</span> <span class="nv">line-number</span><span class="p">))</span>
         <span class="p">(</span><span class="nb">loop</span>
            <span class="nv">for</span> <span class="nv">header</span> <span class="nv">in</span> <span class="nv">headers</span>
            <span class="nv">for</span> <span class="nv">field</span> <span class="nv">in</span> <span class="nv">row</span>
            <span class="nb">do</span>
            <span class="p">(</span><span class="nb">handler-bind</span>
                <span class="p">((</span><span class="nv">csv-error</span> <span class="nf">#'</span><span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">c</span><span class="p">)</span>
                                <span class="p">(</span><span class="nb">setf</span> <span class="p">(</span><span class="nv">csv-error-line-number</span> <span class="nv">c</span><span class="p">)</span> <span class="nv">line-number</span><span class="p">))))</span>
              <span class="c1">;; If this restart is invoked, validation will continue</span>
              <span class="c1">;; on the next field in the row</span>
              <span class="p">(</span><span class="nb">with-simple-restart</span> <span class="p">(</span><span class="nv">continue-next-field</span> <span class="s">"Continue validation on next field."</span><span class="p">)</span>
                <span class="p">(</span><span class="nv">validate-field</span> <span class="nv">header</span> <span class="nv">field</span><span class="p">))))))))</span>
</code></pre></div></div>

<p>Time for some fun now. Pass an invalid file to the validator, and what do we see in the debugger? Two new restarts: <code class="language-plaintext highlighter-rouge">CONTINUE-NEXT-FIELD</code>, and <code class="language-plaintext highlighter-rouge">CONTINUE-NEXT-ROW</code>. Select any one of them to see the validation move forward. The <code class="language-plaintext highlighter-rouge">ABORT</code> restart should be present all the time, so we can end the validation any time we want.</p>

<h2 id="starting-all-over-again">Starting all over again</h2>

<p>We’ll add one more restart now: this will allow us to revalidate the whole file if an error is signalled.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; Note that what was known as VALIDATE-CSV earlier is now called</span>
<span class="c1">;; VALIDATE-CSV-AUX.</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">validate-csv</span> <span class="p">(</span><span class="nv">file</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">restart-case</span> <span class="p">(</span><span class="nv">validate-csv-aux</span> <span class="nv">file</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">retry-file</span> <span class="p">()</span>
      <span class="ss">:report</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nc">stream</span><span class="p">)</span>
                <span class="p">(</span><span class="nb">format</span> <span class="nc">stream</span> <span class="s">"Retry validating the file ~A."</span> <span class="nv">file</span><span class="p">))</span>
      <span class="p">(</span><span class="nv">validate-csv</span> <span class="nv">file</span><span class="p">))))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">validate-csv-aux</span> <span class="p">(</span><span class="nv">file</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">destructuring-bind</span> <span class="p">(</span><span class="nv">headers</span> <span class="o">.</span> <span class="nv">rows</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">parse-csv-file</span> <span class="nv">file</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">loop</span>
       <span class="nv">for</span> <span class="nv">row</span> <span class="nv">in</span> <span class="nv">rows</span>
       <span class="nv">for</span> <span class="nv">line-number</span> <span class="nv">upfrom</span> <span class="mi">2</span>
       <span class="nb">do</span>
       <span class="p">(</span><span class="nb">with-simple-restart</span> <span class="p">(</span><span class="nv">continue-next-row</span> <span class="s">"Continue validation on next row."</span><span class="p">)</span>
         <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">/=</span> <span class="p">(</span><span class="nb">length</span> <span class="nv">row</span><span class="p">)</span> <span class="p">(</span><span class="nb">length</span> <span class="nv">headers</span><span class="p">))</span>
           <span class="p">(</span><span class="nv">csv-error</span> <span class="s">"Number of fields doesn't equal number of headers."</span>
                      <span class="ss">:line-number</span> <span class="nv">line-number</span><span class="p">))</span>
         <span class="p">(</span><span class="nb">loop</span>
            <span class="nv">for</span> <span class="nv">header</span> <span class="nv">in</span> <span class="nv">headers</span>
            <span class="nv">for</span> <span class="nv">field</span> <span class="nv">in</span> <span class="nv">row</span>
            <span class="nb">do</span>
            <span class="p">(</span><span class="nb">handler-bind</span>
                <span class="p">((</span><span class="nv">csv-error</span> <span class="nf">#'</span><span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">c</span><span class="p">)</span>
                                <span class="p">(</span><span class="nb">setf</span> <span class="p">(</span><span class="nv">csv-error-line-number</span> <span class="nv">c</span><span class="p">)</span> <span class="nv">line-number</span><span class="p">))))</span>
              <span class="p">(</span><span class="nb">with-simple-restart</span> <span class="p">(</span><span class="nv">continue-next-field</span> <span class="s">"Continue validation on next field."</span><span class="p">)</span>
                <span class="p">(</span><span class="nv">validate-field</span> <span class="nv">header</span> <span class="nv">field</span><span class="p">))))))))</span>
</code></pre></div></div>

<p>Now what happens if we pass an invalid file to validate-csv? We get the <code class="language-plaintext highlighter-rouge">RETRY-FILE</code> restart in the debugger. This means that we can fix the problematic field, save the file, and start the validation all over again, without having exited the debugger!</p>

<h2 id="handling-restarts">Handling restarts</h2>

<p>Apart from the debugger, we can also handle restarts using <code class="language-plaintext highlighter-rouge">handler-bind</code> and <code class="language-plaintext highlighter-rouge">find-restart</code>.</p>

<p>For example, the following function will continue validating the file as long as <code class="language-plaintext highlighter-rouge">CSV-ERROR</code>s are signalled and one of <code class="language-plaintext highlighter-rouge">CONTINUE-NEXT-FIELD</code> or <code class="language-plaintext highlighter-rouge">CONTINUE-NEXT-ROW</code> restarts is available. It collects those errors in a list and returns the same.</p>

<div class="language-cl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">list-csv-errors</span> <span class="p">(</span><span class="nv">file</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">result</span> <span class="no">nil</span><span class="p">))</span>
    <span class="p">(</span><span class="nb">handler-bind</span>
        <span class="p">((</span><span class="nv">csv-error</span> <span class="nf">#'</span><span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">c</span><span class="p">)</span>
                        <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nc">restart</span> <span class="p">(</span><span class="nb">or</span> <span class="p">(</span><span class="nb">find-restart</span> <span class="ss">'continue-next-field</span><span class="p">)</span>
                                           <span class="p">(</span><span class="nb">find-restart</span> <span class="ss">'continue-next-row</span><span class="p">))))</span>
                          <span class="p">(</span><span class="nb">when</span> <span class="nc">restart</span>
                            <span class="p">(</span><span class="nb">push</span> <span class="nv">c</span> <span class="nv">result</span><span class="p">)</span>
                            <span class="p">(</span><span class="nb">invoke-restart</span> <span class="nc">restart</span><span class="p">))))))</span>

      <span class="p">(</span><span class="nv">validate-csv</span> <span class="nv">file</span><span class="p">))</span>
    <span class="p">(</span><span class="nb">nreverse</span> <span class="nv">result</span><span class="p">)))</span>
</code></pre></div></div>

<p>If we want a non-programmer to use the validator, we can provide a way to upload the CSV file (e.g. using Hunchentoot) and give a nicely formatted output of list-csv-errors in the browser.</p>

<h2 id="conclusion">Conclusion</h2>

<p>What I really like about the condition system is how it allows one to defer decisions to higher-level functions. The low-level functions provide different ways to move forward in case of exceptions (this is what <code class="language-plaintext highlighter-rouge">validate-csv</code> does), while the higher-level functions actually get to decide what path to take (like <code class="language-plaintext highlighter-rouge">list-csv-errors</code>).</p>

<p>If we wanted <code class="language-plaintext highlighter-rouge">list-csv-errors</code> to list only one error per each row, that change would have been trivial, thanks to the restarts we have provided. This separation of logic, IMHO, makes it a very elegant tool in dealing with problems like these.</p>]]></content><author><name>Chaitanya Gupta</name></author><category term="lisp" /><summary type="html"><![CDATA[This post originally appeared on chaitanyagupta.com.]]></summary></entry></feed>