<?xml version="1.0" encoding="utf-8"?> 
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
 <title type="text">Fragments: Posts tagged 'programming'</title>
 <link rel="self" href="https://www.tfeb.org/fragments/feeds/programming.atom.xml" />
 <link href="https://www.tfeb.org/fragments/tags/programming.html" />
 <id>urn:https-www-tfeb-org:-fragments-tags-programming-html</id>
 <updated>2025-10-31T12:40:33Z</updated>
 <entry>
  <title type="text">Disentangling iteration from value accumulation</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2025/10/31/disentangling-iteration-from-value-accumulation/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2025-10-31-disentangling-iteration-from-value-accumulation</id>
  <published>2025-10-31T12:40:33Z</published>
  <updated>2025-10-31T12:40:33Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;Iteration forms and forms which accumulate values don&amp;rsquo;t have to be the same thing. I think that it turns out that separating them works rather well.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;There&amp;rsquo;s no one true way to write programs, especially in Lisp&lt;sup&gt;&lt;a href="#2025-10-31-disentangling-iteration-from-value-accumulation-footnote-1-definition" name="2025-10-31-disentangling-iteration-from-value-accumulation-footnote-1-return"&gt;1&lt;/a&gt;&lt;/sup&gt;: a language whose defining feature is that it supports and encourages the seamless construction of new programming languages&lt;sup&gt;&lt;a href="#2025-10-31-disentangling-iteration-from-value-accumulation-footnote-2-definition" name="2025-10-31-disentangling-iteration-from-value-accumulation-footnote-2-return"&gt;2&lt;/a&gt;&lt;/sup&gt;. In particular there are plenty of different approaches to iteration, and to accumulating values during iteration. In CL there are at least three approaches in the base language:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;constructs which map a function over some &amp;lsquo;iterable&amp;rsquo; object, often a list or a sequence of some other kind, to build another object with the results, as by &lt;code&gt;mapcar&lt;/code&gt; for instance;&lt;/li&gt;
 &lt;li&gt;constructs which just iterate, as by &lt;code&gt;dotimes&lt;/code&gt;;&lt;/li&gt;
 &lt;li&gt;iteration constructs which combine iteration with possible value accumulation, such as &lt;code&gt;do&lt;/code&gt; and of course &lt;code&gt;loop&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;What CL &lt;em&gt;doesn&amp;rsquo;t&lt;/em&gt; have is any constructs which simply accumulate values. So, for instance, if you wanted to acquire the even numbers from a list with &lt;code&gt;dolist&lt;/code&gt; you might write&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(let ((evens '()))
  (dolist (e l (nreverse evens))
    (when (and (realp e) (evenp e))
      (push e evens))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course you could do this with &lt;code&gt;loop&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(loop for e in l
      when (and (realp e) (evenp e)) collect e)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;but &lt;code&gt;loop&lt;/code&gt; is a construct which combines iteration and value collection.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s tempting to say that, well, can&amp;rsquo;t you turn &lt;em&gt;all&lt;/em&gt; iteration into mapping? Python sort of does this: objects can be &amp;lsquo;iterable&amp;rsquo;, and you can iterate over anything iterable, and then comprehensions let you accumulate values. But in general this doesn&amp;rsquo;t work very well: consider a file which you want to iterate over. But &lt;em&gt;how&lt;/em&gt;? Do you want to iterate over its characters, its bytes, its lines, its words, over some other construct in the file? You can&amp;rsquo;t just say &amp;lsquo;a file is iterable&amp;rsquo;: it is, but you have to specify the intent before iterating over it&lt;sup&gt;&lt;a href="#2025-10-31-disentangling-iteration-from-value-accumulation-footnote-3-definition" name="2025-10-31-disentangling-iteration-from-value-accumulation-footnote-3-return"&gt;3&lt;/a&gt;&lt;/sup&gt;. You also have the problem that you very often only want to return &lt;em&gt;some&lt;/em&gt; values, so the notion of &amp;lsquo;mapping&amp;rsquo; is not very helpful. If you try and make everything be mapping you end up with ugly things like &lt;code&gt;mapcan&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You do need general iteration constructs, I think: constructs which say &amp;lsquo;is there more? if there is give me the next thing&amp;rsquo;. In CL both the standard general iteration constructs combine, or can combine, iteration with accumulation: there is no pure general iteration construct. And there are no pure value accumulation constructs at all.&lt;/p&gt;

&lt;h2 id="from-maclisp-to-cl"&gt;From Maclisp to CL&lt;/h2&gt;

&lt;p&gt;An interesting thing happened in the transition from Maclisp to CL.&lt;/p&gt;

&lt;p&gt;Maclisp had &lt;a href="https://www.maclisp.info/pitmanual/contro.html#5.9.1"&gt;&lt;code&gt;prog&lt;/code&gt;&lt;/a&gt;, which was a special operator (it would have called it a special form), and which combined the ability to use &lt;code&gt;go&lt;/code&gt; and to say &lt;code&gt;return&lt;/code&gt;. This is a construct which dates back to the very early days of Lisp.&lt;/p&gt;

&lt;p&gt;Common Lisp also has &lt;a href="https://www.lispworks.com/documentation/HyperSpec/Body/m_prog_.htm" title="prog"&gt;&lt;code&gt;prog&lt;/code&gt;&lt;/a&gt;, but now it&amp;rsquo;s a macro, not a special operator. The reason its a macro is that CL has split the functionality of &lt;code&gt;prog&lt;/code&gt; into three parts (four parts if you include variable binding):&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;a href="https://www.lispworks.com/documentation/HyperSpec/Body/s_progn.htm" title="progn"&gt;&lt;code&gt;progn&lt;/code&gt;&lt;/a&gt; is a special operator which evaluates the forms in its body in order;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://www.lispworks.com/documentation/HyperSpec/Body/s_tagbod.htm" title="tagbody"&gt;&lt;code&gt;tagbody&lt;/code&gt;&lt;/a&gt; is a special operator whch allows tags and &lt;code&gt;go&lt;/code&gt; in its body;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://www.lispworks.com/documentation/HyperSpec/Body/s_block.htm" title="block"&gt;&lt;code&gt;block&lt;/code&gt;&lt;/a&gt; is a special operator which supports &lt;code&gt;return&lt;/code&gt; and &lt;code&gt;return-from&lt;/code&gt;&lt;/li&gt;
 &lt;li&gt;and of course &lt;a href="https://www.lispworks.com/documentation/HyperSpec/Body/s_let_l.htm" title="let"&gt;&lt;code&gt;let&lt;/code&gt;&lt;/a&gt; provides binding of variables.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Maclisp had &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;progn&lt;/code&gt;: what it &lt;em&gt;didn&amp;rsquo;t&lt;/em&gt; have was &lt;code&gt;tagbody&lt;/code&gt; and &lt;code&gt;block&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;These can be combined (you don&amp;rsquo;t in fact need &lt;code&gt;progn&lt;/code&gt; in this case) to form &lt;code&gt;prog&lt;/code&gt;, which is something like&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defmacro prog ((&amp;amp;rest bindings)
                &amp;amp;body tags/forms)
  `(block nil
     (let ,@bindings
       (tagbody
        ,@tags/forms)
       nil)))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So what CL has done is to divide &lt;code&gt;prog&lt;/code&gt; into its component parts, which then can be used individually in other ways: it has provided the components of &lt;code&gt;prog&lt;/code&gt; as individual constructs. You can build &lt;code&gt;prog&lt;/code&gt; from these, but you can build other things as well (&lt;code&gt;defun&lt;/code&gt; expands to something involving &lt;code&gt;block&lt;/code&gt;, for instance), including things which don&amp;rsquo;t exist in base CL.&lt;/p&gt;

&lt;h2 id="a-linguistic-separation-of-concerns"&gt;A linguistic separation of concerns&lt;/h2&gt;

&lt;p&gt;What CL has achieved is a &lt;em&gt;separation of concerns&lt;/em&gt; at the language level: it has reduced the number of concerns addressed by each construct. It hasn&amp;rsquo;t done this completely: &lt;code&gt;progn&lt;/code&gt; is not the only special operator which sequences the forms in its body, for instance, and &lt;code&gt;let&lt;/code&gt; is not a macro defined in terms of &lt;code&gt;lambda&lt;/code&gt;. But it&amp;rsquo;s taken steps in this direction compared to Maclisp.&lt;/p&gt;

&lt;p&gt;This approach is really only viable for languages which have powerful macro systems where macros are not syntactically distinguished. Without a macro system then separating concerns at the language level would make almost all programs more verbose since constructs which combine lower-level ones can&amp;rsquo;t be created. With a macro system where macros are syntactically distinguished, such as Julia&amp;rsquo;s, then such constructs are always second-class citizens. With a macro system like CL&amp;rsquo;s this is no longer a problem: CL has &lt;code&gt;prog&lt;/code&gt;, for instance, but it&amp;rsquo;s now a macro.&lt;/p&gt;

&lt;p&gt;It seems to me that the only reason &lt;em&gt;not&lt;/em&gt; to take this process as far as it can go in Lisps is if it makes the compiler&amp;rsquo;s job unduly hard. It makes no difference to users of the language, so long as it provides, as CL does the old, unseparated, convenient constructs.&lt;/p&gt;

&lt;h2 id="from-cl-to-here-knows-when"&gt;From CL to here knows when&lt;/h2&gt;

&lt;p&gt;I can&amp;rsquo;t redesign CL and don&amp;rsquo;t want to do that. But I can experiment with building a language I&amp;rsquo;d like to use on top of it.&lt;/p&gt;

&lt;p&gt;In particular CL has already provided the separated constructs you need to build your own iteration constructs, and no CL iteration constructs are special operators. Just as &lt;code&gt;do&lt;/code&gt; is constructed from (perhaps) &lt;code&gt;let&lt;/code&gt;, &lt;code&gt;block&lt;/code&gt; and &lt;code&gt;tagbody&lt;/code&gt;, and &lt;code&gt;loop&lt;/code&gt; is constructed from some horrid soup if the same things, you can build your own iteration constructs this way. And the same is true for value accumulation constructs. And you can reasonably expect these to perform as well as the ones in the base language.&lt;/p&gt;

&lt;p&gt;This is what I&amp;rsquo;ve done, several times in fact.&lt;/p&gt;

&lt;p&gt;The first thing I built, long ago, was a list accumulation construct called &lt;code&gt;collecting&lt;/code&gt;: within its body there is a local function, &lt;code&gt;collect&lt;/code&gt;, which will accumulate a value onto the list returned from &lt;code&gt;collecting&lt;/code&gt;. It secretly maintains a tail-pointer to the list so accumulation is constant-time. This was originally built to make it simpler to accumulate values when traversing tree or graph structures, to avoid the horrid and, in those days, slow explicit &lt;code&gt;push&lt;/code&gt; &amp;hellip; &lt;code&gt;nreverse&lt;/code&gt; idiom.&lt;/p&gt;

&lt;p&gt;So, for instance&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(collecting
  (labels ((walk (node)
             ...
             (when ... (collect thing))
             ...
             (dolist (...) (walk ...))))
    (walk ...)))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;might walk over some structure, collecting interesting things, and returning a list of them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tfeb.org/fragments/documentation/tfeb-lisp-hax.html#collecting-lists-forwards-and-accumulating-collecting" title="Collecting"&gt;&lt;code&gt;collecting&lt;/code&gt;&lt;/a&gt; was originally based on some ideas in Interlisp-D, and has since metastasized into a, well, collection of related constructs: multiple named collectors (&lt;code&gt;collecting&lt;/code&gt; itself is now defined in terms of this construct), explicit collector objects, general accumulators and most recently a construct which accumulates values into vectors. It works pretty well.&lt;/p&gt;

&lt;p&gt;The second part of the story is high-performance iteration constructs which just iterate, which are general, which are pleasant to use and have semantics which are easy to understand. Both &lt;code&gt;loop&lt;/code&gt;and &lt;code&gt;do&lt;/code&gt; fail the first three of these conditions for me, and &lt;code&gt;loop&lt;/code&gt; fails the fourth as well.&lt;/p&gt;

&lt;p&gt;Well, I&amp;rsquo;ve written a number of iteration constructs and constructs related to iteration. Finally, last year, my friend Zyni &amp;amp; I (the ideas are largely hers, I wrote most of the code I think) came up with &lt;a href="https://tfeb.org/fragments/documentation/star.html" title="Štar"&gt;Štar&lt;/a&gt; which we&amp;rsquo;ve described as &amp;lsquo;a simple and extensible iteration construct&amp;rsquo;. Lots of other people have written iteration constructs for CL: Štar occupies a position which tries to be as extreme as possible while remaining pleasant to use. There are no special keywords, the syntax is pretty much that of &lt;code class="brush: ^4"&gt;let&lt;/code&gt; and there is no value accumulation: all it does is iterate. The core of Štar exports six names, of which the three that support nested iteration are arguably unneeded in the same way that &lt;code&gt;let*&lt;/code&gt; is. Teaching it how to iterate over things is simple, teaching it how to optimize such iterations is usually simple enough to do when it&amp;rsquo;s worth it. And it&amp;rsquo;s within $\varepsilon$ of anything in terms of performance.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s simple (at least in interface) and quick because it hardly does anything, of course: it relies entirely on iterators to do anything at all and iterator optimizers to do anything quickly. Even then all it does is, well, iterate.&lt;/p&gt;

&lt;p&gt;These two components are thus attempts at separating the two parts of something like &lt;code&gt;loop&lt;/code&gt;, &lt;a href="https://iterate.common-lisp.dev" title="Iterate"&gt;Iterate&lt;/a&gt; or &lt;a href="https://github.com/Shinmera/for" title="For"&gt;For&lt;/a&gt;, or other constructs which combine iteration and value accumulation: they are to these constructs what &lt;code&gt;tagbody&lt;/code&gt; and &lt;code&gt;block&lt;/code&gt; are to &lt;code&gt;prog&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id="reinventing-the-wheel"&gt;Reinventing the wheel&lt;/h2&gt;

&lt;p&gt;I used to ride bicycles a lot. And I got interested in the surprisingly non-obvious way that bicycle wheels work. After reading &lt;a href="https://en.wikipedia.org/wiki/The_Bicycle_Wheel" title="The bicycle wheel"&gt;&lt;em&gt;The bicycle wheel&lt;/em&gt;&lt;/a&gt; I decided that I could make wheels, and I did do that.&lt;/p&gt;

&lt;p&gt;And a strange thing happened: although I rationally understood that the wheels I had made were as good or better than any other wheel, for the first little while after building them I was terrified that they would bend or, worse, collapse. There was no rational reason for this: it was just that for some reason I trusted my own workmanship less than I trusted whoever had made the off-the-shelf wheels they&amp;rsquo;d replaced (and, indeed, some of whose parts I had cannibalised to make them).&lt;/p&gt;

&lt;p&gt;Of course they didn&amp;rsquo;t bend or collapse, and I still rode on one of them until quite recently.&lt;/p&gt;

&lt;p&gt;The same thing happened with Štar: for quite a while after finishing it I had to work hard to force myself to use it: even though I knew it was fast and robust. It wasn&amp;rsquo;t helped that one of the basic early iterators was overcomplex and had somewhat fragile performance. It wasn&amp;rsquo;t until I gave up on it and replaced it by a much simpler and more limited one, while also making a much more general iterator fast enough to use for the complicated cases that it felt comfortable.&lt;/p&gt;

&lt;p&gt;This didn&amp;rsquo;t happen with &lt;code&gt;collecting&lt;/code&gt;: I think that&amp;rsquo;s because it did something CL didn&amp;rsquo;t already have versions of, while it&amp;rsquo;s very often possible to replace a construct using Štar with some nasty thing involving &lt;code&gt;do&lt;/code&gt; or some other iteration construct. Also Štar is much bigger than &lt;code&gt;collecting&lt;/code&gt; and it&amp;rsquo;s hard to remember that I&amp;rsquo;m not using a machine with a few MB of memory any more. Perhaps it&amp;rsquo;s also because I first wrote &lt;code&gt;collecting&lt;/code&gt; a very long time ago.&lt;/p&gt;

&lt;p&gt;But I got over this, and now almost the only times I&amp;rsquo;d use any other iteration construct are either when &lt;code&gt;mapcar&lt;/code&gt; &amp;amp;c are obviously right, or when I&amp;rsquo;m writing code for someone else to look at.&lt;/p&gt;

&lt;p&gt;And writing iterators is easy, especially given that you very often do not need optimizers for them: if you&amp;rsquo;re iterating over the lines in a file two function calls per line is not hurting much. Iterators, of course, can also iterate over recursively-defined structures such as trees or DAGs: it&amp;rsquo;s easy to say &lt;code&gt;(for ((leaf (in-graph ... :only-leaves t))) ...)&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id="would-it-help"&gt;Would it help?&lt;/h2&gt;

&lt;p&gt;In my biased experience, yes, quite a lot. I now much prefer writing and reading code that uses &lt;code&gt;for&lt;/code&gt; to code that uses almost any of the standard iteration constructs, and &lt;code&gt;collecting&lt;/code&gt;, together with its friends, simply does not have a standard equivalent at all: if you don&amp;rsquo;t have it, you need either to write it, or implement it explicitly each time.&lt;/p&gt;

&lt;p&gt;But my experience is very biased: I have hated &lt;code&gt;loop&lt;/code&gt; almost since it arrived in CL, and I find using &lt;code&gt;do&lt;/code&gt; for anything non-trivial clumsy enough that I&amp;rsquo;ve previously written &lt;a href="https://tfeb.org/fragments/documentation/tfeb-lisp-hax.html#decomposing-iteration-simple-loops" title="Simple loops"&gt;versions of it which require less repetition&lt;/a&gt;. And of course I was quite involved in the design and implementation of Štar, so it&amp;rsquo;s not surprising that I like it.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m also &lt;a href="https://tfeb.org/fragments/2022/10/03/bradshaw-s-laws/" title="Bradshaw's laws"&gt;very comfortable&lt;/a&gt; with the idea that Lisp is about language design &amp;mdash; in 2025 I don&amp;rsquo;t see any compelling advantage of Lisp &lt;em&gt;other&lt;/em&gt; than constructing languages &amp;mdash; and that people who write Lisp end up writing in their own idiolects. The argument against doing this seems to be that every Lisp project ends up being its own language and this means that it is hard to recruit people. I can only assume that the people who say that have never worked on any large system written in languages other than Lisp&lt;sup&gt;&lt;a href="#2025-10-31-disentangling-iteration-from-value-accumulation-footnote-4-definition" name="2025-10-31-disentangling-iteration-from-value-accumulation-footnote-4-return"&gt;4&lt;/a&gt;&lt;/sup&gt;: &lt;a href="https://en.wikipedia.org/wiki/Greenspun's_tenth_rule" title="Greenspun's tenth rule"&gt;Greenspun&amp;rsquo;s tenth rule&lt;/a&gt; very much applies to these systems.&lt;/p&gt;

&lt;p&gt;In summary: yes, it would help.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id="an-example"&gt;An example&lt;/h2&gt;

&lt;p&gt;In the examples directory for Štar there is an iterator called &lt;code&gt;in-graph&lt;/code&gt; which can iterate over any graph, if it knows how to find the neighbours of a node. For instance:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (for ((n (in-graph (list '(a b (c b) d))
                     (lambda (n)
                       (if (atom n) '() (cdr n))))))
    (print n))

(a b (c b) d) 
b 
(c b) 
b 
d 
nil

&amp;gt; (for ((n (in-graph (list '(a b (c b) d))
                     (lambda (n)
                       (if (atom n) '() (cdr n)))
                     :unique t)))
    (print n))

(a b (c b) d) 
b 
(c b) 
d 
nil

&amp;gt; (for ((n (in-graph (list '(a b (c b) d))
                     (lambda (n)
                       (if (atom n) '() (cdr n)))
                     :order :breadth-first)))
    (print n))

(a b (c b) d) 
b 
(c b) 
d 
b 
nil

&amp;gt; (collecting (for ((n (in-graph (list '(a b (c b) d))
                                 (lambda (n)
                                   (if (atom n) '() (cdr n)))
                                 :unique t
                                 :only-leaves t)))
                (collect n)))
(b d)&lt;/code&gt;&lt;/pre&gt;

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

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (setf *print-circle* t)
t

&amp;gt; (for ((n (in-graph (list '#1=(a #2=(b c #1#) d #2#))
                     (lambda (n)
                       (if (atom n) '() (cdr n)))
                     :unique t)))
    (print n))

#1=(a #2=(b c #1#) d #2#) 
#1=(b c (a #1# d #1#)) 
c 
d 
nil&lt;/code&gt;&lt;/pre&gt;

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

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (for ((p (in-graph (list *package*) #'package-use-list
                     :unique t :order :breadth-first)))
    (format t "~&amp;amp;~A~%" (package-name p)))
COMMON-LISP-USER
ORG.TFEB.DSM
ORG.TFEB.HAX.ITERATE
ORG.TFEB.HAX.COLLECTING
ORG.TFEB.STAR
ORG.TFEB.TOOLS.REQUIRE-MODULE
COMMON-LISP
HARLEQUIN-COMMON-LISP
LISPWORKS
ORG.TFEB.HAX.UTILITIES
ORG.TFEB.HAX.SIMPLE-LOOPS
ORG.TFEB.HAX.SPAM
ORG.TFEB.DSM/IMPL
nil&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;in-graph&lt;/code&gt; is fairly simple, and uses both collectors and Štar in its own implementation:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun in-graph (roots node-neighbours &amp;amp;key
                       (only-leaves nil)
                       (order ':depth-first)
                       (unique nil)
                       (test #'eql)
                       (key #'identity))
  ;; Preorder / postorder would be nice to have
  "Iterate over a graph

- ROOTS are the nodes to start from.
- NODE-NEIGHBOURS is a function which, given a node, returns its
  neighbours if any.
- ORDER may be :DEPTH-FIRST (default) or :BREADTH-FIRST.
- UNIQUE, if given, will iterate nodes uniquely.
- TEST is the comparison test for nodes: it must be something
  acceptable to MAKE-HASH-TABLE.  Default is #'EQL.
- KEY, if given, extracts a key from a node for comparison in the
  usual way.

There is no optimizer.

If the graph is cyclic an iteration using this will not terminate
unless UNIQUE is true, unless some other clause stops it.  If the
graph is not directed you also need to use UNIQUE."
  (check-type order (member :depth-first :breadth-first))
  (let ((agenda (make-collector :initial-contents roots))
        (duplicate-table (if unique (make-hash-table :test test) nil))
        (this nil))
    (values
     (thunk                             ;predicate does all the work
       (if (collector-empty-p agenda)
           nil
         (for ((it (stepping (it :as (pop-collector agenda)))))
           (let ((neighbours (funcall node-neighbours it))
                 (k (and unique (funcall key it))))
             (cond
              ((and unique (gethash k duplicate-table))
               ;; It's a duplicate: skip
               (if (collector-empty-p agenda)
                   (final nil)
                 (next)))
              ((null neighbours)
               ;; Leaf, add it to the duplicate table if need be and say we found something
               (when unique
                 (setf (gethash k duplicate-table) t))
               (setf this it)
               (final t))
              (t
               ;; Not a leaf: update the agenda ...
               (setf agenda
                     (case order
                       (:depth-first
                        (nconc-collectors (make-collector :initial-contents neighbours) agenda))
                       (:breadth-first
                        (nconc-collectors agenda (make-collector :initial-contents neighbours)))))
               ;; .. add it to the duplicate table if need be so it's
               ;; skipped next time ...
               (when unique               
                 (setf (gethash k duplicate-table) t))
               ;; ... and decide if we found something
               (cond
                (only-leaves
                 (if (collector-empty-p agenda)
                     (final nil)
                   (next)))
                 (t
                  (setf this it)
                  (final t)))))))))
     (thunk this))))&lt;/code&gt;&lt;/pre&gt;

&lt;hr /&gt;

&lt;div class="footnotes"&gt;
 &lt;ol&gt;
  &lt;li id="2025-10-31-disentangling-iteration-from-value-accumulation-footnote-1-definition" class="footnote-definition"&gt;
   &lt;p&gt;&amp;lsquo;Lisp&amp;rsquo; here will usually mean &amp;lsquo;Common Lisp&amp;rsquo;.&amp;nbsp;&lt;a href="#2025-10-31-disentangling-iteration-from-value-accumulation-footnote-1-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2025-10-31-disentangling-iteration-from-value-accumulation-footnote-2-definition" class="footnote-definition"&gt;
   &lt;p&gt;Although if you use &lt;code&gt;loop&lt;/code&gt; you must accept that you will certainly suffer eternal damnation. Perhaps that&amp;rsquo;s worth it: Robert Johnson thought so, anyway.&amp;nbsp;&lt;a href="#2025-10-31-disentangling-iteration-from-value-accumulation-footnote-2-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2025-10-31-disentangling-iteration-from-value-accumulation-footnote-3-definition" class="footnote-definition"&gt;
   &lt;p&gt;This is the same argument that explains why a universal equality predicate is nonsensical: equality of objects depends on what they are equal &lt;em&gt;as&lt;/em&gt; and that is often not implicit in the objects.&amp;nbsp;&lt;a href="#2025-10-31-disentangling-iteration-from-value-accumulation-footnote-3-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2025-10-31-disentangling-iteration-from-value-accumulation-footnote-4-definition" class="footnote-definition"&gt;
   &lt;p&gt;Or in Lisp, more than likely.&amp;nbsp;&lt;a href="#2025-10-31-disentangling-iteration-from-value-accumulation-footnote-4-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content></entry>
 <entry>
  <title type="text">Minimum clown</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2025/08/26/minimum-clown/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2025-08-26-minimum-clown</id>
  <published>2025-08-26T14:29:31Z</published>
  <updated>2025-08-26T14:29:31Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;Hosting code on GitHub now seems like an invitation to have it turned into AI slop. Here&amp;rsquo;s what I did to move.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;blockquote&gt;
 &lt;p&gt;Isn&amp;rsquo;t it rich?
  &lt;br /&gt;Are we a pair?
  &lt;br /&gt;Me here at last on the ground,
  &lt;br /&gt;You in mid-air.
  &lt;br /&gt;Send in the clowns.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;I think the number of people who care about, let alone rely on, my Lisp code who I don&amp;rsquo;t personally know is somewhere between few and none by now. Nevertheless, it makes me feel honest to publish some of what I write, in the hope someone might find it useful.&lt;/p&gt;

&lt;p&gt;Long ago, I did that by simply putting files on my vanity site (in the days when people had vanity sites). At some point it became clear that this was not the right answer, and the thing to do was to keep things on one of the newfangled source-hosting sites. I have never been and will never be comfortable with the idea of the canonical version of anything I make not sitting on storage that I control &amp;mdash; people who do that are not thinking hard enough in my opinion &amp;mdash; which means that no source-hosting site based on a centralised source control system was at all interesting.&lt;/p&gt;

&lt;h2 id="send-in-the-clowns"&gt;Send in the clowns&lt;/h2&gt;

&lt;p&gt;And then git arrived, and sometime after it, GitHub. Git meant that I could both keep the canonical versions of things somewhere safe while making them publicly available. At about the same time I was realising that vanity sites were, well, vanity, and the antique documentation written in raw HTML with its origins in the mid 1990s really needed to be turned into something better, anyway.&lt;/p&gt;

&lt;p&gt;Well, it was more complicated, of course. I have a source tree which contains history that&amp;rsquo;s not public and some of which is very old&lt;sup&gt;&lt;a href="#2025-08-26-minimum-clown-footnote-1-definition" name="2025-08-26-minimum-clown-footnote-1-return"&gt;1&lt;/a&gt;&lt;/sup&gt;. So after initially pushing a frozen version of what used to be on my vanity site, I organised things into various &amp;lsquo;publication repos&amp;rsquo; which get populated (by &lt;code&gt;make&lt;/code&gt;) from the source tree. These have simplified histories, often really only being a series of release versions. And this worked fine.&lt;/p&gt;

&lt;p&gt;I never really used much of the mechanism provided by GitHub: I didn&amp;rsquo;t need it, and doing so would have broken my rule of not depending on things I don&amp;rsquo;t have control over.&lt;/p&gt;

&lt;p&gt;In 2018 Microsoft bought GitHub, and&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;THIS IS WHAT HAPPENS WHEN YOU STORE YOUR DATA IN THE CLOWN.&lt;/p&gt;
 &lt;p&gt;The Clown is just &lt;em&gt;someone else&amp;rsquo;s computer&lt;/em&gt; and they can and will &lt;em&gt;fuck&lt;/em&gt; you. If it&amp;rsquo;s not on your computer, it&amp;rsquo;s not under your control. Why do you all keep doing this to yourselves??&lt;/p&gt;
 &lt;p&gt;Stop hitting yourself. Seriously, stop it.
  &lt;br /&gt;&amp;mdash; &lt;a href="https://www.jwz.org/blog/2018/06/lol-github/" title="LOL Github"&gt;jwz&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;But I wasn&amp;rsquo;t worried, because I was not storing my data in the clown: I was just publishing copies of it there. I felt kind of smug about that. I hadn&amp;rsquo;t worked out, in 2018, how bad things could get and how fast. I had worked out that if you were not paying the clown, then the clown was feeding on your soul, but I didn&amp;rsquo;t think it would get any useful nutrition from the parts of my soul it could reach. And other things were going on which distracted me.&lt;/p&gt;

&lt;p&gt;Fast forward to mid&amp;ndash;2025, and GitHub is a subsidiary of Microsoft&amp;rsquo;s &amp;lsquo;weaponized bullshit&amp;rsquo; division: it is time, and past time, to go.&lt;/p&gt;

&lt;p&gt;Where? Well there are other clowns. But no: they may be good clowns, for now, but they&amp;rsquo;re still clowns. Clowns are, well, clowns: you don&amp;rsquo;t want to be trusting them. You want a &lt;em&gt;minimum clown&lt;/em&gt; policy.&lt;/p&gt;

&lt;h2 id="where-are-the-clowns"&gt;Where are the clowns?&lt;/h2&gt;

&lt;p&gt;So here&amp;rsquo;s what I am doing.&lt;/p&gt;

&lt;p&gt;If you can live with git&amp;rsquo;s &lt;a href="https://git-scm.com/docs/http-protocol" title="HTTP protocol"&gt;dumb HTTP protocol&lt;/a&gt; then any web server which can host static files can host read-only git repos. To push to them you need some smarter protocol, and you need to have a hook which does &lt;code&gt;git update-server-info&lt;/code&gt; after any change: this should be in the &lt;code&gt;post-update&lt;/code&gt; hook, really. All these repos will be read-only and public, so I don&amp;rsquo;t need access control or authentication.&lt;/p&gt;

&lt;p&gt;To actually make them exist you need more. Fortunately the people who host my vanity domain provide SSH access and &lt;code&gt;git&lt;/code&gt; exists on the server. So that&amp;rsquo;s enough to create a repo, add the hook and then push everything to it as and when I need to.&lt;/p&gt;

&lt;p&gt;For documentation: I am already using &lt;a href="https://docs.racket-lang.org/frog/index.html" title="Frog"&gt;Frog&lt;/a&gt; for, for instance, this post. And Frog has the nice feature that you can just add Markdown files in a directory (or any subdirectory) it knows about and it will turn them into HTML. So I wrote a makefile to copy &lt;code&gt;README.md&lt;/code&gt; files from publication repos and suitably munged the original GitHub Pages index page.&lt;/p&gt;

&lt;p&gt;Then there were a bunch of small changes such as telling &lt;code&gt;rsync&lt;/code&gt; not to clobber the repos when updating things, gluing makefiles together so suitable things happen in subdirectories and &lt;code&gt;make publish&lt;/code&gt; does everything needed.&lt;/p&gt;

&lt;p&gt;What this needs is a web server that can host static files with enough storage (which is not a great deal), and a way of syncing local content to it. SSH access, git on the server and &lt;code&gt;rsync&lt;/code&gt; make things quite a bit easier but I could maintain the public repos locally and sync them to the web server however it allowed that.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m pretty confident that any other hosting provider I might one day switch to&lt;sup&gt;&lt;a href="#2025-08-26-minimum-clown-footnote-2-definition" name="2025-08-26-minimum-clown-footnote-2-return"&gt;2&lt;/a&gt;&lt;/sup&gt; will provide that.&lt;/p&gt;

&lt;h2 id="well-maybe-next-year"&gt;Well, maybe next year&lt;/h2&gt;

&lt;p&gt;If I was a big player I think I would simply delete my GitHub repos and put up a message saying where people could now find things. I&amp;rsquo;m not a big player, so what I did is to make the repos read-only (GitHub calls this &amp;lsquo;archiving&amp;rsquo;) and add suitable links. I&amp;rsquo;ve done this for all my main Lisp repos: I have some more to do. Archiving means people may never notice: so be it. I plan to tell, for instance, Quicklisp in due course. I also have some non-public (clones of) repos on GitHub which I will just host outside the web server tree, accessing them only via SSH.&lt;/p&gt;

&lt;p&gt;There are, inevitably, some changes to the Markdown parsing, which I need to chase down and fix in the source. There already were incompatibilities amongst GitHub&amp;rsquo;s various parsers.&lt;/p&gt;

&lt;p&gt;When I&amp;rsquo;ve finished all this, I probably will replace my GitHub Pages site by something which just points at the canonical place.&lt;/p&gt;

&lt;p&gt;There will be no releases: I&amp;rsquo;ll just post things announcing changes with tag names. There is no big tracking: just mail me.&lt;/p&gt;

&lt;p&gt;Where things are&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;a href="https://tfeb.org/computer/" title="tfeb.org/computer/"&gt;tfeb.org/computer/&lt;/a&gt; is the list of things;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://tfeb.org/computer/repos/" title="tfeb.org/computer/repos/"&gt;tfeb.org/computer/repos/&lt;/a&gt; is where the repos are;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://tfeb.org/fragments/documentation/" title="tfeb.org/fragments/documentation/"&gt;tfeb.org/fragments/documentation/&lt;/a&gt; is the list of documentation.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;And that is all.&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;Isn&amp;rsquo;t it rich?
  &lt;br /&gt;Isn&amp;rsquo;t it queer,
  &lt;br /&gt;Losing my timing this late
  &lt;br /&gt;In my career?
  &lt;br /&gt;And where are the clowns?
  &lt;br /&gt;There ought to be clowns.
  &lt;br /&gt;Well, maybe next year.&lt;/p&gt;&lt;/blockquote&gt;

&lt;hr /&gt;

&lt;div class="footnotes"&gt;
 &lt;ol&gt;
  &lt;li id="2025-08-26-minimum-clown-footnote-1-definition" class="footnote-definition"&gt;
   &lt;p&gt;It turns out I never did import all the CVS versions of things, although I meant to.&amp;nbsp;&lt;a href="#2025-08-26-minimum-clown-footnote-1-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2025-08-26-minimum-clown-footnote-2-definition" class="footnote-definition"&gt;
   &lt;p&gt;Pair, my current provider, are fine. But they are also American, and I&amp;rsquo;d rather use a provider based in a democracy.&amp;nbsp;&lt;a href="#2025-08-26-minimum-clown-footnote-2-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content></entry>
 <entry>
  <title type="text">The modern real programmer</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2025/01/31/the-modern-real-programmer/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2025-01-31-the-modern-real-programmer</id>
  <published>2025-01-31T19:17:18Z</published>
  <updated>2025-01-31T19:17:18Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;This is adapted from an email from my friend Zyni, used with her permission. Don&amp;rsquo;t take it too seriously.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;Real programmers do not write programs like this. If a real programmer has to deal with a collection of particles, they do not have some silly object which represents a particle, perhaps made up of other objects representing physical vectors, and then some array of pointers to these particle objects. That is a bourgeois fantasy and the people who do that will not long survive the revolution. They will die due to excessive pointer-chasing; many of them have already died of quiche.&lt;/p&gt;

&lt;p&gt;Real programmers do today as they have always done: if they have some particles to simulate a galaxy they make an array of floating point numbers, in which the particles live.&lt;/p&gt;

&lt;p&gt;This is how it has always been done, and how it always will be done, by people who care about performance.&lt;/p&gt;

&lt;p&gt;And this is why Lisp is so superb. Because you can write this:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(for* ((i1 (in-particle-vector-indices pv))
       (i2 (in-particle-vector-indices pv i1)))
  (declare (type particle-vector-index i1 i2))
  (with-particle-at (i1 pv :name p1)
    (with-particle-at (i2 pv :name p2)
      (let/fpv ((rx (- p2-x p1-x))
                (ry ...)
                ...)
        ... compute interactions ...))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And this is:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;very fast&lt;sup&gt;&lt;a href="#2025-01-31-the-modern-real-programmer-footnote-1-definition" name="2025-01-31-the-modern-real-programmer-footnote-1-return"&gt;1&lt;/a&gt;&lt;/sup&gt;, because it all turns into optimized loops over suitable &lt;code&gt;(simple-array double-float (*))&lt;/code&gt; with no silly objects or consing;&lt;/li&gt;
 &lt;li&gt;relatively easy for a human to read, since you can see, for instance what &lt;code&gt;(for ((i (in-particle-vector-indices v))) ...)&lt;/code&gt; is doing and do not have to second-guess some idiot &lt;code&gt;loop&lt;/code&gt; form which will be full of obscure bugs;&lt;/li&gt;
 &lt;li&gt;quiche-compatible: you can easily write a function &lt;code&gt;particle-at&lt;/code&gt; which will construct a &lt;code&gt;particle&lt;/code&gt; object from a particle vector entry (such a function will later be excised as it has no callers, of course);&lt;/li&gt;
 &lt;li&gt;perhaps most important it is possible for a &lt;em&gt;program&lt;/em&gt; to take this code and to look at it and to say, &amp;lsquo;OK, this is an iteration over a particle vector – it is not some stupid hard-to-parse &lt;code&gt;(loop for ... oh I have no idea what this is ...)&lt;/code&gt; as used by the quiche people, it is &lt;code&gt;(for ((i (in-particle-vector-indices v))) ...)&lt;/code&gt; and it is very easy to see what this is – and there are things I can do with that&amp;rsquo; and generate Fortran which can be easily (or, less difficultly &amp;mdash; is &amp;lsquo;difficultly&amp;rsquo; a word? English is so hard) be made to run well on proper machines with sensible numbers of processors.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;And this is the thing they still do not see. You write your program which uses the only useful data structure, but you also write your program in a language you have built designed so that both a human and another program can understand it, and do useful things with it, because your program says what it means. Every construct in your program should be designed so that this other program can get &lt;em&gt;semantic&lt;/em&gt; information from that construct to turn it into something else.&lt;/p&gt;

&lt;p&gt;And this is why Lisp is so uniquely useful for real orogrammers. Lisp has only one interesting feature today: it is a language not for writing programs, but for writing &lt;em&gt;languages&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That is what real programmers do: they build languages to solve their problems. The real programmer understands only two things:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;the only data structure worth knowing about is the array;&lt;/li&gt;
 &lt;li&gt;her job as a programmer is to &lt;em&gt;write languages&lt;/em&gt; which will make writing programs to manipulate arrays easy for a human to understand;&lt;/li&gt;
 &lt;li&gt;and her other job is to write other programs which will take these programs and turn them into Fortran;&lt;/li&gt;
 &lt;li&gt;and when that is done she can go and ride her lovely cob to the fair.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Real programmers also can count only to two.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class="footnotes"&gt;
 &lt;ol&gt;
  &lt;li id="2025-01-31-the-modern-real-programmer-footnote-1-definition" class="footnote-definition"&gt;
   &lt;p&gt;I (Tim, not Zyni, who would use a cleverer integrator) wrote a mindless program to integrate systems of gravitating particles to test some of the things we&amp;rsquo;ve written that are mentioned in this email. On an Apple M1 it sustains well over 1 double precision GFLOP. Without using the GPU I think this is about what the processor can do.&amp;nbsp;&lt;a href="#2025-01-31-the-modern-real-programmer-footnote-1-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content></entry>
 <entry>
  <title type="text">Monochrome</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2024/05/20/monochrome/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2024-05-20-monochrome</id>
  <published>2024-05-20T08:58:05Z</published>
  <updated>2024-05-20T08:58:05Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;Or, why limitations matter.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;After we released Štar, my friend Zyni had a rather distressing and inconclusive exchange with someone on reddit. Apart from making me feel even better about walking away from reddit a decade and more ago, I realised an interesting thing when talking to her about her experience.&lt;/p&gt;

&lt;h2 id="limitations"&gt;Limitations&lt;/h2&gt;

&lt;p&gt;Here are some curious things that people do.&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Why, in 2024, would anyone use a digital camera which can only make monochrome pictures?&lt;/li&gt;
 &lt;li&gt;Why, in 2024, would anyone use a film camera?&lt;/li&gt;
 &lt;li&gt;Why, in 2024, would anyone record music in a studio which uses tape?&lt;/li&gt;
 &lt;li&gt;Why, in 2024, would any guitarist use a collection of flaky old FX pedals connected by noisy and unreliable cables, and a valve amplifier which occasionally catches fire&lt;sup&gt;&lt;a href="#2024-05-20-monochrome-footnote-1-definition" name="2024-05-20-monochrome-footnote-1-return"&gt;1&lt;/a&gt;&lt;/sup&gt;?&lt;/li&gt;
 &lt;li&gt;Why, in 2024, would anyone shoot a movie on film?&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Yet people do all these things: there are at least two manufacturers of dedicated monochrome cameras, and you can pay to have your colour digital camera converted to monochrome by removing the filter array; many people use film; studios which use tape still exist and probably are becoming more common; too many guitarists to count use elderly FX pedals, a nest of cables and a valve amplifier; many very famous recent movies have been made on film.&lt;/p&gt;

&lt;p&gt;There is, of course, a lot of myth and lore about the special magic properties of these things: people go on endlessly about how monochrome digital sensors have more effective resolution than Bayer sensors, as if anyone needs more resolution today, or how the effective sensitivity is higher, as if anyone needs more sensitivity today. The same for film (no, it&amp;rsquo;s not magic, no, it&amp;rsquo;s not somehow better than digital in any objective way), analogue recording, old FX pedals and amplifiers, and movies made on film. If you really think movies made on film are somehow better or &amp;lsquo;more natural&amp;rsquo;, watch &lt;em&gt;The Holdovers&lt;/em&gt;, which was shot digitally but is a really beautiful simulacrum of what movies looked like in about 1972.&lt;/p&gt;

&lt;p&gt;The awful truth is that none of these technologies get you anything objectively better, &lt;em&gt;even if what you want to do is reproduce what people did when those technologies were all there was&lt;/em&gt;. You can simulate film so well it is impossible to tell the difference, you can simulate analogue tape just as well. Modern digital FX/amplification systems for guitar are a wonder. You can produce really beautiful monochrome images from colour files.&lt;/p&gt;

&lt;p&gt;So why, really, do people do these things?&lt;/p&gt;

&lt;p&gt;The clue, for me, is in the first one: why would anyone use a dedicated monochrome digital camera? Why would I use one if I could afford to? The answer, for me and others, is &lt;em&gt;because it restricts what you can do&lt;/em&gt;. If your camera will only do monochrome, then &lt;em&gt;that&amp;rsquo;s all you can do&lt;/em&gt;, and somehow that matters. I can&amp;rsquo;t afford a monochrome-only digital camera, but I do use a digital camera which has a monochrome-only workflow (this is why I bought it, in fact): the camera sets a &amp;lsquo;monochrome&amp;rsquo; flag in its files which the raw-conversion tool understands, and unless you work hard you never see a colour version of the photographs you&amp;rsquo;ve taken. And this matters to me: it needs to be difficult to overcome the limitation, so I can think in monochrome&lt;sup&gt;&lt;a href="#2024-05-20-monochrome-footnote-2-definition" name="2024-05-20-monochrome-footnote-2-return"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;And of course I use film as well, and mostly black and white film with some recent excursions into colour reversal (slide) film. Partly I do this because I enjoy working in the darkroom and the tactile quality of film cameras from the 1980s and before, but more important, I think, is how limiting film is. Once you&amp;rsquo;ve taken a picture, it&amp;rsquo;s there: you can&amp;rsquo;t chimp and decide to do it again. You have 36 (or 10, or 1) exposures before you have to change film: every frame matters. Film can&amp;rsquo;t see in the dark. Mostly it can&amp;rsquo;t even see in colour (reversal film is now absurdly expensive). 35mm film is always going to have grain. Making photographs using film is a festival of limitations.&lt;/p&gt;

&lt;p&gt;It turns out that, for many people, &lt;em&gt;limitations matter&lt;/em&gt;. If you take them away, then suddenly you can do anything. So you spend your time fiddling with the parameters of what you &lt;em&gt;can&lt;/em&gt; do, and doing nothing as a result, rather than being forced to pull your finger out and do &lt;em&gt;something&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s why many people make photographs with monochrome cameras, or on film. That&amp;rsquo;s why people still make movies on film. That&amp;rsquo;s why people paint or draw, rather than using some vast digital image-creation system. That&amp;rsquo;s why people write books on typewriters, or with a pen. That&amp;rsquo;s why Colin Chapman designed cars the way he did, and why more than 160 companies have made (and still do make) replicas of one of his designs.&lt;/p&gt;

&lt;p&gt;Not everyone: not even most people. But some people. Enough people.&lt;/p&gt;

&lt;p&gt;And it&amp;rsquo;s not enough to simply say &amp;lsquo;I won&amp;rsquo;t use all the features I do not want&amp;rsquo;: those features need &lt;em&gt;not to be there&lt;/em&gt;. Using a camera which can only make monochrome images is &lt;em&gt;not like&lt;/em&gt; using a camera which can make colour images but choosing not to. Choosing not to chimp is &lt;em&gt;not like&lt;/em&gt; being unable to chimp. Using a film camera is &lt;em&gt;not like&lt;/em&gt; using a digital camera and film simulation. Drawing with a pencil on paper is &lt;em&gt;not like&lt;/em&gt; using a drawing program but choosing only to use the pencil tool, however good that tool is. Limitations have to be, well, limitations. I don&amp;rsquo;t know why this is, but they do.&lt;/p&gt;

&lt;h2 id="štar"&gt;Štar&lt;/h2&gt;

&lt;p&gt;And that&amp;rsquo;s why Štar exists: because it&amp;rsquo;s limited, because it does &lt;em&gt;one thing&lt;/em&gt;. Because there is as little syntax as we could make there be. In Štar &lt;em&gt;everything&lt;/em&gt; is an iterator&lt;sup&gt;&lt;a href="#2024-05-20-monochrome-footnote-3-definition" name="2024-05-20-monochrome-footnote-3-return"&gt;3&lt;/a&gt;&lt;/sup&gt; so any expression like&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(for ((&amp;lt;var/s&amp;gt; &amp;lt;iterator&amp;gt;))
  ...)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;can be turned into&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(multiple-value-bind (v c) &amp;lt;iterator&amp;gt;
  (for ((&amp;lt;var/s&amp;gt; (values v c)))
    ...)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And it will mean exactly the same thing, although often it will be slower&lt;sup&gt;&lt;a href="#2024-05-20-monochrome-footnote-4-definition" name="2024-05-20-monochrome-footnote-4-return"&gt;4&lt;/a&gt;&lt;/sup&gt;. And &lt;em&gt;all&lt;/em&gt; clauses are like that. There is &lt;em&gt;only one case&lt;/em&gt;: the form on the right-hand side of a clause is a perfectly general expression evaluated, once, in the way you think it will be. There is no magic syntax, at all. And because Štar does only one thing &amp;mdash; iterate &amp;mdash; it &lt;em&gt;forces&lt;/em&gt; you to use other tools to do other things, and to make sure all these tools compose well with each other. There was once a famous operating system whose designers played the same trick.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dreamsongs.com/WorseIsBetter.html" title="Worse is better"&gt;Richard Gabriel&amp;rsquo;s famous essay&lt;/a&gt;, usually known as &lt;a href="https://www.dreamsongs.com/RiseOfWorseIsBetter.html" title="The rise of worse is better"&gt;&lt;em&gt;Worse is better&lt;/em&gt;&lt;/a&gt;, is celebrated for describing the difference between &lt;em&gt;right thing&lt;/em&gt; systems and &lt;em&gt;worse is better&lt;/em&gt; systems&lt;sup&gt;&lt;a href="#2024-05-20-monochrome-footnote-5-definition" name="2024-05-20-monochrome-footnote-5-return"&gt;5&lt;/a&gt;&lt;/sup&gt;. It is less celebrated for another distinction it made amongst the right thing systems. That distinction is between &lt;em&gt;big complex systems&lt;/em&gt; and &lt;em&gt;diamond-like jewel&lt;/em&gt; systems:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;The &lt;em&gt;big complex system&lt;/em&gt; scenario goes like this:&lt;/p&gt;
 &lt;p&gt;First, the right thing needs to be designed. Then its implementation needs to be designed. Finally it is implemented. Because it is the right thing, it has nearly 100% of desired functionality, and implementation simplicity was never a concern so it takes a long time to implement. It is large and complex. It requires complex tools to use properly. The last 20% takes 80% of the effort, and so the right thing takes a long time to get out, and it only runs satisfactorily on the most sophisticated hardware.&lt;/p&gt;
 &lt;p&gt;The &lt;em&gt;diamond-like jewel&lt;/em&gt; scenario goes like this:&lt;/p&gt;
 &lt;p&gt;The right thing takes forever to design, but it is quite small at every point along the way. To implement it to run fast is either impossible or beyond the capabilities of most implementors.&lt;/p&gt;
 &lt;p&gt;The two scenarios correspond to Common Lisp and Scheme.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Štar aspires to be the diamond-like jewel of iteration frameworks. Its interface is tiny: &lt;code&gt;org.tfeb.*&lt;/code&gt; exports six symbols, four of which could be removed with no loss of functionality&lt;sup&gt;&lt;a href="#2024-05-20-monochrome-footnote-6-definition" name="2024-05-20-monochrome-footnote-6-return"&gt;6&lt;/a&gt;&lt;/sup&gt;. But it aims to be general and to be able to turn this clean, minimal syntax into fast code: apart from the catalogue of built-in iterators, almost all the rest of the interface is to the tools that let you do this for your own iterators.&lt;/p&gt;

&lt;p&gt;It may seem odd that Štar is written in Common Lisp, not Scheme, but CL is what we actually use and so producing tools which turn CL into the system we&amp;rsquo;d like to have is what we care about. In my case, I also remember the movement to reexpress CL as a small core language combined with libraries.&lt;/p&gt;

&lt;p&gt;Štar is not for everybody. If you like &lt;code&gt;loop&lt;/code&gt; you probably will hate it (but you have no taste, so we don&amp;rsquo;t care). If you are an adherent of the big complex system school you probably won&amp;rsquo;t like it either (and we respect your opinion). That&amp;rsquo;s not who Štar is for: Štar is for the people who appreciate the diamond-like jewel, who believe that limitations matter, in a deep way.&lt;/p&gt;

&lt;p&gt;If that&amp;rsquo;s not for you, that is completely fine: not everybody is the same: not everyone wants a monochrome camera, and not everyone knew, or liked if they did know, that famous operating system&lt;sup&gt;&lt;a href="#2024-05-20-monochrome-footnote-7-definition" name="2024-05-20-monochrome-footnote-7-return"&gt;7&lt;/a&gt;&lt;/sup&gt;. Some people even like &lt;code&gt;loop&lt;/code&gt;, apparently. But understand that it &lt;em&gt;is&lt;/em&gt; for some people, and try to avoid sneering at them, if you can.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class="footnotes"&gt;
 &lt;ol&gt;
  &lt;li id="2024-05-20-monochrome-footnote-1-definition" class="footnote-definition"&gt;
   &lt;p&gt;Well-maintained valve amplifiers hardly ever catch fire. Often they are also electrically safe.&amp;nbsp;&lt;a href="#2024-05-20-monochrome-footnote-1-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2024-05-20-monochrome-footnote-2-definition" class="footnote-definition"&gt;
   &lt;p&gt;Why a photographer or a movie maker would &lt;em&gt;want&lt;/em&gt; to work in monochrome is another, related question: why, in 2024, intentionally throw away all the colour information in a scene?&amp;nbsp;&lt;a href="#2024-05-20-monochrome-footnote-2-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2024-05-20-monochrome-footnote-3-definition" class="footnote-definition"&gt;
   &lt;p&gt;In this way, Štar is like some Scheme compilers which turn everything into \(\lambda\) expressions and then try to make those expressions quick.&amp;nbsp;&lt;a href="#2024-05-20-monochrome-footnote-3-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2024-05-20-monochrome-footnote-4-definition" class="footnote-definition"&gt;
   &lt;p&gt;One of the things Štar&amp;rsquo;s tests do is exactly this transformation as a way of testing that iterator optimizers do not change the semantics of the program.&amp;nbsp;&lt;a href="#2024-05-20-monochrome-footnote-4-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2024-05-20-monochrome-footnote-5-definition" class="footnote-definition"&gt;
   &lt;p&gt;Entertainingly, that famous operating system is often disparaged as an example of worse is better. In terms of its implementation that may be justified: its ideas are certainly &lt;em&gt;not&lt;/em&gt; examples of worse is better.&amp;nbsp;&lt;a href="#2024-05-20-monochrome-footnote-5-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2024-05-20-monochrome-footnote-6-definition" class="footnote-definition"&gt;
   &lt;p&gt;We have argued, at length, about this. We decided that, just as Scheme includes &lt;code&gt;let&lt;/code&gt; and, even more extravagantly, &lt;code&gt;let*&lt;/code&gt;, Štar should include &lt;code&gt;final&lt;/code&gt;, &lt;code&gt;for*&lt;/code&gt; and &lt;code&gt;final*&lt;/code&gt;. In the language of the Scheme reports, they are library syntax (&lt;code&gt;for*&lt;/code&gt;) and library procedures (&lt;code&gt;final&lt;/code&gt;, &lt;code&gt;final*&lt;/code&gt;, &lt;code&gt;next*&lt;/code&gt; which serves no purpose without &lt;code&gt;for*&lt;/code&gt;).&amp;nbsp;&lt;a href="#2024-05-20-monochrome-footnote-6-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2024-05-20-monochrome-footnote-7-definition" class="footnote-definition"&gt;
   &lt;p&gt;There&amp;rsquo;s a book about that.&amp;nbsp;&lt;a href="#2024-05-20-monochrome-footnote-7-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content></entry>
 <entry>
  <title type="text">Štar: an iteration construct for Common Lisp</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2024/05/15/an-iteration-construct-for-common-lisp/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2024-05-15-an-iteration-construct-for-common-lisp</id>
  <published>2024-05-15T06:37:18Z</published>
  <updated>2024-05-15T06:37:18Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;Štar is a concise and extensible iteration construct for Common Lisp which aims to be pleasant to use, easy to understand, fast if needed, general, and not to look like Fortran.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;Common Lisp has multiple iteration constructs: mapping functions such as &lt;code&gt;mapcar&lt;/code&gt;, special-purpose constructs such as &lt;code&gt;dotimes&lt;/code&gt; and &lt;code&gt;dolist&lt;/code&gt;, the general but somewhat clumsy construct which is &lt;code&gt;do&lt;/code&gt; and &lt;code&gt;do*&lt;/code&gt;, and finally the extended &lt;code&gt;loop&lt;/code&gt; macro which aims to embed a &amp;lsquo;more friendly&amp;rsquo; iteration language into CL and succeeds in being so complex that it is often hard to know whether a given form is legal or not without poring over &lt;code&gt;loop&lt;/code&gt;&amp;rsquo;s grammar.&lt;/p&gt;

&lt;p&gt;None of these constructs manage to be all three of pleasant to use, easy to understand and general. &lt;code&gt;loop&lt;/code&gt; somehow fails to be any of these things in many cases. None are extensible&lt;sup&gt;&lt;a href="#2024-05-15-an-iteration-construct-for-common-lisp-footnote-1-definition" name="2024-05-15-an-iteration-construct-for-common-lisp-footnote-1-return"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;But Common Lisp is a Lisp, and Lisp&amp;rsquo;s huge advantage is that it is a programming language in which it is easy to write programming languages, or parts of them, like iteration constructs. That is, after all, how most or all of the existing constructs started life.&lt;/p&gt;

&lt;p&gt;Lots of these have been written, of course. Štar tries to distinguish itself by being as simple as possible: it has as little special syntax as I could work out how to give it – there is no special little language you need to learn. It also has no inherent knowledge about how to iterate over any particular structure: it doesn&amp;rsquo;t know how to iterate over lists, or ranges of numbers. Rather it knows that iterating has to answer two questions:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;is there more?&lt;/li&gt;
 &lt;li&gt;what is the next thing?&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;In addition it knows how to ask another question:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;is there any information I can use to make asking the first two questions faster?&lt;/li&gt;&lt;/ul&gt;

&lt;h2 id="what-it-looks-like"&gt;What it looks like&lt;/h2&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(for ((e (in-list l)))
  (print e))

(for (((k v) (in-hash-table h)))
  ...)

(for* ((entry (in-list entries))
       (element (in-list entry)))
  ...)

(defun in-alist (alist)
  (values
    (lambda () (not (null alist)))
    (lambda ()
      (destructuring-bind ((k . v) . more) alist
        (setf alist more)
        (values k v)))))

(for (((k v) (in-alist ...)))
  ...)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These are some simple examples: the last shows how easy it is to teach Štar to iterate over new things, or over existing things in new ways. Not shown here is that it&amp;rsquo;s also pretty easy to teach it how to optimize new iterators and to make various declarations about things.&lt;/p&gt;

&lt;h2 id="what-štar-is-not"&gt;What Štar is not&lt;/h2&gt;

&lt;p&gt;Štar is an &lt;em&gt;iteration construct&lt;/em&gt;: what it does is to iterate. It has nothing to do with collecting values. For Štar, iteration and value accumulation are orthogonal problems which should be solved by orthogonal constructs. In particular if you wanted to make a list of the even numbers from a list, you might to this by using Štar together with a value-collection macro:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(collecting
  (for ((e (in-list ...)))
    (when (evenp e)
      (collect e))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is yet another way in which Štar differs from &lt;code&gt;loop&lt;/code&gt; and many other constructs. In particular Štar&amp;rsquo;s point of view is that mixing together iteration and value accumulation results in a system that is not very good at either.&lt;/p&gt;

&lt;p&gt;Similarly, Štar doesn&amp;rsquo;t contain a mass of syntax letting you select only certain values, or allowing you to terminate iteration early: you don&amp;rsquo;t write&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(loop for x in l while (numberp x) do ...)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Instead you write&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(for ((x (in-list l)))
  (unless (numberp x) (final))
  ...)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The body of an iteration is exactly like the body of &lt;code&gt;defun&lt;/code&gt;, except there are some local functions which you can call to skip to the next iteration or finish the iteration.&lt;/p&gt;

&lt;p&gt;Štar, of course, doesn&amp;rsquo;t bundle some destructuring system which will inevitably be subtly incompatible with other destructuring systems while also not being usable independently. If you want destructuring, use a full-fat system of your choice.&lt;/p&gt;

&lt;p&gt;You probably get the idea: Štar is a tool whose job is to iterate: not some leaking bag of broken abstractions.&lt;/p&gt;

&lt;h2 id="multiple-values"&gt;Multiple values&lt;/h2&gt;

&lt;p&gt;One thing that Štar &lt;em&gt;does&lt;/em&gt; do is to take multiple values seriously. A clause which specifies a list of variables will bind them to the multiple values returned by the iterator. Multiple values, unlike destructuring, are something you really have to have in the iteration construct itself.&lt;/p&gt;

&lt;h2 id="the-thing-that-doesnt-really-matter-but-everyone-cares-about"&gt;The thing that doesn&amp;rsquo;t really matter but everyone cares about&lt;/h2&gt;

&lt;p&gt;So, OK, Štar is an extensible, general, iteration construct. Obviously it will have traded performance for all this. I mean, it&amp;rsquo;s the old Lisp story, &lt;a href="https://www.dreamsongs.com/WorseIsBetter.html" title="Worse is better"&gt;the one Gabriel told us&lt;/a&gt; long ago. Right?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;* Running benchmarks
** lists of length 2000, nesting 3
what                                                  seconds      ratio
star                                                   30.312      1.000
loop                                                   30.071      0.992
dolist                                                 21.594      0.712
** range 100000, nesting 2
what                                                  seconds      ratio
star/with-step                                          9.414      1.000
star/no-step                                            9.406      0.999
loop                                                   18.412      1.956
dotimes                                                 9.469      1.006&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="a-sketch-of-štar"&gt;A sketch of Štar&lt;/h2&gt;

&lt;p&gt;Štar has three parts, four if you count the iterators:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;the iteration constructs themselves and bindings they make;&lt;/li&gt;
 &lt;li&gt;a protocol for defining new iterators;&lt;/li&gt;
 &lt;li&gt;a protocol for defining optimizers for iterators;&lt;/li&gt;
 &lt;li&gt;a collection of predefined iterators and optimizers for them.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;The first three parts are much more finished than the fourth: most of the existing iterators were written as proofs of concept and may well change, get better, or go away.&lt;/p&gt;

&lt;h3 id="iterators"&gt;Iterators&lt;/h3&gt;

&lt;p&gt;These are forms (usually, named function calls) which return two values, both functions of no arguments:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;the first value is called and should return true if there is more to do;&lt;/li&gt;
 &lt;li&gt;the second value is called to return the next value or values of the iterator.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;These functions answer the first two questions Štar needs to ask: is there more, and if there is, what is it? These two functions obviously share state in general.&lt;/p&gt;

&lt;p&gt;To answer the third question – how do I make things faster? – named iterator functions can have &lt;em&gt;optimizers&lt;/em&gt;: these are functions called by Štar at macroexpansion time which tell it how to make things faster. It&amp;rsquo;s up to an optimizer to ensure the semantics are the same for the optimized and unoptimized versions. Optimizers can specify a set of bindings to make, declarations for them, how to iterate, and some other things.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s possible to install and remove optimizers, and to dynamically bind sets of them. This might be useful, for instance, to compile a file where some particular assumptions (&amp;lsquo;all vectors are vectors of floats&amp;rsquo;) are true.&lt;/p&gt;

&lt;h3 id="iteration-constructs"&gt;Iteration constructs&lt;/h3&gt;

&lt;p&gt;There are two:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;code&gt;for&lt;/code&gt; iterates in parallel;&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;for*&lt;/code&gt; defines nested loops: &lt;code&gt;(for* ((...) (...)) ...)&lt;/code&gt; is like &lt;code&gt;(for ((...)) (for ((...)) ...))&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Note that because of the way iterators work, sequential binding within one loop makes no sense.&lt;/p&gt;

&lt;p&gt;The first argument of &lt;code&gt;for&lt;/code&gt; or &lt;code&gt;for*&lt;/code&gt; specifies a number of clauses: each clause is of the form &lt;code&gt;&amp;lt;var/s&amp;gt; &amp;lt;iterator&amp;gt;)&lt;/code&gt;. Multiple values are supported, and it is possible to make various declarations about variables: this matters for &lt;code&gt;for*&lt;/code&gt;, where there is no room for declarations for other than the last (innermost) clause. Variables whose name is &lt;code&gt;"_"&lt;/code&gt; are ignored by default.&lt;/p&gt;

&lt;p&gt;Within the body of an iteration there are four local functions:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;code&gt;next&lt;/code&gt; skips to the next iteration;&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;next*&lt;/code&gt; skips to the next outer-level iteration for &lt;code&gt;for*&lt;/code&gt; and is the same as &lt;code&gt;next&lt;/code&gt; for &lt;code&gt;for&lt;/code&gt;;&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;final&lt;/code&gt; returns zero or more values from the current iteration&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;final*&lt;/code&gt; returns zero or more values for the outer-level iteration for &lt;code&gt;for*&lt;/code&gt; and is the same as &lt;code&gt;final&lt;/code&gt; for &lt;code&gt;for&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;

&lt;h3 id="provided-iterators"&gt;Provided iterators&lt;/h3&gt;

&lt;p&gt;There are iterators which work for lists, vectors, general sequences, hash tables, ranges of reals, as well as some more interesting ones. Not all iterators currently have optimizers. You only need to care about writing optimizers if you need to make iterators very fast: they can be significantly fiddly to write.&lt;/p&gt;

&lt;p&gt;The iterator over ranges of reals has an optimizer which tries hard to make things pretty fast.&lt;/p&gt;

&lt;p&gt;As well as this there are some more interesting iterators. An example is &lt;code&gt;sequentially&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(for ((a (sequentially 1 2)))
  ...)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;will bind &lt;code&gt;a&lt;/code&gt; sequentually to &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;2&lt;/code&gt;. But this iterator is a macro which has the behaviour of a FEXPR, so it evaluates its arguments only when needed (and as many times as needed). A variant of &lt;code&gt;sequentially&lt;/code&gt; is &lt;code&gt;sequentially*&lt;/code&gt; which &amp;lsquo;sticks&amp;rsquo; on its last argument. So for instance:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (let ((v 0))
    (for ((a (sequentially* (incf v)))
          (_ (in-range 3)))
      (print a)))

1 
2 
3 &lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Another way to write this is:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (for ((a (let ((v 0)) (sequentially* (incf v))))
        (_ (in-range 4)))
    (print a))

1 
2 
3 
4 &lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And of course there is a meta-iterator (also implemented as a macro), &lt;code&gt;in-iterators&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (for ((a (in-iterators
            (in-list '(1 2))
            (in-list '(3 4)))))
    (print a))

1 
2 
3 
4 &lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;rsquo;s possible to construct very general iterators with tools like this.&lt;/p&gt;

&lt;p&gt;As I said above, Štar&amp;rsquo;s current iterators are in a fairly rough state: a lot of this might change.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id="notes"&gt;Notes&lt;/h2&gt;

&lt;h3 id="declarations"&gt;Declarations&lt;/h3&gt;

&lt;p&gt;A form like&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(for* ((a (in-range 10))
       (b (in-range 10)))
  ...)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;corresponds roughly to&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(for ((a (in-range 10)))
  (for ((b (in-range 10)))
    ...)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The problem is now how to make declarations which apply to &lt;code&gt;a&lt;/code&gt;. This is hard because CL doesn&amp;rsquo;t provide the tools you need to know whether a declaration refers to a variable or not: to know whether &lt;code&gt;(declare (foo a))&lt;/code&gt; refers to &lt;code&gt;a&lt;/code&gt; or not you need to know, at least, whether &lt;code&gt;foo&lt;/code&gt; names a type, which you can&amp;rsquo;t do. You often can guess, but not always.&lt;/p&gt;

&lt;p&gt;So, rather than trying to solve an intractable problem, Štar lets you specify some properties of a variable in the clause that binds it: you can say&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(for* (((a :type fixnum) (in-range 10))
       (b (in-range 10)))
  ...)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;for instance. This is a bit ugly, but it solves the problem. It is only useful for &lt;code&gt;for*&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id="binding"&gt;Binding&lt;/h3&gt;

&lt;p&gt;Štar binds, rather than assigns:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(collecting
  (for ((a (in-list 1 2)))
    (collect
      (lambda (&amp;amp;optional (v vp))
        (if vp (setf a v) a)))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;will return two closures over independent bindings.&lt;/p&gt;

&lt;h2 id="epilogue"&gt;Epilogue&lt;/h2&gt;

&lt;p&gt;Štar&amp;rsquo;s source code is &lt;a href="https://github.com/tfeb/star"&gt;here&lt;/a&gt;. The manual is included with the source code but also &lt;a href="https://tfeb.github.io/star/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Štar is pronounced roughly &amp;lsquo;shtar&amp;rsquo;.&lt;/p&gt;

&lt;p&gt;Much of the inspiration for Štar came from my friend Zyni: thanks to her for the inspiration behind it, actually making me write it and for many other things.&lt;/p&gt;

&lt;p&gt;Štar is dedicated to her, and to Ian Anderson.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class="footnotes"&gt;
 &lt;ol&gt;
  &lt;li id="2024-05-15-an-iteration-construct-for-common-lisp-footnote-1-definition" class="footnote-definition"&gt;
   &lt;p&gt;Some implementations have mechanisms for extending &lt;code&gt;loop&lt;/code&gt;.&amp;nbsp;&lt;a href="#2024-05-15-an-iteration-construct-for-common-lisp-footnote-1-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content></entry>
 <entry>
  <title type="text">Symbol nicknames: a broken toy</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2023/10/12/symbol-nicknames-a-broken-toy/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2023-10-12-symbol-nicknames-a-broken-toy</id>
  <published>2023-10-12T14:08:27Z</published>
  <updated>2023-10-12T14:08:27Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;&lt;a href="https://github.com/tfeb/symbol-nicknames"&gt;Symbol nicknames&lt;/a&gt; allows multiple names to refer to the same symbol in supported implementations of Common Lisp. That may or may not be useful.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;People often say the Common Lisp package system is deficient. But a lot of the same people write code which is absolutely full of explicit package prefixes in what I can only suppose is an attempt to make programs harder to read. Somehow this is meant to be made better by using package-local nicknames for packages. And let&amp;rsquo;s not mention the unspeakable idiocy that is thinking that a package name like, say, &lt;code&gt;XML&lt;/code&gt; is suitable for any kind of general use at all. So forgive me if I don&amp;rsquo;t take their concerns too seriously.&lt;/p&gt;

&lt;p&gt;The CL package system can&amp;rsquo;t do all the things something like the Racket module system can do. But it&amp;rsquo;s not clear that, given its job of collecting symbols into, well, packages, it could do that much more than it currently does. Probably some kind of &amp;lsquo;package universe&amp;rsquo; notion such as Symbolics Genera had would be useful. But the namespace has to be anchored &lt;em&gt;somewhere&lt;/em&gt;, and if you&amp;rsquo;re willing to give packages domain-structured names in the obvious way &lt;em&gt;and&lt;/em&gt; spend time actually constructing a namespace for the language you want to use, it&amp;rsquo;s perfectly pleasant in my experience.&lt;/p&gt;

&lt;p&gt;One thing that &lt;em&gt;might&lt;/em&gt; be useful is to allow multiple names to refer to the same symbol. So for instance you might want to have &lt;code&gt;eq?&lt;/code&gt; be the same symbol as &lt;code&gt;eq&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (setf (nickname-symbol "EQ?") 'eq)
eq

&amp;gt; (eq 'eq? 'eq)
t

&amp;gt; (eq? 'eq 'eq?)
t&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This allows you to construct languages which have different names for things, but where the names are translated to the underlying name efficiently. As another example, let&amp;rsquo;s say you wanted to call &lt;code&gt;eql&lt;/code&gt; &lt;code&gt;equivalent-p&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (setf (nickname-symbol "EQUIVALENT-P") 'eql)
eql

&amp;gt; (eql 'eql 'equivalent-p)
t&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, now you can use &lt;code&gt;equivalent-p&lt;/code&gt; as a synonym for &lt;code&gt;eql&lt;/code&gt; &lt;em&gt;wherever&lt;/em&gt; it occurs:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (defmethod foo ((x (equivalent-p 1)))
    "x is 1")
#&amp;lt;standard-method foo nil ((eql 1)) 801005BD23&amp;gt;

&amp;gt; (foo 1)
"x is 1"&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Symbol nicknames is not completely portable as it requires hooking string-to-symbol lookup. It is supported in LispWorks and SBCL currently: it will load in other Lisps but will complain that it can&amp;rsquo;t infect them.&lt;/p&gt;

&lt;p&gt;Symbol nicknames is also not completely compatible with CL. In CL you can assume that &lt;code&gt;(find-symbol "FOO")&lt;/code&gt; either returns a symbol whose name is &lt;code&gt;"FOO"&lt;/code&gt; or &lt;code&gt;nil&lt;/code&gt; and &lt;code&gt;nil&lt;/code&gt;: with symbol nicknames you can&amp;rsquo;t. In the case where a nickname link has been followed the second value of &lt;code&gt;find-symbol&lt;/code&gt; will be &lt;code&gt;:nickname&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Symbol nicknames is a toy. I am not convinced that the idea is even useful, and if it is it probably needs to be thought about more than I have.&lt;/p&gt;

&lt;p&gt;But it exists.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Measuring some tree-traversing functions</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2023/03/26/measuring-some-tree-traversing-functions/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2023-03-26-measuring-some-tree-traversing-functions</id>
  <published>2023-03-26T09:25:50Z</published>
  <updated>2023-03-26T09:25:50Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;In a &lt;a href="https://www.tfeb.org/fragments/2023/03/13/variations-on-a-theme/" title="Variations on a theme"&gt;previous article&lt;/a&gt; my friend Zyni wrote some variations on a list-flattening function, some of which were &amp;lsquo;recursive&amp;rsquo; and some of which &amp;lsquo;iterative&amp;rsquo;, managing the stack explicitly. We thought it would be interesting to see what the performance differences were, both for this function and a more useful variant which searches a tree rather than flattening it.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h2 id="what-we-measured"&gt;What we measured&lt;/h2&gt;

&lt;p&gt;The code we used is &lt;a href="https://github.com/tfeb/zyni-flatten" title="sample code"&gt;here&lt;/a&gt;&lt;sup&gt;&lt;a href="#2023-03-26-measuring-some-tree-traversing-functions-footnote-1-definition" name="2023-03-26-measuring-some-tree-traversing-functions-footnote-1-return"&gt;1&lt;/a&gt;&lt;/sup&gt;. We measured four variations of each of two functions.&lt;/p&gt;

&lt;h3 id="list-flattening"&gt;List flattening&lt;/h3&gt;

&lt;p&gt;All these functions use &lt;a href="https://tfeb.github.io/tfeb-lisp-hax/#collecting-lists-forwards-and-accumulating-collecting" title="collecting"&gt;&lt;code&gt;collecting&lt;/code&gt;&lt;/a&gt; to build their results forwards. They live in &lt;a href="https://github.com/tfeb/zyni-flatten/blob/main/flatten-variants.lisp" title="flatten-variants.lisp"&gt;&lt;code&gt;flatten-variants.lisp&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;code&gt;flatten/implicit-stack&lt;/code&gt; works in the obvious recursive way, with an implicit stack. This uses &lt;a href="https://tfeb.github.io/tfeb-lisp-hax/#applicative-iteration-iterate" title="iterate"&gt;&lt;code&gt;iterate&lt;/code&gt;&lt;/a&gt; to express the local recursive function.&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;flatten/explicit-stack&lt;/code&gt; uses an explicit stack (called &lt;code&gt;agenda&lt;/code&gt; in the code) represented as a vector, and uses &lt;a href="https://tfeb.github.io/tfeb-lisp-hax/#decomposing-iteration-simple-loops" title="looping"&gt;&lt;code&gt;looping&lt;/code&gt;&lt;/a&gt; to express iteration.&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;flatten/explicit-stack/adja&lt;/code&gt; is like the previous function but it is willing to extend the explicit stack, which it does by using &lt;code&gt;adjust-array&lt;/code&gt; and assignment.&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;flatten/explicit-stack/adjb&lt;/code&gt; is like &lt;code&gt;flatten/explicit-stack/adja&lt;/code&gt; but uses a local tail-recursive function to &lt;em&gt;bind&lt;/em&gt; the extended stack rather than assignment.&lt;/li&gt;
 &lt;li&gt;Finally &lt;code&gt;flatten/consy-stack&lt;/code&gt; is very close to Zyni&amp;rsquo;s original iterative solution: it represents the stack as a list. This version necessarily conses fairly copiously.&lt;/li&gt;&lt;/ul&gt;

&lt;h3 id="searching-cons-trees"&gt;Searching cons trees&lt;/h3&gt;

&lt;p&gt;These functions, in &lt;a href="https://github.com/tfeb/zyni-flatten/blob/main/treesearch-variants.lisp" title="treesearch-variants.lisp"&gt;&lt;code&gt;treesearch-variants.lisp&lt;/code&gt;&lt;/a&gt;, correspond to the flattening variants, except they are searching for some atomic value in the tree of conses:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;code&gt;search/implicit-stack&lt;/code&gt; uses an implicit stack;&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;search/explicit-stack&lt;/code&gt; uses a vector;&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;search/explicit-stack/adja&lt;/code&gt; uses a vector and adjusts by assignment;&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;search/explicit-stack/adjb&lt;/code&gt; uses a vector and adjusts by binding;&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;search/consy-stack&lt;/code&gt; uses a consy stack.&lt;/li&gt;&lt;/ul&gt;

&lt;h3 id="notes-on-the-code"&gt;Notes on the code&lt;/h3&gt;

&lt;p&gt;The functions all have &lt;code&gt;(declare (optimize (speed 3)))&lt;/code&gt; but specifically &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; turn off safety or use implementation-specific settings: we wanted to test code we felt we&amp;rsquo;d be happy running, and that means code compiled with reasonable settings for safety: if you turn safety off you&amp;rsquo;re brave, foolish, or both.&lt;/p&gt;

&lt;p&gt;We did not compare &lt;code&gt;looping&lt;/code&gt; with &lt;code&gt;do&lt;/code&gt; or &lt;code&gt;loop&lt;/code&gt;: we probably should. However the expansion of &lt;code&gt;looping&lt;/code&gt; is pretty straightforward:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(looping ((this o) (depth 0))
  (declare ...)
  ...)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Turns into&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(let ((this o) (depth 0))
  (declare ...)
  (block nil
    (tagbody
      #:start
      (multiple-value-setq (this depth) ...)
      (go #:start))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The only real question here, we think is whether &lt;code&gt;multiple-value-setq&lt;/code&gt; is compiled well: brief inspection implies it is. We should probably still compare the current version with more &amp;lsquo;native CL&amp;rsquo; variants.&lt;/p&gt;

&lt;p&gt;The variants which use a vector as a stack maintain the current element themselves: that&amp;rsquo;s because we tested using a fill pointer and &lt;code&gt;vector-push&lt;/code&gt; / &lt;code&gt;vector-pop&lt;/code&gt; and it was really significantly slower in both implementations.&lt;/p&gt;

&lt;h2 id="what-we-did"&gt;What we did&lt;/h2&gt;

&lt;h3 id="the-lisp-implementations-we-used"&gt;The Lisp implementations we used&lt;/h3&gt;

&lt;p&gt;We used LispWorks 8.0 and very recent SBCL builds, compiled from the &lt;code&gt;master&lt;/code&gt; branch no more than a few days before we ran the tests in mid March 2023.&lt;/p&gt;

&lt;p&gt;In the case of SBCL we paid attention to notes and warnings during compilation. The significant one we did &lt;em&gt;not&lt;/em&gt; address was that it complained vociferously about not being able to optimize calls to &lt;code&gt;eql&lt;/code&gt;: that&amp;rsquo;s because we don&amp;rsquo;t know the type of the thing we are searching for: it &lt;em&gt;needs&lt;/em&gt; to do the work it is trying to avoid. Apart from this the only warnings were about the computation of the new length of the agenda, which never actually happens in the tests we ran.&lt;/p&gt;

&lt;h3 id="the-machines-we-benchmarked-on"&gt;The machines we benchmarked on&lt;/h3&gt;

&lt;p&gt;We both have M1-based Macbook Airs so this is what we used. In particular we have not run any benchmarks on x64.&lt;/p&gt;

&lt;h3 id="what-we-ran"&gt;What we ran&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;make-car-cdr&lt;/code&gt;, in &lt;a href="https://github.com/tfeb/zyni-flatten/blob/main/common.lisp" title="common.lisp"&gt;&lt;code&gt;common.lisp&lt;/code&gt;&lt;/a&gt;, makes a list where each element is a chain linked by cars, finally terminating in a specified element. Controlling the length of the list and the depth of the chains gives the functions more iterative or more recursive work to do respectively. The benchmarking code then made a series of suitable structures of increasing size and timed many iterations of each function on the same structure, computing the time per call. We then wrote a program in Racket to plot the results on axes of &amp;lsquo;breadth&amp;rsquo; (length of the list) and &amp;lsquo;depth&amp;rsquo; (depth of the car-linked chain). For the search functions the element being searched for was not in the tree so they had to do as much work as possible.&lt;/p&gt;

&lt;p&gt;Life was usually arranged so that the initial agenda was big enough for the functions which used a vector as the agenda, so none of that aspect of them was teated, except for one case below. Apart from that case, the &amp;lsquo;vector stack&amp;rsquo; timings refer to &lt;code&gt;flatten/explicit-stack&lt;/code&gt; and &lt;code&gt;treesearch/explicit-stack&lt;/code&gt;, not the adjustable-stack variants.&lt;/p&gt;

&lt;h2 id="some-results"&gt;Some results&lt;/h2&gt;

&lt;p&gt;We timed 1,000 iterations of each call, for list lengths (breadth in the plots and below) from 30 to 1,000 in steps of 10 and depths (depth in the plots and below) from 10 to 300 in steps of 10, computing times in μs per iteration. Neither of us knows anything about how data like this should be best presented but simply plotting the performance surfaces seemed reasonable. We used bilinear interpolation to make the surface from the points&lt;sup&gt;&lt;a href="#2023-03-26-measuring-some-tree-traversing-functions-footnote-2-definition" name="2023-03-26-measuring-some-tree-traversing-functions-footnote-2-return"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h3 id="lispworks"&gt;LispWorks&lt;/h3&gt;

&lt;div class="figure"&gt;&lt;img src="/fragments/img/2023/zyni-flatten/lw-treesearch-implicit-vector.svg" alt="Treesearch: implicit compared with vector stack" /&gt;
 &lt;p class="caption"&gt;Treesearch: implicit compared with vector stack&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;This is nicely linear in both breadth and depth, and so quadratic in breadth \(\times\) depth. And it&amp;rsquo;s easy to see that for LW using the implicit stack is faster than the manually-managed stack.&lt;/p&gt;

&lt;div class="figure"&gt;&lt;img src="/fragments/img/2023/zyni-flatten/lw-treesearch-vector-consy.svg" alt="Treesearch: vector stack compared with consy stack" /&gt;
 &lt;p class="caption"&gt;Treesearch: vector stack compared with consy stack&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;This compares the vector stack with the consy stack, for treesearch. The consy stack is slightly faster which surprised us. This conses a list as long as the depth of the tree for each &amp;lsquo;leftward&amp;rsquo; branch, and then immediately unwinds that and throws the whole list away. So it creates significant garbage, but the allocation and garbage collection overhead together is still faster than using a vector. Consing really is (almost) free.&lt;/p&gt;

&lt;div class="figure"&gt;&lt;img src="/fragments/img/2023/zyni-flatten/lw-treesearch-flatten.svg" alt="Treesearch compared with flatten, both with implicit stacks" /&gt;
 &lt;p class="caption"&gt;Treesearch compared with flatten, both with implicit stacks&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;Here is more evidence that consing is very cheap: the difference between treesearch (which does not cons) and flatten (which does) is tiny.&lt;/p&gt;

&lt;h3 id="sbcl"&gt;SBCL&lt;/h3&gt;

&lt;div class="figure"&gt;&lt;img src="/fragments/img/2023/zyni-flatten/sbcl-treesearch-implicit-vector.svg" alt="Treesearch: implicit compared with vector stack" /&gt;
 &lt;p class="caption"&gt;Treesearch: implicit compared with vector stack&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;So here is SBCL. For SBCL explicitly managing the stack as a vector is significantly faster than the implicit stack. Something that is also apparent here is how variable SBCL&amp;rsquo;s timings are compared with LW&amp;rsquo;s: we don&amp;rsquo;t know why that is although we suspect it might be because SBCL&amp;rsquo;s garbage collector is more intrusive than LW&amp;rsquo;s. We also don&amp;rsquo;t know whether this variation is repeatable, or whether it&amp;rsquo;s due to a single very slow run or something like that.&lt;/p&gt;

&lt;div class="figure"&gt;&lt;img src="/fragments/img/2023/zyni-flatten/sbcl-treesearch-vector-consy.svg" alt="Treesearch: vector stack compared with consy stack" /&gt;
 &lt;p class="caption"&gt;Treesearch: vector stack compared with consy stack&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;For SBCL the consy stack is significantly slower than the vector stack, so for SBCL the vector stack is the fastest.&lt;/p&gt;

&lt;div class="figure"&gt;&lt;img src="/fragments/img/2023/zyni-flatten/sbcl-treesearch-flatten.svg" alt="Treesearch compared with flatten, both with implicit stacks" /&gt;
 &lt;p class="caption"&gt;Treesearch compared with flatten, both with implicit stacks&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;SBCL has a slightly larger difference between treesearch and flatten, with flatten being slower. There are also curious &amp;lsquo;waves&amp;rsquo; in the plot as depth increases.&lt;/p&gt;

&lt;h3 id="lispworks-compared-with-sbcl"&gt;LispWorks compared with SBCL&lt;/h3&gt;

&lt;div class="figure"&gt;&lt;img src="/fragments/img/2023/zyni-flatten/lw-sbcl-treesearch-implicit.svg" alt="Treesearch: SBCL compared with Lispworks, implicit stacks" /&gt;
 &lt;p class="caption"&gt;Treesearch: SBCL compared with Lispworks, implicit stacks&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;LW is significantly faster than SBCL for implicit stacks except for very small depths.&lt;/p&gt;

&lt;div class="figure"&gt;&lt;img src="/fragments/img/2023/zyni-flatten/lw-sbcl-treesearch-best.svg" alt="Treesearch: SBCL compared with Lispworks, best stacks" /&gt;
 &lt;p class="caption"&gt;Treesearch: SBCL compared with Lispworks, best stacks&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;This compares LW using an implicit stack with SBCL using an explicit vector stack. The difference is pretty small now.&lt;/p&gt;

&lt;div class="figure"&gt;&lt;img src="/fragments/img/2023/zyni-flatten/lw-sbcl-flatten-consy.svg" alt="Flatten: SBCL compared with Lispworks, consy stacks" /&gt;
 &lt;p class="caption"&gt;Flatten: SBCL compared with Lispworks, consy stacks&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;This was meant to be the worst-case for both: flattening and a consy stack. But it&amp;rsquo;s not particularly informative, I think.&lt;/p&gt;

&lt;h3 id="the-outer-reaches-lispworks-with-a-deep-tree"&gt;The outer reaches: LispWorks with a deep tree&lt;/h3&gt;

&lt;p&gt;We did one run with the maximum depth set to 10,000 with a step of 500, and maximum breadth set to 1,000 with a step of 100, averaged over 100 iterations instead of 1,000. This is too deep for LW&amp;rsquo;s stack, but LW allows stack extension, and we wrote what later became &lt;a href="https://github.com/tfeb/tfeb-lisp-implementation-hax/blob/main/lw/modules/allowing-stack-extensions.lisp"&gt;this&lt;/a&gt; to extend the stack as required. Note that this happens only during the first recursion into the left-hand branch of the tree so has minimal effect on performance. This also used &lt;code&gt;search/explicit-stack/adjb&lt;/code&gt; for the vector stack.&lt;/p&gt;

&lt;div class="figure"&gt;&lt;img src="/fragments/img/2023/zyni-flatten/lw-treesearch-implicit-vector-deep.svg" alt="Treesearch: implicit compared with consy stack, deep tree" /&gt;
 &lt;p class="caption"&gt;Treesearch: implicit compared with consy stack, deep tree&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;As before the implicit stack is much better for LW. This is much more bumpy than LW was for smaller depths, this might have been because the machine did other things while it was running but we don&amp;rsquo;t think so.&lt;/p&gt;

&lt;h2 id="some-conclusions"&gt;Some conclusions&lt;/h2&gt;

&lt;p&gt;None of the differences were really large. In particular there&amp;rsquo;s no enormous advantage from managing the stack yourself.&lt;/p&gt;

&lt;p&gt;Consing and the resulting garbage-collection does really seem to be very cheap, especially in LispWorks: the days of long GC pauses are long gone.&lt;/p&gt;

&lt;p&gt;We were surprised that LispWorks was fairly reliably faster than SBCL: surprised enough that we ran everything several times to be sure. It&amp;rsquo;s also interesting how much smoother LW&amp;rsquo;s performance surface is in most cases.&lt;/p&gt;

&lt;p&gt;It is possible that our implementations just suck, of course.&lt;/p&gt;

&lt;p&gt;Mostly it&amp;rsquo;s just some pretty pictures.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class="footnotes"&gt;
 &lt;ol&gt;
  &lt;li id="2023-03-26-measuring-some-tree-traversing-functions-footnote-1-definition" class="footnote-definition"&gt;
   &lt;p&gt;All of the functions should be portable CL. Some of the mechanism for expressing dependencies and loading things is not. However it should be easy for anyone to run this if they wish to.&amp;nbsp;&lt;a href="#2023-03-26-measuring-some-tree-traversing-functions-footnote-1-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2023-03-26-measuring-some-tree-traversing-functions-footnote-2-definition" class="footnote-definition"&gt;
   &lt;p&gt;Getting the bilinear interpolation right took longer than anything else, and perhaps longer than everything else put together.&amp;nbsp;&lt;a href="#2023-03-26-measuring-some-tree-traversing-functions-footnote-2-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content></entry>
 <entry>
  <title type="text">The absurdity of stacks</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2023/03/25/the-absurdity-of-stacks/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2023-03-25-the-absurdity-of-stacks</id>
  <published>2023-03-25T10:57:19Z</published>
  <updated>2023-03-25T10:57:19Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;Very often people regard the stack as a scarce, expensive resource, while the heap is plentiful and very cheap. This is absurd: the stack is memory, the heap is also memory. Deforming programs so they are &amp;lsquo;iterative&amp;rsquo; in order that they do not run out of the stack we imagine to be so costly is ridiculous: if you have a program which is inherently recursive, let it be recursive.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;In a &lt;a href="https://www.tfeb.org/fragments/2023/03/13/variations-on-a-theme/" title="Variations on a theme"&gt;previous article&lt;/a&gt; my friend Zyni wrote some variations on a list-flattening function&lt;sup&gt;&lt;a href="#2023-03-25-the-absurdity-of-stacks-footnote-1-definition" name="2023-03-25-the-absurdity-of-stacks-footnote-1-return"&gt;1&lt;/a&gt;&lt;/sup&gt;, some of which were &amp;lsquo;recursive&amp;rsquo; and some of which &amp;lsquo;iterative&amp;rsquo;. Of course, the ones which claim to be iterative are, in fact, recursive: any procedure which traverses a recursively-defined data structure such as a tree of conses is necessarily recursive. The &amp;lsquo;iterative&amp;rsquo; versions just use an explicitly-maintained stack rather than the implicit stack provided by the language. That makes sense only if stack space is very small compared to the heap and must therefore be conserved. And, well, for many systems that&amp;rsquo;s true. But it is small only because we have administratively decided it should be small: the stack is just memory. If there is plenty of memory for the heap, there is plenty for the stack.&lt;/p&gt;

&lt;p&gt;There are, or may be, arguments for why stacks needed to be small on ancient machines. The history is fascinating, but it is not relevant to today&amp;rsquo;s systems, other than tiny embedded ones. The persistent view of modern machines as giant PDP&amp;ndash;11s has been a blight for well over two decades now: it needs to stop.&lt;/p&gt;

&lt;p&gt;The argument that the stack should be small often seems to be that, if it&amp;rsquo;s not, people will write programs which run away. That&amp;rsquo;s spurious: if such a program is, in fact, iterative, then good compilers will eliminate the tail calls and it will not use stack: a small limit on the stack will not help. If it&amp;rsquo;s really recursive then why should it run out of storage before its conversion to a program which manages the stack explicitly does? Of course &lt;em&gt;that&amp;rsquo;s exactly what compilers which do &lt;a href="https://en.wikipedia.org/wiki/Continuation-passing_style?wprov=sfti1" title="continuation-passing style"&gt;CPS conversion&lt;/a&gt; already do&lt;/em&gt;: programs written using compilers which do that won&amp;rsquo;t have these weird stack limits in the first place. But it should not be necessary to rely on a CPS-converting compiler, or to write in continuation-passing style manually to avoid stack usage: it should be used for other reasons, because the stack is not, in fact, expensive.&lt;/p&gt;

&lt;p&gt;Still less should people feel the need to write programs which explicitly manage a stack except in extraordinary cases.&lt;/p&gt;

&lt;p&gt;There need to be &lt;em&gt;some&lt;/em&gt; limits on stack size, just as there need to be &lt;em&gt;some&lt;/em&gt; limits on heap size, but making the limit on stack size far smaller than the limit on heap size simply encourages people to believe things which aren&amp;rsquo;t true, and to live in fear of recursive programs.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class="footnotes"&gt;
 &lt;ol&gt;
  &lt;li id="2023-03-25-the-absurdity-of-stacks-footnote-1-definition" class="footnote-definition"&gt;
   &lt;p&gt;I still want to know how often functions like this are used in real life.&amp;nbsp;&lt;a href="#2023-03-25-the-absurdity-of-stacks-footnote-1-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content></entry>
 <entry>
  <title type="text">Variations on a theme</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2023/03/13/variations-on-a-theme/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2023-03-13-variations-on-a-theme</id>
  <published>2023-03-13T12:36:33Z</published>
  <updated>2023-03-13T12:36:33Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;My friend Zyni wrote a comment to a thread on reddit with some variations on a list-flattening function. We&amp;rsquo;ve since spent some time thinking about things related to this, which is written up in a following article. Here is her comment so the following article can refer to it. Other than notes at the end the following text is Zyni&amp;rsquo;s, not mine.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h2 id="httpswwwredditcomrcommonlispcomments11o1wvmcommentjbt9n54utmsourceshareutmmediumweb2xcontext3the-reddit-comment-by-zyni"&gt;&lt;a href="https://www.reddit.com/r/Common_Lisp/comments/11o1wvm/comment/jbt9n54/?utm_source=share&amp;amp;utm_medium=web2x&amp;amp;context=3"&gt;The reddit comment by Zyni&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;First of all we all know that CL does not promise to optimize tail recursion: means that tail recursive program may generate recursive not iterative process. So recursive program in CL &lt;em&gt;even if tail recursive&lt;/em&gt; is not safe on data of unknown size, assuming stack is limited.&lt;/p&gt;

&lt;p&gt;But let us assume as good implementations do that tail recursion is optimized in implementation (no need for general tail calls here but is obvious nice thing if implementations do this). Certainly if we are deploying code in space we know what implementation we use and can check this.&lt;/p&gt;

&lt;p&gt;So we look at this supposed wonder of code, which I rewrite slightly to use &lt;a href="https://tfeb.github.io/tfeb-lisp-hax/#applicative-iteration-iterate" title="iterate"&gt;&lt;code&gt;iterate&lt;/code&gt; macro&lt;/a&gt; which is simply Scheme&amp;rsquo;s named-&lt;code&gt;let&lt;/code&gt; to be compatible with later examples:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun flatten (o)
  ;; original terrible one
  (iterate ftn ((x o) (accumulator '()))
    (typecase x
      (null accumulator)
      (cons (ftn (car x) (ftn (cdr x) accumulator)))
      (t (cons x accumulator)))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This &amp;hellip; is really bad program. It makes an essential mistake that it wishes to build result forwards but lists wish to be built backwards, so it must therefore recurse (not tail) on cdr of structure first. But most list-based structures have little weight in car but much in cdr, so this will fail &lt;em&gt;even on list which is already flat&lt;/em&gt;: &lt;code&gt;(flatten (make-list 100000 :initial-element 1))&lt;/code&gt; will fail if your example fails.&lt;/p&gt;

&lt;p&gt;Any person presenting this code as good example should be ashamed of self.&lt;/p&gt;

&lt;p&gt;So first change: we accept that we must build lists backwards but we change program so that tail call is on cdr not car, and reverse result:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun flatten (o)
  ;; not TR but better on usual assumptions
  (nreverse
   (iterate ftn ((x o) (accumulator '()))
     (typecase x
       (null accumulator)
       (cons (ftn (cdr x) (ftn (car x) accumulator)))
       (t (cons x accumulator))))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This function will be fine on assumption of structures which have most weight in their cdrs, which often is true.&lt;/p&gt;

&lt;p&gt;Well, you say, ugly &lt;code&gt;reverse&lt;/code&gt;. OK this is easy: we simply add in a &lt;a href="https://tfeb.github.io/tfeb-lisp-hax/#collecting-lists-forwards-and-accumulating-collecting" title="collecting"&gt;&lt;code&gt;collecting&lt;/code&gt; macro&lt;/a&gt; which allows construction of list forwards, implementation is obvious (tail pointer). Now we have done this we can also reorder calls to be more obvious (car call, not TR, is now first):&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun flatten (o)
  ;; not TR, better on usual assumptions, no reverse
  (collecting
    (iterate ftn ((x o))
      (typecase x
        (cons
         (ftn (car x))
         (ftn (cdr x)))
        (null)
        (t (collect x))))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is still not fully TR, so will fail on structures which have much weight in car.&lt;/p&gt;

&lt;p&gt;Well, of course, we can deal with this as well: we use explicit agenda to move stack onto heap and turn into pure tail recursive version. First one which builds list backwards in obvious way, therefore needs &lt;code&gt;reverse&lt;/code&gt; again:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun flatten (o)
  ;; pure TR
  (iterate ftn ((agenda (list o))
                (accumulator '()))
    (if (null agenda)
        ;; can write own reverse as tail recursive of course if wish
        ;; to be pure of heart
        (nreverse accumulator)
      (destructuring-bind (this . more) agenda
        (typecase this
          (null
           (ftn more accumulator))
          (cons
           (ftn (list* (car this) (cdr this) more) accumulator))
          (t
           (ftn more (cons this accumulator))))))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Assuming implementation optimizes tail recursion this will flatten completely arbitrary structure limited only by memory.&lt;/p&gt;

&lt;p&gt;We can avoid this reversery of course:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun flatten (o)
  ;; pure TR, no reverse
  (collecting
    (iterate ftn ((agenda (list o)))
      (when (not (null agenda))
        (destructuring-bind (this . more) agenda
          (typecase this
            (null
             (ftn more))
            (cons
             (ftn (list* (car this) (cdr this) more)))
            (t
             (collect this)
             (ftn more))))))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As before this is limited only by memory assuming implementation optimizes tail calls.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Well, I have written Lisp for only couple of years really (but have maths background). But even I can see that this idea of having to put scary label on recursive function is very bad. Instead people using such code should perhaps &lt;em&gt;read it and understand it&lt;/em&gt; to see what its problems and advantages are. Radical idea, I know.&lt;/p&gt;

&lt;p&gt;Finally idea that stack space is scarce may or may not be true. Example, if we rewrite original version in Racket (first Lisp I used before being lured to dark side):&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(define (flatten o)
  (let ftn ([x o] [accumulator '()])
    (cond
      [(null? x) accumulator]
      [(cons? x) (ftn (car x) (ftn (cdr x) accumulator))]
      [else (cons x accumulator)])))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will happily &amp;lsquo;flatten&amp;rsquo; 100,000 element list and is only limited by memory available because Racket does not treat stack same way.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Finally here is variant of final version using &lt;a href="https://tfeb.github.io/tfeb-lisp-hax/#decomposing-iteration-simple-loops" title="simple loops"&gt;&lt;code&gt;looping&lt;/code&gt; macro&lt;/a&gt; which does applicative iteration: this is iterative, on any implementation:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun flatten (o)
  ;; Iterative
  (collecting
    (looping ((agenda (list o)))
      (when (null agenda)
        (return))
      (destructuring-bind (this . more) agenda
        (typecase this
          (null more)
          (cons (list* (car this) (cdr this) more))
          (t (collect this) more))))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;looping&lt;/code&gt; part of this turns into:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(let ((agenda (list o)))
  (block nil
    (tagbody
     #:start (setq agenda
                   (progn
                     (when (null agenda) (return))
                     (destructuring-bind (this . more) agenda
                       (typecase this
                         (null more)
                         (cons (list* (car this) (cdr this) more))
                         (t (collect this) more)))))
             (go #:start))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;which is iterative.&lt;/p&gt;

&lt;p&gt;I think &lt;code&gt;iterate&lt;/code&gt; one is nicer.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id="notes-from-tim"&gt;Notes from Tim&lt;/h2&gt;

&lt;p&gt;English is Zyni&amp;rsquo;s third language: she wanted me to fix up the above but I refused as I find the way she writes so charming.&lt;/p&gt;

&lt;p&gt;Both of us would like to know how often &lt;code&gt;flatten&lt;/code&gt; is actually used: everyone seems to be very keen on it, but we can&amp;rsquo;t think of any cases where we&amp;rsquo;ve ever wanted it or anything very much like it.&lt;/p&gt;

&lt;p&gt;All of the macros referenced are &amp;lsquo;mine&amp;rsquo; in a somewhat loose sense: They&amp;rsquo;re all published by me, and some of them are mine, some of them were mine but have been made much better by Zyni, some of them are really hers. There are generally comments in the code. Zyni refuses to have anything but a very minimal internet presence for reasons I used to think were absurd but no longer do: you can&amp;rsquo;t be too careful when your parents and by extension you might be on the wrong side of Putin.&lt;/p&gt;

&lt;p&gt;Zyni is not her real name, obviously.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Two tiny Lisp evaluators</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2023/02/27/two-tiny-lisp-evaluators/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2023-02-27-two-tiny-lisp-evaluators</id>
  <published>2023-02-27T14:19:38Z</published>
  <updated>2023-02-27T14:19:38Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;Everyone who has written Lisp has written tiny Lisp evaluators in Lisp: here are two more.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;Following two &lt;a href="https://tfeb.org/fragments/2023/02/22/how-to-understand-closures-in-common-lisp/"&gt;recent&lt;/a&gt; &lt;a href="https://tfeb.org/fragments/2023/02/27/dynamic-binding-without-special-in-common-lisp/"&gt;articles&lt;/a&gt; I wrote on scope and extent in Common Lisp, I thought I would finish with two very tiny evaluators for dynamically and lexically bound variants on a tiny Lisp.&lt;/p&gt;

&lt;h2 id="the-language"&gt;The language&lt;/h2&gt;

&lt;p&gt;The tiny Lisp these evaluators interpret is not minimal: it has constructs other than &lt;code&gt;lambda&lt;/code&gt;, and even has assignment. But it is pretty small. Other than the binding rules the languages are identical.&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;strong&gt;&lt;code&gt;λ&lt;/code&gt;&lt;/strong&gt; &amp;amp; &lt;strong&gt;&lt;code&gt;lambda&lt;/code&gt;&lt;/strong&gt; are synonyms and construct procedures, which can take any number of arguments;&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;&lt;code&gt;quote&lt;/code&gt;&lt;/strong&gt; quotes its argument;&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;&lt;code&gt;if&lt;/code&gt;&lt;/strong&gt; is conditional expression (the else part is optional);&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;&lt;code&gt;set!&lt;/code&gt;&lt;/strong&gt; is assignment and mutates a binding.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;That is all that exists.&lt;/p&gt;

&lt;p&gt;Both evaluators understand primitives, which are usually just functions in the underlying Lisp: since the languages are Lisp&amp;ndash;1s, you could also expose other sorts of things of course (for instance true and false values). You can provide a list of initial bindings to them to define useful primitives.&lt;/p&gt;

&lt;h2 id="requirements"&gt;Requirements&lt;/h2&gt;

&lt;p&gt;Both evaluators rely on my &lt;a href="https://tfeb.github.io/tfeb-lisp-hax/#applicative-iteration-iterate"&gt;iterate&lt;/a&gt; and &lt;a href="https://tfeb.github.io/tfeb-lisp-hax/#simple-pattern-matching-spam"&gt;spam&lt;/a&gt; hacks: they could easily be rewritten not to do so.&lt;/p&gt;

&lt;h2 id="the-dynamic-evaluator"&gt;The dynamic evaluator&lt;/h2&gt;

&lt;p&gt;A procedure is represented by a structure which has a list of formals and a body of one or more forms.&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defstruct (procedure
            (:print-function
             (lambda (p s d)
               (declare (ignore d))
               (print-unreadable-object (p s)
                 (format s "λ ~S" (procedure-formals p))))))
  (formals '())
  (body '()))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The evaluator simply dispatches on the type of thing and then on the operator for compound forms.&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun evaluate (thing bindings)
  (typecase thing
    (symbol
     (let ((found (assoc thing bindings)))
       (unless found
         (error "~S unbound" thing))
       (cdr found)))
    (list
     (destructuring-bind (op . arguments) thing
       (case op
         ((lambda λ)
          (matching arguments
            ((head-matches (list-of #'symbolp))
             (make-procedure :formals (first arguments)
                             :body (rest arguments)))
            (otherwise
             (error "bad lambda form ~S" thing))))
         ((quote)
          (matching arguments
            ((list-matches (any))
             (first arguments))
            (otherwise
             (error "bad quote form ~S" thing))))
         ((if)
          (matching arguments
            ((list-matches (any) (any))
             (if (evaluate (first arguments) bindings)
                 (evaluate (second arguments) bindings)))
            ((list-matches (any) (any) (any))
             (if (evaluate (first arguments) bindings)
                 (evaluate (second arguments) bindings)
               (evaluate (third arguments) bindings)))
            (otherwise
             (error "bad if form ~S" thing))))
         ((set!)
          (matching arguments
            ((list-matches #'symbolp (any))
             (let ((found (assoc (first arguments) bindings)))
               (unless found
                 (error "~S unbound" (first arguments)))
               (setf (cdr found) (evaluate (second arguments) bindings))))
            (otherwise
             (error "bad set! form ~S" thing))))
         (t
          (applicate (evaluate (first thing) bindings)
                     (mapcar (lambda (form)
                               (evaluate form bindings))
                             (rest thing))
                     bindings)))))
    (t thing)))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The interesting thing here is that &lt;code&gt;applicate&lt;/code&gt; needs to know the current set of bindings so it can extend them dynamically.&lt;/p&gt;

&lt;p&gt;Here is &lt;code&gt;applicate&lt;/code&gt; which has a case for primitives and procedures&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun applicate (thing arguments bindings)
  (etypecase thing
    (function
     ;; a primitive
     (apply thing arguments))
    (procedure
     (iterate bind ((vtail (procedure-formals thing))
                    (atail arguments)
                    (extended-bindings bindings))
       (cond
        ((and (null vtail) (null atail))
         (iterate eval-body ((btail (procedure-body thing)))
           (if (null (rest btail))
               (evaluate (first btail) extended-bindings)
             (progn
               (evaluate (first btail) extended-bindings)
               (eval-body (rest btail))))))
        ((null vtail)
         (error "too many arguments"))
        ((null atail)
         (error "not enough arguments"))
        (t
         (bind (rest vtail)
               (rest atail)
               (acons (first vtail) (first atail)
                      extended-bindings))))))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The thing that makes this evaluator dynamic is that the bindings that &lt;code&gt;applicate&lt;/code&gt; extends are those it was given: procedures do not remember bindings.&lt;/p&gt;

&lt;h2 id="the-lexical-evaluator"&gt;The lexical evaluator&lt;/h2&gt;

&lt;p&gt;A procedure is represented by a structure as before, but this time it has a set of bindings associated with it: the bindings in place when it was created.&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defstruct (procedure
            (:print-function
             (lambda (p s d)
               (declare (ignore d))
               (print-unreadable-object (p s)
                 (format s "λ ~S" (procedure-formals p))))))
  (formals '())
  (body '())
  (bindings '()))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The evaluator is almost identical:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun evaluate (thing bindings)
  (typecase thing
    (symbol
     (let ((found (assoc thing bindings)))
       (unless found
         (error "~S unbound" thing))
       (cdr found)))
    (list
     (destructuring-bind (op . arguments) thing
       (case op
         ((lambda λ)
          (matching arguments
            ((head-matches (list-of #'symbolp))
             (make-procedure :formals (first arguments)
                             :body (rest arguments)
                             :bindings bindings))
            (otherwise
             (error "bad lambda form ~S" thing))))
         ((quote)
          (matching arguments
            ((list-matches (any))
             (first arguments))
            (otherwise
             (error "bad quote form ~S" thing))))
         ((if)
          (matching arguments
            ((list-matches (any) (any))
             (if (evaluate (first arguments) bindings)
                 (evaluate (second arguments) bindings)))
            ((list-matches (any) (any) (any))
             (if (evaluate (first arguments) bindings)
                 (evaluate (second arguments) bindings)
               (evaluate (third arguments) bindings)))
            (otherwise
             (error "bad if form ~S" thing))))
         ((set!)
          (matching arguments
            ((list-matches #'symbolp (any))
             (let ((found (assoc (first arguments) bindings)))
               (unless found
                 (error "~S unbound" (first arguments)))
               (setf (cdr found) (evaluate (second arguments) bindings))))
            (otherwise
             (error "bad set! form ~S" thing))))
         (t
          (applicate (evaluate (first thing) bindings)
                     (mapcar (lambda (form)
                               (evaluate form bindings))
                             (rest thing)))))))
    (t thing)))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The differences are that when constructing a procedure the current bindings are recorded in the procedure, and it is no longer necessary to pass bindings to &lt;code&gt;applicate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;applicate&lt;/code&gt; is also almost identical:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun applicate (thing arguments)
  (etypecase thing
    (function
     ;; a primitive
     (apply thing arguments))
    (procedure
     (iterate bind ((vtail (procedure-formals thing))
                    (atail arguments)
                    (extended-bindings (procedure-bindings thing)))
       (cond
        ((and (null vtail) (null atail))
         (iterate eval-body ((btail (procedure-body thing)))
           (if (null (rest btail))
               (evaluate (first btail) extended-bindings)
             (progn
               (evaluate (first btail) extended-bindings)
               (eval-body (rest btail))))))
        ((null vtail)
         (error "too many arguments"))
        ((null atail)
         (error "not enough arguments"))
        (t
         (bind (rest vtail)
               (rest atail)
               (acons (first vtail) (first atail)
                      extended-bindings))))))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The difference is that the bindings it extends when binding arguments are the bindings which the procedure remembered, not the dynamically-current bindings, which it does not even know.&lt;/p&gt;

&lt;h2 id="the-difference-between-them"&gt;The difference between them&lt;/h2&gt;

&lt;p&gt;Here is the example that shows how these two evaluators differ.&lt;/p&gt;

&lt;p&gt;With the dynamic evaluator:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;? ((λ (f)
     ((λ (x)
        ;; bind x to 1 around the call to f
        (f))
      1))
   ((λ (x)
      ;; bind x to 2 when the function that will be f is created
      (λ () x))
    2))
1&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The binding in effect is the dynamically current one, not the one that was in effect when the procedure was created.&lt;/p&gt;

&lt;p&gt;With the lexical evaluator:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;? ((λ (f)
     ((λ (x)
        ;; bind x to 1 around the call to f
        (f))
      1))
   ((λ (x)
      ;; bind x to 2 when the function that will be f is created
      (λ () x))
    2))
2&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now the binding in effect is the one that existed when the procedure was created.&lt;/p&gt;

&lt;p&gt;Something more interesting is how you create recursive procedures in the lexical evaluator. With suitable bindings for primitives, it&amp;rsquo;s easy to see that this can&amp;rsquo;t work:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;((λ (length)
   (length '(1 2 3)))
 (λ (l)
   (if (null? l)
       0
       (+ (length (cdr l)) 1))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It can&amp;rsquo;t work because &lt;code&gt;length&lt;/code&gt; is not in scope in the body of &lt;code&gt;length&lt;/code&gt;. it &lt;em&gt;will&lt;/em&gt; work in the dynamic evaluator.&lt;/p&gt;

&lt;p&gt;The first fix, which is similar to what Scheme does with &lt;code&gt;letrec&lt;/code&gt;, is to use assignment to mutate the binding so it is correct:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;((λ (length)
   (set! length (λ (l)
                  (if (null? l)
                      0
                      (+ (length (cdr l)) 1))))
   (length '(1 2 3)))
 0)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note the initial value of &lt;code&gt;length&lt;/code&gt; is never used.&lt;/p&gt;

&lt;p&gt;The second fix is to use something like &lt;a href="https://tfeb.org/fragments/2020/03/09/the-u-combinator/"&gt;the U combinator&lt;/a&gt; (you could use Y of course: I think U is simpler to understand):&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;((λ (length)
   (length '(1 2 3)))
 (λ (l)
   ((λ (c)
      (c c l 0))
    (λ (c t s)
      (if (null? t)
          s
          (c c (cdr t) (+ s 1)))))))&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="source-code"&gt;Source code&lt;/h2&gt;

&lt;p&gt;These two evaluators, together with a rudimentary REPL which can use either of them, can be found &lt;a href="https://github.com/tfeb/tiny-eval"&gt;here&lt;/a&gt;.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Dynamic binding without special in Common Lisp</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2023/02/27/dynamic-binding-without-special-in-common-lisp/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2023-02-27-dynamic-binding-without-special-in-common-lisp</id>
  <published>2023-02-27T09:53:27Z</published>
  <updated>2023-02-27T09:53:27Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;In Common Lisp, dynamic bindings and lexical bindings live in the same namespace. They don&amp;rsquo;t have to.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;Common Lisp has &lt;a href="https://www.tfeb.org/fragments/2023/02/22/how-to-understand-closures-in-common-lisp/" title="How to understand closures in Common Lisp"&gt;two sorts of bindings for variables&lt;/a&gt;: lexical binding and dynamic binding. Lexical binding has lexical scope &amp;mdash; the binding is available where it is visible in source code &amp;mdash; and indefinite extent &amp;mdash; the binding is available as long as any code might reference it. Dynamic binding has indefinite scope &amp;mdash; the binding is available to any code which runs between when the binding is established and when control leaves the form which established it &amp;mdash; and dynamic extent &amp;mdash; the binding ceases to exist when control leaves the binding form.&lt;/p&gt;

&lt;p&gt;These are really two very different things. However CL places both of these kinds of bindings into the same namespace, relying on &lt;code&gt;special&lt;/code&gt; declarations and proclamations to tell the system which sort of binding to create and reference for a given name.&lt;/p&gt;

&lt;p&gt;That doesn&amp;rsquo;t have to be the case: it&amp;rsquo;s possible in CL to completely isolate these two namespaces from each other. This means you could write code where all variable references were to lexical bindings and where dynamic bindings were created and referenced by a completely different set of operators. Here is an example of that. Following practice in some old Lisps I will call this &amp;lsquo;fluid&amp;rsquo; binding. I will also use &lt;code&gt;/&lt;/code&gt; to delimit the names of fluid variables simply to distinguish them from normal variables.&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun inner (varname value)
  (setf (fluid-value varname) value))

(defun outer (varname value)
  (call/fluid-bindings
   (lambda ()
     (values
      (fluid-value varname)
      (progn
        (inner varname (1+ value))
        (fluid-value varname))))
   (list varname)
   (list value)))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (outer '/v/ 1)
1
2&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here are a set of operators for dealing with these fluid variables:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;fluid-value&lt;/code&gt;&lt;/strong&gt; accesses the value of a fluid variable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;fluid-boundp&lt;/code&gt;&lt;/strong&gt; tells you if a name is bound as a fluid variable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;call/fluid-bindings&lt;/code&gt;&lt;/strong&gt; calls a function with one or more fluid variables bound.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;define-fluid&lt;/code&gt;&lt;/strong&gt; (not used above) defines a global value for a fluid variable.&lt;/p&gt;

&lt;p&gt;Well, of course you can do something like this using an explicit binding stack and a single special variable to hang it from. But that&amp;rsquo;s not how this works: these &amp;lsquo;fluid variables&amp;rsquo; are just CL&amp;rsquo;s dynamic variables:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun call/print-base (f base)
  (call/fluid-bindings  f '(*print-base*) (list base)))&lt;/code&gt;&lt;/pre&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (call/print-base
   (lambda ()
     *print-base*)
   2)
2&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So how does this work? Well &lt;code&gt;fluid-value&lt;/code&gt; and &lt;code&gt;fluid-boundp&lt;/code&gt; are obvious:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun fluid-value (s)
  (symbol-value s))

(defun (setf fluid-value) (n s)
  (setf (symbol-value s) n))

(defun fluid-boundp (s)
  (boundp s))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And the trick now is that &lt;em&gt;CL gives you enough mechanism to bind named dynamic variables yourself&lt;/em&gt;, that mechanism being &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/s_progv.htm" title="progv"&gt;progv&lt;/a&gt;, which&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;[&amp;hellip;] allows binding one or more dynamic variables whose names may be determined at run time [&amp;hellip;]&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;So now &lt;code&gt;call/fluid-bindings&lt;/code&gt; just uses &lt;code&gt;progv&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun call/fluid-bindings (f fluids values)
  (progv fluids values (funcall f)))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And finally &lt;code&gt;define-fluid&lt;/code&gt; looks like this:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defmacro define-fluid (var &amp;amp;optional (value nil)
                            (doc nil docp))
  `(progn
     (setf (fluid-value ',var) ,value)
     ,@(if docp
           `((setf (documentation ',var 'variable) ',doc))
         '())
     ',var))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The interesting thing here is that there are no &lt;code&gt;special&lt;/code&gt; declarations or proclamations: you can create and bind new fluid variables without any recourse to &lt;code&gt;special&lt;/code&gt; at all, in a way which is completely compatible with the existing dynamic variables, because fluid variables &lt;em&gt;are&lt;/em&gt; dynamic variables.&lt;/p&gt;

&lt;p&gt;So one way of thinking about &lt;code&gt;special&lt;/code&gt; is that it is a declaration that says &amp;lsquo;for this variable name, access the namespace of dynamic bindings rather than lexical bindings&amp;rsquo;. This is not really what &lt;code&gt;special&lt;/code&gt; was of course in Lisps before CL &amp;mdash; it was historically closer to an instruction to use the interpreter&amp;rsquo;s variable binding mechanism in compiled code &amp;mdash; but you can think of it this way in CL, where the interpreter and compiler do not have separate binding rules.&lt;/p&gt;

&lt;p&gt;And, of course, using something like the above, you could write code in CL where all variable bindings were lexical and dynamic variables lived entirely in their own namespace. For instance this works fine:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun f ()
  (let ((x 2))
    (call/fluid-bindings
     (lambda ()
       (values x (fluid-value 'x)))
     '(x) '(3))))&lt;/code&gt;&lt;/pre&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (f)
2
3&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The reference to &lt;code&gt;x&lt;/code&gt; as a variable refers to its lexical binding, while &lt;code&gt;(fluid-value 'x)&lt;/code&gt; refers to its dynamic binding.&lt;/p&gt;

&lt;p&gt;Whether writing code like that would be useful I am not sure: I think that the &lt;code&gt;*&lt;/code&gt;-convention for dynamic variables is perfectly fine in fact. But it is perhaps interesting to see that you can think of dynamic bindings in CL this way.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">How to understand closures in Common Lisp</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2023/02/22/how-to-understand-closures-in-common-lisp/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2023-02-22-how-to-understand-closures-in-common-lisp</id>
  <published>2023-02-22T13:51:07Z</published>
  <updated>2023-02-22T13:51:07Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;The first rule of understanding closures is that you do not talk about closures. The second rule of understanding closures in Common Lisp is that &lt;em&gt;you do not talk about closures&lt;/em&gt;. These are all the rules.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;There is a lot of elaborate bowing and scraping about closures in the Lisp community. But despite that &lt;em&gt;a closure isn&amp;rsquo;t actually a thing&lt;/em&gt;: the thing people call a closure is just a function which obeys the language&amp;rsquo;s rules about the scope and extent of bindings. &lt;em&gt;Implementors&lt;/em&gt; need to care about closures: users just need to understand the rules for bindings. So rather than obsessing about this magic invisible thing which doesn&amp;rsquo;t actually exist in the language, I suggest that it is far better simply to think about the rules which cover &lt;em&gt;bindings&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id="angels-and-pinheads"&gt;Angels and pinheads&lt;/h2&gt;

&lt;p&gt;It&amp;rsquo;s easy to see why this has happened: &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Front/index.htm" title="HyperSpec"&gt;the CL standard&lt;/a&gt; has a lot of discussion of &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_l.htm#lexical_closure" title="lexical closure"&gt;lexical closures&lt;/a&gt;, &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_l.htm#lexical_environment" title="lexical environment"&gt;lexical&lt;/a&gt; and &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_d.htm#dynamic_environment" title="dynamic environment"&gt;dynamic&lt;/a&gt; environments and so on. So it&amp;rsquo;s tempting to think that this way of thinking about things is &amp;lsquo;the one true way&amp;rsquo; because it has been blessed by those who went before us. And indeed CL does have &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/03_aad.htm" title="environment objects"&gt;objects representing part of the lexical environment&lt;/a&gt; which are given to macro functions. Occasionally these are even useful. But there are &lt;em&gt;no&lt;/em&gt; objects which represent closures as distinct from functions, and &lt;em&gt;no&lt;/em&gt; predicates which tell you if a function is a closure or not in the standard language: closures simply do not exist as objects distinct from functions at all. They were useful, perhaps, as part of the text which &lt;em&gt;defined&lt;/em&gt; the language, but they are nowhere to be found in the language itself.&lt;/p&gt;

&lt;p&gt;So, with the exception of the environment objects passed to macros, &lt;em&gt;none&lt;/em&gt; of these objects exist in the language. They may exist in implementations, and might even be exposed by some implementations, but from the point of the view of the language they simply do not exist: if I give you a function object you cannot know if it is a closure or not.&lt;/p&gt;

&lt;p&gt;So it is strange that people spend so much time worrying about these objects which, if they even exist in the implementation, can&amp;rsquo;t be detected by anyone using the standard language. This is worrying about angels and pinheads: wouldn&amp;rsquo;t it be simpler to simply understand what the rules of the language actually say should observably happen? I think it would.&lt;/p&gt;

&lt;p&gt;I am not arguing that the terminology used by the standard is wrong! All I am arguing is that, if you think you want to understand closures, you might instead be better off understanding the rules that give rise to them. And when you have done that you may suddenly find that closures have simply vanished into the mist: all you need is the rules.&lt;/p&gt;

&lt;h2 id="history"&gt;History&lt;/h2&gt;

&lt;p&gt;Common Lisp is steeped in history: it is full of traces of the Lisps which went before it. This is intentional: one goal of CL was to enable programs written in those earlier Lisps &amp;mdash; which were &lt;em&gt;all&lt;/em&gt; Lisps at that time of course &amp;mdash; to run without extensive modification.&lt;/p&gt;

&lt;p&gt;But one place where CL &lt;em&gt;didn&amp;rsquo;t&lt;/em&gt; steep itself in history is in exactly the areas that you need to understand to understand closures. Before Common Lisp (really, before Scheme), people spent a lot of time writing papers about &lt;a href="https://en.wikipedia.org/wiki/Funarg_problem" title="the funarg problem"&gt;the funarg problem&lt;/a&gt; and describing and implementing more-or-less complicated ways of resolving it. Then Scheme came along and decided that this was all nonsense and that it could just be made to go away by implementing the language properly. And the Common Lisp designers, who knew about Scheme, said that, well, if Scheme can do this, then we can do this as well, and so they also made it the problem vanish, although not in quite such an extreme way as Scheme did.&lt;/p&gt;

&lt;p&gt;And this is now ancient history: these predecessor Lisps to CL are all at least 40 years old now. I am, just, old enough to have used some of them when they were current, but for most CL programmers these questions were resolved before they were born. The history is very interesting, but you do not need to steep yourself in it to understand closures.&lt;/p&gt;

&lt;h2 id="bindings"&gt;Bindings&lt;/h2&gt;

&lt;p&gt;So the notion of a closure is part of the history behind CL: a hangover from the time when people worried about the funarg problem; a time before they understood that the whole problem could simply be made to go away. So, again, if you think you want to understand closures, the best approach is to understand something else: to understand &lt;em&gt;bindings&lt;/em&gt;. Just as with closures, bindings do not exist as objects in the language, although you &lt;em&gt;can&lt;/em&gt; make some enquiries about some kinds of bindings in CL. They are also a concept which exists in many programming languages, not just CL.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;binding&lt;/strong&gt; is an association between a name &amp;mdash; a symbol &amp;mdash; and something. The most common binding is a variable binding, which is an association between a name and a value. There are other kinds of bindings however: the most obvious kind in CL is a function binding: an association between a name and a function object. And for example within a (possibly implicit) &lt;code&gt;block&lt;/code&gt; there is a binding between the name of the block and a point to which you can jump. And there are other kinds of bindings in CL as well, and the set is extensible. &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_b.htm#binding" title="binding"&gt;The CL standard&lt;/a&gt; only calls variable bindings &amp;lsquo;bindings&amp;rsquo;, but I am going to use the term more generally.&lt;/p&gt;

&lt;p&gt;Bindings are established by some binding construct and are usually not first-class objects in CL: they are just as vaporous as closures and environments. Nevertheless they are a powerful and useful idea.&lt;/p&gt;

&lt;h2 id="what-can-be-bound"&gt;What can be bound?&lt;/h2&gt;

&lt;p&gt;By far the most common kind of binding is a &lt;strong&gt;variable binding&lt;/strong&gt;: an association between a name and a value. However there are other kinds of bindings: associations between names and other things. I&amp;rsquo;ll mention those briefly at the end, but in everything else that follows it&amp;rsquo;s safe to assume that &amp;lsquo;binding&amp;rsquo; means &amp;lsquo;variable binding&amp;rsquo; unless I say otherwise.&lt;/p&gt;

&lt;h2 id="scope-and-extent"&gt;Scope and extent&lt;/h2&gt;

&lt;p&gt;For both variable bindings and other kinds of bindings there are two interesting questions you can ask:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;em&gt;where&lt;/em&gt; is the binding available?&lt;/li&gt;
 &lt;li&gt;&lt;em&gt;when&lt;/em&gt; is the binding visible?&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;The first question is about the &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_s.htm#scope" title="scope"&gt;&lt;strong&gt;scope&lt;/strong&gt;&lt;/a&gt; of the binding. The second is about the &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_e.htm#extent" title="extent"&gt;&lt;strong&gt;extent&lt;/strong&gt;&lt;/a&gt; of the binding.&lt;/p&gt;

&lt;p&gt;Each of these questions has (at least) two possible answers giving (at least) four possibilities. CL has bindings which use three of these possibilities and the fourth in a restricted case: two and a restricted version of a third for variable bindings, the other one for some other kinds of bindings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scope.&lt;/strong&gt; The two options are:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;the binding may be available only in code where the binding construct is visible;&lt;/li&gt;
 &lt;li&gt;or the binding may be available during all code which runs between where the binding is established and where it ends, regardless of whether the binding construct is visible.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;What does &amp;lsquo;visible&amp;rsquo; mean? Well, given some binding form, it means that the bindings it establishes are visible to all the code that is inside that form in the source. So, in a form like &lt;code&gt;(let ((x 1)) ...)&lt;/code&gt; the binding of &lt;code&gt;x&lt;/code&gt; is visible to the code that replaces the ellipsis, including any code introduced by macroexpansion, and only to that code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extent.&lt;/strong&gt; The two options are:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;the binding may exist only during the time that the binding construct is active, and goes away when control leaves it;&lt;/li&gt;
 &lt;li&gt;or the binding may exist as long as there is any possibility of reference.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Unfortunately the CL standard is, I think, slightly inconsistent in its naming for these options. However I&amp;rsquo;m going to use the standard&amp;rsquo;s terms with one exception. Here they are.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scope&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;when a binding is available only when visible this called &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_l.htm#lexical_scope" title="lexical scope"&gt;&lt;strong&gt;lexical scope&lt;/strong&gt;&lt;/a&gt;;&lt;/li&gt;
 &lt;li&gt;when a binding available to all code within the binding construct this is called &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_i.htm#indefinite_scope" title="indefinite scope"&gt;&lt;strong&gt;indefinite scope&lt;/strong&gt;&lt;/a&gt;&lt;sup&gt;&lt;a href="#2023-02-22-how-to-understand-closures-in-common-lisp-footnote-1-definition" name="2023-02-22-how-to-understand-closures-in-common-lisp-footnote-1-return"&gt;1&lt;/a&gt;&lt;/sup&gt;;&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Extent&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;when a binding ends at the end of the binding form this is called &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_d.htm#dynamic_extent" title="dynamic extent"&gt;&lt;strong&gt;dynamic extent&lt;/strong&gt;&lt;/a&gt;&lt;sup&gt;&lt;a href="#2023-02-22-how-to-understand-closures-in-common-lisp-footnote-2-definition" name="2023-02-22-how-to-understand-closures-in-common-lisp-footnote-2-return"&gt;2&lt;/a&gt;&lt;/sup&gt;;&lt;/li&gt;
 &lt;li&gt;when a binding available indefinitely this called &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_i.htm#indefinite_extent" title="indefinite extent"&gt;&lt;strong&gt;indefinite extent&lt;/strong&gt;&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;The term from the standard I am &lt;em&gt;not&lt;/em&gt; going to use is &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_d.htm#dynamic_scope" title="dynamic scope"&gt;&lt;strong&gt;dynamic scope&lt;/strong&gt;&lt;/a&gt;, which it defines to mean the combination of indefinite scope and dynamic extent. I am not going to use this term because I think it is confusing: although it has &amp;lsquo;scope&amp;rsquo; in its name it concerns both scope and extent. Instead I will introduce better, commonly used, terms below for the interesting combinations of scope and extent.&lt;/p&gt;

&lt;p&gt;The four possibilities for bindings are then:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;lexical scope and dynamic extent;&lt;/li&gt;
 &lt;li&gt;lexical scope and indefinite extent;&lt;/li&gt;
 &lt;li&gt;indefinite scope and dynamic extent;&lt;/li&gt;
 &lt;li&gt;indefinite scope and indefinite extent.&lt;/li&gt;&lt;/ul&gt;

&lt;h2 id="the-simplest-kind-of-binding"&gt;The simplest kind of binding&lt;/h2&gt;

&lt;p&gt;So then let&amp;rsquo;s ask: what is the simplest kind of binding to understand? If you are reading some code and you see a reference to a binding then what choice from the above options will make it easiest for you to understand whether that reference is valid or not?&lt;/p&gt;

&lt;p&gt;Well, the first thing is that you&amp;rsquo;d like to be able to know &lt;em&gt;by looking at the code&lt;/em&gt; whether a reference is valid or not. That means that the binding construct should be &lt;em&gt;visible&lt;/em&gt; to you, or that the binding should have lexical scope. Compare the following two fragments of code:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun simple (x)
  ...
  (+ x 1)
  ...)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun confusing ()
  ...
  (+ *x* 1)
  ...)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, in the first one you can tell, just by looking at the code, that the reference to &lt;code&gt;x&lt;/code&gt; is valid: the function, when called, establishes a binding of &lt;code&gt;x&lt;/code&gt; and you can see that when reading the code. In the second one you just have to assume that the reference to &lt;code&gt;*x*&lt;/code&gt; is valid: you can&amp;rsquo;t tell by reading the code whether it is or not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lexical scope&lt;/strong&gt; makes it easiest for people reading the code to understand it, and in particular it is easier to understand than indefinite scope. It is the simplest kind of scoping to understand for people reading the code.&lt;/p&gt;

&lt;p&gt;So that leaves extent. Well, in the two examples above definite or indefinite extent makes no difference to how simple the code is to understand: once the functions return there&amp;rsquo;s no possibility of reference to the bindings anyway. To expose the difference we need somehow to construct some object which can refer to a binding &lt;em&gt;after the function has returned&lt;/em&gt;. We need something like this:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun maker (x)
  ...
  &amp;lt;construct object which refers to binding of x&amp;gt;)

(let ((o (maker 1)))
  &amp;lt;use o somehow to cause it to reference the binding of x&amp;gt;)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, what it this object going to be? What sort of things reference bindings? &lt;em&gt;Code&lt;/em&gt; references bindings, and the objects which contain code are &lt;em&gt;functions&lt;/em&gt;&lt;sup&gt;&lt;a href="#2023-02-22-how-to-understand-closures-in-common-lisp-footnote-3-definition" name="2023-02-22-how-to-understand-closures-in-common-lisp-footnote-3-return"&gt;3&lt;/a&gt;&lt;/sup&gt;. What we need to do is construct and return a function:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun maker (x)
  (lambda (y)
    (+ x y)))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and then cause this function to reference the binding by calling it:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(let ((f (maker 1)))
  (funcall f 2))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So now we can, finally, ask: what is the choice for the &lt;em&gt;extent&lt;/em&gt; of the binding of &lt;code&gt;x&lt;/code&gt; which makes this code simplest to understand? Well, the answer is that unless the binding of &lt;code&gt;x&lt;/code&gt; remains visible to the function that is created in &lt;code&gt;maker&lt;/code&gt;, this code &lt;em&gt;can&amp;rsquo;t work at all&lt;/em&gt;. It would have to be the case that it was simply not legal to return functions like this from other functions. Functions, in other words, would not be first-class objects.&lt;/p&gt;

&lt;p&gt;Well, OK, that&amp;rsquo;s a possibility, and it makes the above code simple to understand: it&amp;rsquo;s not legal and it&amp;rsquo;s easy to see that it is not. Except consider this small variant on the above:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun maybe-maker (x return-identity-p)
  (if return-identity-p
      #'identity
    (lambda (y)
      (+ x y))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There is &lt;em&gt;no way to know&lt;/em&gt; from reading this code whether &lt;code&gt;maybe-maker&lt;/code&gt; will return the nasty anonymous function or the innocuous &lt;code&gt;identity&lt;/code&gt; function. If it is not allowed to return anonymous functions in this way then there is &lt;em&gt;no way of knowing&lt;/em&gt; whether&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(funcall (maybe-maker 1 (zerop (random 2)))
         2)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;is correct or not. This is certainly not simple: in fact it is a horrible nightmare. Another way of saying this is that you&amp;rsquo;d be in a situation where&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(let ((a 1))
  (funcall (lambda ()
             a)))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;would work, but&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(funcall (let ((a 1))
           (lambda ()
             a)))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;would not. There are languages which work that way: those languages suck.&lt;/p&gt;

&lt;p&gt;So what &lt;em&gt;would&lt;/em&gt; be simple? What would be simple is to say that if a binding is visible, it is visible, and that&amp;rsquo;s the end of the story. In a function like &lt;code&gt;maker&lt;/code&gt; above the binding of &lt;code&gt;x&lt;/code&gt; established by &lt;code&gt;maker&lt;/code&gt; is visible to the function that it returns. Therefore &lt;em&gt;it&amp;rsquo;s visible to the function that &lt;code&gt;maker&lt;/code&gt; returns&lt;/em&gt;: without any complicated rules or weird special cases. That means the binding must have indefinite extent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Indefinite extent&lt;/strong&gt; makes it easiest for people reading the code to understand it when that code may construct and return functions, and in particular it is easier to understand than dynamic extent, which makes it essentially impossible to tell in many cases whether such code is correct or not.&lt;/p&gt;

&lt;p&gt;And that&amp;rsquo;s it: lexical scope and indefinite extent, which I will call &lt;strong&gt;lexical binding&lt;/strong&gt;, is the simplest binding scheme to understand for a language which has first-class functions&lt;sup&gt;&lt;a href="#2023-02-22-how-to-understand-closures-in-common-lisp-footnote-4-definition" name="2023-02-22-how-to-understand-closures-in-common-lisp-footnote-4-return"&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;And really &lt;em&gt;that&amp;rsquo;s it&lt;/em&gt;: that&amp;rsquo;s all you need to understand. Lexical scope and indefinite extent make reading code simple, and entirely explain the things people call &amp;lsquo;closures&amp;rsquo; which are, in fact, simply functions which obey these simple rules.&lt;/p&gt;

&lt;h2 id="examples-of-the-simple-binding-rules"&gt;Examples of the simple binding rules&lt;/h2&gt;

&lt;p&gt;One thing I have not mentioned before is that, in CL, bindings are &lt;strong&gt;mutable&lt;/strong&gt;, which is another way of saying that CL supports assignment: assignment to variables is mutation of variable bindings. So, as a trivial example:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun maximum (list)
  (let ((max (first list)))
    (dolist (e (rest list) max)
      (when (&amp;gt; e max)
        (setf max e)))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is very easy to understand and does not depend on the binding rules in detail.&lt;/p&gt;

&lt;p&gt;But, well, bindings are mutable, so the rules which say they exist as long as they can be referred to also imply they can be mutated as long as they can be referred to: anything else would certainly not be simple. So here&amp;rsquo;s a classic example of this:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun make-incrementor (&amp;amp;optional (value 0))
  (lambda (&amp;amp;optional (increment 1))
    (prog1 value
      (incf value increment))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (let ((i (make-incrementor)))
    (print (funcall i))
    (print (funcall i))
    (print (funcall i -2))
    (print (funcall i))
    (print (funcall i))
    (values))

0
1
2
0
1&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see, the function returned by &lt;code&gt;make-incrementor&lt;/code&gt; is mutating the binding that it can still see.&lt;/p&gt;

&lt;p&gt;What happens when two functions can see the same binding?&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun make-inc-dec (&amp;amp;optional (value 0))
  (values
   (lambda ()
     (prog1 value
       (incf value)))
   (lambda ()
     (prog1 value
       (decf value)))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (multiple-value-bind (inc dec) (make-inc-dec)
    (print (funcall inc))
    (print (funcall inc))
    (print (funcall dec))
    (print (funcall dec))
    (print (funcall inc))
    (values))

0
1
2
1
0&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Again, what happens is the simplest thing: you can see simply from reading the code that both functions can see the &lt;em&gt;same&lt;/em&gt; binding of &lt;code&gt;value&lt;/code&gt; and they are therefore both mutating this common binding.&lt;/p&gt;

&lt;p&gt;Here is an example which demonstrates all these features: an implementation of a simple queue as a pair of functions which can see two shared bindings:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun make-queue ()
  (let ((head '())
        (tail nil))
    (values
     (lambda (thing)
       ;; Push thing onto the queue
       (if (null head)
           ;; It's empty currently so set it up
           (setf head (list thing)
                 tail head)
         ;; not empty: just adjust the tail
         (setf (cdr tail) (list thing)
               tail (cdr tail)))
       thing)
     (lambda ()
       (cond
        ((null head)
         ;; empty
         (values nil nil))
        ((null (cdr head))
         ;; will be empty: don't actually need this case but it is
         ;; cleaner
         (values (prog1 (car head)
                   (setf head '()
                         tail nil))
                 t))
        (t
         ;; will still have content
         (values (pop head) t)))))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;make-queue&lt;/code&gt; will return two functions:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;the first takes one argument which it appends to the queue;&lt;/li&gt;
 &lt;li&gt;the second takes no argument and either the next element of the queue and &lt;code&gt;t&lt;/code&gt; or &lt;code&gt;nil&lt;/code&gt; and &lt;code&gt;nil&lt;/code&gt; if the queue is empty.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;So, with this little function to drain the queue&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun drain-and-print (popper)
  (multiple-value-bind (value fullp) (funcall popper)
    (when fullp
      (print value)
      (drain-and-print popper))
    (values)))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;we can see this in action&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (multiple-value-bind (pusher popper) (make-queue)
    (funcall pusher 1)
    (funcall pusher 2)
    (funcall pusher 3)
    (drain-and-print popper))

1
2
3&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="a-less-simple-kind-of-binding-which-is-sometimes-very-useful"&gt;A less-simple kind of binding which is sometimes very useful&lt;/h2&gt;

&lt;p&gt;Requiring bindings to be simple usually makes programs easy to read and understand. But it also makes it hard to do some things. One of those things is to control the &amp;lsquo;ambient state&amp;rsquo; of a program. A simple example would be the base for printing numbers. It&amp;rsquo;s quite natural to say that &amp;lsquo;in this region of the program I want numbers printed in hex&amp;rsquo;.&lt;/p&gt;

&lt;p&gt;If all we had was lexical binding then this becomes a nightmare: every function you call in the region you want to cause printing to happen in hex needs to take some extra argument which says &amp;lsquo;print in hex&amp;rsquo;. And if you then decide that, well, you&amp;rsquo;d also like some other ambient parameter, you need to provide more arguments to every function&lt;sup&gt;&lt;a href="#2023-02-22-how-to-understand-closures-in-common-lisp-footnote-5-definition" name="2023-02-22-how-to-understand-closures-in-common-lisp-footnote-5-return"&gt;5&lt;/a&gt;&lt;/sup&gt;. This is just horrible.&lt;/p&gt;

&lt;p&gt;You might think you can do this with global variables which you temporarily set: that is both fiddly (better make sure you set it back) and problematic in the presence of multiple threads&lt;sup&gt;&lt;a href="#2023-02-22-how-to-understand-closures-in-common-lisp-footnote-6-definition" name="2023-02-22-how-to-understand-closures-in-common-lisp-footnote-6-return"&gt;6&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;A better approach is to allow &lt;strong&gt;dynamic bindings&lt;/strong&gt;: bindings with indefinite scope &amp;amp; dynamic extent. CL has these, and at this point history becomes unavoidable: rather than have some separate construct for dynamic bindings, CL simply says that some variable bindings, and some references to variable bindings, are to be treated as having indefinite scope and dynamic extent, and you tell the system which bindings this applies to with&lt;code&gt;special&lt;/code&gt; declarations / proclamations. CL does this because that&amp;rsquo;s very close to how various predecessor Lisps worked, and so makes porting programs from them to CL much easier. To make this less painful there is a convention that dynamically-bound variable names have &lt;code&gt;*&lt;/code&gt;stars&lt;code&gt;*&lt;/code&gt; around them, of course.&lt;/p&gt;

&lt;p&gt;Dynamic bindings are so useful that if you don&amp;rsquo;t have them you really need to invent them: I have on at least two occasions implemented a dynamic binding system in Python, for instance.&lt;/p&gt;

&lt;p&gt;However this is not an article on dynamic bindings so I will not write more about them here: perhaps I will write another article later.&lt;/p&gt;

&lt;h2 id="what-else-can-be-bound"&gt;What else can be bound?&lt;/h2&gt;

&lt;p&gt;Variable bindings are by far the most common kind. But not the only kind. Other things can be bound. Here is a partial list&lt;sup&gt;&lt;a href="#2023-02-22-how-to-understand-closures-in-common-lisp-footnote-7-definition" name="2023-02-22-how-to-understand-closures-in-common-lisp-footnote-7-return"&gt;7&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;strong&gt;local functions&lt;/strong&gt; have lexical scope and indefinite extent;&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;block names&lt;/strong&gt; have lexical scope and definite extent (see below);&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;tag names&lt;/strong&gt; have lexical scope and definite extent (see below);&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;catch tags&lt;/strong&gt; have indefinite scope and definite extent;&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;condition handlers&lt;/strong&gt; have indefinite scope and definite extent;&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;restarts&lt;/strong&gt; have indefinite scope and definite extent.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;The two interesting cases here are block names and tag names. Both of these have lexical scope but only definite extent. As I argued above this makes it hard to know whether references to them are valid or not. Look at this, for example:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun outer (x)
  (inner (lambda (r)
           (return-from outer r))
         x))

(defun inner (r rp)
  (if rp
      r
    (funcall r #'identity)))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So then &lt;code&gt;(funcall (outer nil) 1)&lt;/code&gt; will: call &lt;code&gt;inner&lt;/code&gt; with a function which wants to return from &lt;code&gt;outer&lt;/code&gt; and &lt;code&gt;nil&lt;/code&gt;, which will cause &lt;code&gt;inner&lt;/code&gt; to call that function, returning the &lt;code&gt;identity&lt;/code&gt; function, which is then called by &lt;code&gt;funcall&lt;/code&gt; with argument &lt;code&gt;1&lt;/code&gt;: the result is 1.&lt;/p&gt;

&lt;p&gt;But &lt;code&gt;(funcall (outer t) 1)&lt;/code&gt; will instead return the function which wants to return from &lt;code&gt;outer&lt;/code&gt;, which is then called by &lt;code&gt;funcall&lt;/code&gt; which is an error since it is outside the dynamic extent of the call to &lt;code&gt;outer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And there is no way that either a human reading the code &lt;em&gt;or the compiler&lt;/em&gt; can detect that this is going to happen: a very smart compiler might perhaps be able to deduce that the internal function &lt;em&gt;might&lt;/em&gt; be returned from &lt;code&gt;outer&lt;/code&gt;, but probably only because this is a rather simple case: for instance in&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defun nasty (f)
  (funcall f (lambda ()
               (return-from nasty t))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;the situation is just hopeless. So this is a case where the binding rules are not as simple as you might like.&lt;/p&gt;

&lt;h2 id="what-is-simple"&gt;What is simple?&lt;/h2&gt;

&lt;p&gt;For variable bindings I think it&amp;rsquo;s easy to see that the simplest rule for a person reading the code is lexical binding. The other question is whether that is simpler &lt;em&gt;for the implementation&lt;/em&gt;. And the answer is that probably it is not: probably lexical scope and definite extent is the simplest implementationally. That certainly approximates what many old Lisps did&lt;sup&gt;&lt;a href="#2023-02-22-how-to-understand-closures-in-common-lisp-footnote-8-definition" name="2023-02-22-how-to-understand-closures-in-common-lisp-footnote-8-return"&gt;8&lt;/a&gt;&lt;/sup&gt;. It&amp;rsquo;s fairly easy to write a &lt;em&gt;bad&lt;/em&gt; implementation of lexical binding, simply by having all functions retain all the bindings, regardless of whether they might refer to them. A &lt;em&gt;good&lt;/em&gt; implementation requires more work. But CL&amp;rsquo;s approach here is that doing the right thing &lt;em&gt;for people&lt;/em&gt; is more important than making the implementor&amp;rsquo;s job easier. And I think that approach has worked well.&lt;/p&gt;

&lt;p&gt;On the other hand CL hasn&amp;rsquo;t done the right thing for blocks and tags: There are at least three reasons for this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementational complexity.&lt;/strong&gt; If the bindings had lexical scope and &lt;em&gt;indefinite&lt;/em&gt; extent then you would need to be able to return from a block which had already been returned from, and go to a tag from outside the extent of the form that established it. That opens an enormous can of worms both in making such an implementation work at all but also handling things like dynamic bindings, open files and so on. That&amp;rsquo;s not something the CL designers were willing to impose on implementors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Complexity in the specification.&lt;/strong&gt; If CL had lexical bindings for blocks and tags then the specification of the language would need to describe what happens in all the many edge cases that arise, including cases where it is genuinely unclear what the correct thing to do is at all such as dealing with open files and so on. Nobody wanted to deal with that, I&amp;rsquo;m sure: the language specification was already seen as far too big and the effort involved would have made it bigger, later and more expensive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conceptual difficulty.&lt;/strong&gt; It might seem that making block bindings work like lexical variable bindings would make things simpler to understand. Well, that&amp;rsquo;s exactly what Scheme did with &lt;code&gt;call/cc&lt;/code&gt; and &lt;code&gt;call/cc&lt;/code&gt; can give rise to some of the most opaque code I have ever seen. It is often very &lt;em&gt;pretty&lt;/em&gt; code, but it&amp;rsquo;s not easy to understand.&lt;/p&gt;

&lt;p&gt;I think the bargain that CL has struck here is at least reasonable: to make the common case of variable bindings simple for people, and to avoid the cases where doing the right thing results in a language which is harder to understand in many cases and far harder to implement and specify.&lt;/p&gt;

&lt;p&gt;Finally, once again I think that the best way to understand how closures in CL is not to understand them: instead understand the binding rules for variables, why they are simple and what they imply.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class="footnotes"&gt;
 &lt;ol&gt;
  &lt;li id="2023-02-22-how-to-understand-closures-in-common-lisp-footnote-1-definition" class="footnote-definition"&gt;
   &lt;p&gt;indefinite scope is often called &amp;lsquo;dynamic scope&amp;rsquo; although I will avoid this term as it is used by the standard to mean the combination of indefinite scope and dynamic extent.&amp;nbsp;&lt;a href="#2023-02-22-how-to-understand-closures-in-common-lisp-footnote-1-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2023-02-22-how-to-understand-closures-in-common-lisp-footnote-2-definition" class="footnote-definition"&gt;
   &lt;p&gt;Dynamic extent could perhaps be called &amp;lsquo;definite extent&amp;rsquo;, but this is not the term that the standard uses so I will avoid it.&amp;nbsp;&lt;a href="#2023-02-22-how-to-understand-closures-in-common-lisp-footnote-2-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2023-02-22-how-to-understand-closures-in-common-lisp-footnote-3-definition" class="footnote-definition"&gt;
   &lt;p&gt;Here and below I am using the term &amp;lsquo;function&amp;rsquo; in the very loose sense that CL usually uses it: almost none of the &amp;lsquo;functions&amp;rsquo; I will talk about are actually mathematical functions: they&amp;rsquo;re what Scheme would call &amp;lsquo;procedures&amp;rsquo;.&amp;nbsp;&lt;a href="#2023-02-22-how-to-understand-closures-in-common-lisp-footnote-3-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2023-02-22-how-to-understand-closures-in-common-lisp-footnote-4-definition" class="footnote-definition"&gt;
   &lt;p&gt;For languages which &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; have first-class functions or equivalent constructs, lexical scope and definite extent is the same as lexical scope and indefinite extent, because it is not possible to return objects which can refer to bindings from the place those bindings were created.&amp;nbsp;&lt;a href="#2023-02-22-how-to-understand-closures-in-common-lisp-footnote-4-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2023-02-22-how-to-understand-closures-in-common-lisp-footnote-5-definition" class="footnote-definition"&gt;
   &lt;p&gt;More likely, you would end up making every function have, for instance an &lt;code&gt;ambient&lt;/code&gt; keyword argument whose value would be an alist or plist which mapped between properties of the ambient environment and values for them. All functions which might call other functions would need this extra argument, and would need to be sure to pass it down suitably.&amp;nbsp;&lt;a href="#2023-02-22-how-to-understand-closures-in-common-lisp-footnote-5-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2023-02-22-how-to-understand-closures-in-common-lisp-footnote-6-definition" class="footnote-definition"&gt;
   &lt;p&gt;This can be worked around, but it&amp;rsquo;s not simple to do so.&amp;nbsp;&lt;a href="#2023-02-22-how-to-understand-closures-in-common-lisp-footnote-6-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2023-02-22-how-to-understand-closures-in-common-lisp-footnote-7-definition" class="footnote-definition"&gt;
   &lt;p&gt;In other words &amp;lsquo;this is all I can think of right now, but there are probably others&amp;rsquo;.&amp;nbsp;&lt;a href="#2023-02-22-how-to-understand-closures-in-common-lisp-footnote-7-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2023-02-22-how-to-understand-closures-in-common-lisp-footnote-8-definition" class="footnote-definition"&gt;
   &lt;p&gt;Very often old Lisps had indefinite scope and definite extent in interpreted code but lexical scope and definite extent in compiled code: yes, compiled code behaved differently to interpreted code, and yes, that sucked.&amp;nbsp;&lt;a href="#2023-02-22-how-to-understand-closures-in-common-lisp-footnote-8-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content></entry>
 <entry>
  <title type="text">A case-like macro for regular expressions</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2023/01/11/a-case-like-macro-for-regular-expressions/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2023-01-11-a-case-like-macro-for-regular-expressions</id>
  <published>2023-01-11T18:17:29Z</published>
  <updated>2023-01-11T18:17:29Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;I often find myself wanting a simple &lt;code&gt;case&lt;/code&gt;-like macro where the keys are regular expressions. &lt;code&gt;regex-case&lt;/code&gt; is an attempt at this.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;I use &lt;a href="https://edicl.github.io/cl-ppcre/"&gt;CL-PPCRE&lt;/a&gt; for the usual things regular expressions are useful for, and probably for some of the things they should not really be used for as well. I often find myself wanting a &lt;code&gt;case&lt;/code&gt; like macro, where the keys are regular expressions. There is a contributed package for &lt;a href="https://github.com/guicho271828/trivia"&gt;Trivia&lt;/a&gt; which will do this, but Trivia is pretty overwhelming. So I gave in and wrote &lt;code&gt;regex-case&lt;/code&gt; which does what I want.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;regex-case&lt;/code&gt; is a &lt;code&gt;case&lt;/code&gt;-like macro. It looks like&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(regex-case &amp;lt;thing&amp;gt;
  (&amp;lt;pattern&amp;gt; (...)
   &amp;lt;form&amp;gt; ...)
  ...
  (otherwise ()
   &amp;lt;form&amp;gt; ...))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here &lt;code&gt;&amp;lt;pattern&amp;gt;&lt;/code&gt; is a literal regular expression, either a string or in CL-PPCRE&amp;rsquo;s s-expression parse-tree syntax for them. Unlike &lt;code&gt;case&lt;/code&gt; there can only be a single pattern per clause: allowing the parse-tree syntax makes it hard to do anything else. &lt;code&gt;otherwise&lt;/code&gt; (which can also be &lt;code&gt;t&lt;/code&gt;) is optional but must be last.&lt;/p&gt;

&lt;p&gt;The second form in a clause specifies what, if any, variables to bind on a match. As an example&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(regex-case line
  ("fog\\s+(.*)\\s$" (:match m :registers (v))
    ...)
  ...)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;will bind &lt;code&gt;m&lt;/code&gt; to the whole match and &lt;code&gt;v&lt;/code&gt; to the substring corresponding to the first register. You can also bind match and register positions. A nice (perhaps) thing is that you can &lt;em&gt;not&lt;/em&gt; bind some register variables:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(regex-case line
  (... (:registers (_ _ v))
   ...)
  ...)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;will bind &lt;code&gt;v&lt;/code&gt; to the substring corresponding to the third register. You can use &lt;code&gt;nil&lt;/code&gt; instead of &lt;code&gt;_&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The current state of &lt;code&gt;regex-case&lt;/code&gt; is a bit preliminary: in particular I don&amp;rsquo;t like the syntax for binding thngs very much, although I can&amp;rsquo;t think of a better one. Currently therefore it&amp;rsquo;s in my collection of toys: it will probably migrate from there at some point.&lt;/p&gt;

&lt;p&gt;Currently documentation is &lt;a href="https://tfeb.github.io/tfeb-lisp-toys/#case-for-regular-expressions-regex-case"&gt;here&lt;/a&gt; and source code is &lt;a href="https://github.com/tfeb/tfeb-lisp-toys"&gt;here&lt;/a&gt;.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Package-local nicknames</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2022/10/14/package-local-nicknames/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2022-10-14-package-local-nicknames</id>
  <published>2022-10-14T09:26:31Z</published>
  <updated>2022-10-14T09:26:31Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;What follows is an opinion. Do not under any circumstances read it. Other opinions are available (but wrong).&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;Package-local nicknames are an abomination. They should be burned with nuclear fire, and their ashes launched into space on a trajectory which will leave the Solar System.&lt;/p&gt;

&lt;p&gt;The only reason why package-local nicknames matter is if you are writing a lot of code with lots of package-qualified names in it. If you are doing that then &lt;em&gt;you are writing code which is hard to read&lt;/em&gt;: the names in your code are longer than they need to be and the first several characters of them are package name noise (people read, broadly from left to right). Imagine me:a la:version ge:of oe:English oe:where la:people wrote like that: it&amp;rsquo;s just horrible. If you are writing code which is hard to read you are writing bad code.&lt;/p&gt;

&lt;p&gt;Instead you should do the work to construct a namespace in which the words you intend to use are directly present. This means constructing suitable packages: the files containing the package definitions are then almost the only place where package names occur, and are a minute fraction of the total code. Doing this is a good practice in itself because the package definition file is then a place which describes just what names your code needs, from where, and what names it provides. Things like conduit packages (shameless self-promotion) can help with this, which is why I wrote them: being able to say &amp;lsquo;this package exports the combination of the exports of these packages, except &amp;hellip;&amp;rsquo; or &amp;lsquo;this package exports just the following symbols from these packages&amp;rsquo; in an explicit way is very useful.&lt;/p&gt;

&lt;p&gt;If you are now rehearsing a litany of things that can go wrong with this approach in rare cases&lt;sup&gt;&lt;a href="#2022-10-14-package-local-nicknames-footnote-1-definition" name="2022-10-14-package-local-nicknames-footnote-1-return"&gt;1&lt;/a&gt;&lt;/sup&gt;, please don&amp;rsquo;t: this is not my first rodeo and, trust me, I know about these cases. Occasionally, the CL package system can make it hard or impossible to construct the namespace you need, with the key term here being being &lt;em&gt;occasionally&lt;/em&gt;: people who give up because something is occasionally hard or impossible have what Erik Naggum famously called &amp;lsquo;one-bit brains&amp;rsquo;&lt;sup&gt;&lt;a href="#2022-10-14-package-local-nicknames-footnote-2-definition" name="2022-10-14-package-local-nicknames-footnote-2-return"&gt;2&lt;/a&gt;&lt;/sup&gt;: the answer is to &lt;em&gt;get more bits for your brain&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Once you write code like this then the only place package-local nicknames can matter is, perhaps, the package definition file. And the only reason they can matter there is because people think that picking a name like &amp;lsquo;XML&amp;rsquo; or &amp;lsquo;RPC&amp;rsquo; or &amp;lsquo;SQL&amp;rsquo; for their packages is a good idea. When people in the programming section of my hollowed-out-volcano lair do this they are &amp;hellip; well, I will not say, but my sharks are well-fed and those things on spikes surrounding the crater are indeed their heads.&lt;/p&gt;

&lt;p&gt;People should use long, unique names for packages. Java, astonishingly, got this right: use domains in big-endian order (&lt;code&gt;org.tfeb.conduit-packages&lt;/code&gt;, &lt;code&gt;org.tfeb.hax.metatronic&lt;/code&gt;). Do not use short nicknames. Never use names without at least one dot, which should be reserved for implementations and perhaps KMP-style substandards. Names will now not clash. Names will be longer and require more typing, but this will not matter because the only place package names are referred to are in package definition files and in &lt;code&gt;in-package&lt;/code&gt; forms, which are a minute fraction of your code.&lt;/p&gt;

&lt;p&gt;I have no idea where or when the awful plague of using package-qualified names in code arose: it&amp;rsquo;s not something people used to do, but it seems to happen really a lot now. I think it may be because people also tend to do this in Python and other dotty languages, although, significantly, in Python you never actually need to do this if you bother, once again, to actually go to the work of constructing the namespace you want: rather than the awful&lt;/p&gt;

&lt;pre class="brush: python"&gt;&lt;code&gt;import sys

... sys.argv ...

...

sys.exit(...)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;you can simply say&lt;/p&gt;

&lt;pre class="brush: python"&gt;&lt;code&gt;from sys import argv, exit

... argv ...

exit(...)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and now the very top of your module lets anyone reading it know exactly what functionality you are importing and from where it comes.&lt;/p&gt;

&lt;p&gt;It may also be because the whole constructing namespaces thing is a bit hard. Yes, it is indeed a bit hard, but designing programs, of which it is a small but critical part, &lt;em&gt;is&lt;/em&gt; a bit hard.&lt;/p&gt;

&lt;p&gt;OK, enough.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;If, after reading the above, you think you should mail me about how wrong it all is and explain some detail of the CL package system to me: don&amp;rsquo;t, I do not want to hear from you. Really, I don&amp;rsquo;t.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class="footnotes"&gt;
 &lt;ol&gt;
  &lt;li id="2022-10-14-package-local-nicknames-footnote-1-definition" class="footnote-definition"&gt;
   &lt;p&gt;in particular, if your argument is that someone has used, for instance, the name &lt;code&gt;set&lt;/code&gt; in some package to mean, for instance, a set in the sense it is used in maths, and that this clashes with &lt;code&gt;cl:set&lt;/code&gt; and perhaps some other packages, don&amp;rsquo;t. If you are writing a program and you think, &amp;lsquo;I know, I&amp;rsquo;ll use a symbol with the same name as a symbol exported from CL to mean something else&amp;rsquo; in a context where users of your code also might want to use the symbol exported by CL (which in the case of &lt;code&gt;cl:set&lt;/code&gt; is &amp;lsquo;almost never&amp;rsquo;, of course), then my shark pool is just over here: please throw yourself in.&amp;nbsp;&lt;a href="#2022-10-14-package-local-nicknames-footnote-1-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2022-10-14-package-local-nicknames-footnote-2-definition" class="footnote-definition"&gt;
   &lt;p&gt;Curiously, I think that quote was about Scheme, which I am sure Erik hated. But, for instance, Racket&amp;rsquo;s module system lets you do just the things which are hard in the package system: renaming things on import, for instance.&amp;nbsp;&lt;a href="#2022-10-14-package-local-nicknames-footnote-2-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content></entry>
 <entry>
  <title type="text">Bradshaw's laws</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2022/10/03/bradshaw-s-laws/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2022-10-03-bradshaw-s-laws</id>
  <published>2022-10-03T19:50:51Z</published>
  <updated>2022-10-03T19:50:51Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;There are two laws.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h2 id="the-laws"&gt;The laws&lt;/h2&gt;

&lt;ol&gt;
 &lt;li&gt;&lt;strong&gt;Bradshaw&amp;rsquo;s law.&lt;/strong&gt; All sufficiently large software systems end up being programming languages.&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;Zyni&amp;rsquo;s corollary.&lt;/strong&gt; Whenever you think the point is at which the first law will apply, it will apply before that.&lt;/li&gt;&lt;/ol&gt;

&lt;h2 id="implications-of-the-laws"&gt;Implications of the laws&lt;/h2&gt;

&lt;p&gt;When building software systems you should design them as programming langages. You should do this however small you think they will be. In order to make this practical for small systems you should therefore use a language which allows seamless extension into other languages with insignificant zero-point cost.&lt;/p&gt;

&lt;p&gt;But because the laws are not widely known, most large software systems are built without understanding that what is being built is in fact a programming language. Because people don&amp;rsquo;t know they are building a programming language, don&amp;rsquo;t know how to build programming languages, and do not use languages which make the seamless construction of programming languages easy, the languages they build are usually terrible: they are hard to use, have opaque and inconsistent semantics and are almost always insecure.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Simple logging in Common Lisp</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2022/09/26/simple-logging-in-common-lisp/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2022-09-26-simple-logging-in-common-lisp</id>
  <published>2022-09-26T11:26:32Z</published>
  <updated>2022-09-26T11:26:32Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;&lt;code&gt;slog&lt;/code&gt; is a simple logging framework for Common Lisp based on the observation that conditions can represent log events.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;&lt;code&gt;slog&lt;/code&gt; is based on an two observations about the Common Lisp condition system:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;conditions do not have to represent errors, or warnings, but can just be a way of a program saying &amp;lsquo;look, something interesting happened&amp;rsquo;;&lt;/li&gt;
 &lt;li&gt;handlers can decline to handle a condition, and in particular handlers are invoked &lt;em&gt;before the stack is unwound&lt;/em&gt;.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Well, saying &amp;lsquo;look, something interesting happened&amp;rsquo; is really quite similar to what logging systems do, and &lt;code&gt;slog&lt;/code&gt; is built on this idea.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;slog&lt;/code&gt; is the &lt;em&gt;simple&lt;/em&gt; logging system: it provides a framework on which logging can be built but does not itself provide a vast category of log severities &amp;amp;c. Such a thing could be built on top of &lt;code&gt;slog&lt;/code&gt;, which aims to provide mechanism, not policy.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;slog&lt;/code&gt; provides a couple of conditions representing log entries, which are designed to be subclassed in real life. Log entries are created using a &lt;code&gt;slog&lt;/code&gt; function (this is why &lt;code&gt;slog&lt;/code&gt; is called &lt;code&gt;slog&lt;/code&gt;: &lt;code&gt;log&lt;/code&gt; is already taken) which simply signals an appropriate condition. Handlers are set up by a &lt;code&gt;logging&lt;/code&gt; form (this should really be called &lt;code&gt;slogging&lt;/code&gt; but it is not), which associates conditions with handlers. There is fairly flexible file handling for logging to files, and in particular you can refer to file names which all get associated with the approprate stream, streams get closed automagically (and you can manually close them, when they will be reopened if need be), and the underlying mechanism for writing entries is exposed by a &lt;code&gt;slog-to&lt;/code&gt; generic function which could be extended. Log entry formats can be controlled in various ways.&lt;/p&gt;

&lt;p&gt;In addition &lt;code&gt;slog&lt;/code&gt; tries to associate log entries with &amp;lsquo;precision time&amp;rsquo;, which is CL&amp;rsquo;s universal time expanded to the precision of a millisecond, or of internal time if it is less precise than a millisecond. Setting this up means that &lt;code&gt;slog&lt;/code&gt; takes a second or so to load.&lt;/p&gt;

&lt;p&gt;Once again: &lt;code&gt;slog&lt;/code&gt; is a &lt;em&gt;framework&lt;/em&gt;: it has no dealings with log severities, catagories, or anything like that. All that is meant to be provided on top of what &lt;code&gt;slog&lt;/code&gt; provides.&lt;/p&gt;

&lt;p&gt;Documentation is &lt;a href="https://tfeb.github.io/tfeb-lisp-hax/#simple-logging-slog"&gt;here&lt;/a&gt;, source code is &lt;a href="https://github.com/tfeb/tfeb-lisp-hax"&gt;here&lt;/a&gt;. It will be available from Quicklisp in due course.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Metatronic macros</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2022/09/26/metatronic-macros/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2022-09-26-metatronic-macros</id>
  <published>2022-09-26T10:54:25Z</published>
  <updated>2022-09-26T10:54:25Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;Metatronic macros are a simple hack which makes it a little easier to write less unhygienic macros in Common Lisp.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;Common Lisp macros require you to avoid variable name capture yourself. So, for a macro which iterates over the lines in a file, this is wrong:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defmacro with-file-lines ((line file) &amp;amp;body forms)
  ;; wrong
  `(with-open-file (in ,file)
     (do ((,line (read-line in nil in)
                 (read-line in nil in)))
         ((eq ,line in))
       ,@forms)))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;rsquo;s wrong because it binds &lt;code&gt;in&lt;/code&gt; to the stream open to the file, and user code could perfectly legitimately refer to a variable of the same name.&lt;/p&gt;

&lt;p&gt;The standard approach to dealing with this is to use gensyms:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defmacro with-file-lines ((line file) &amp;amp;body forms)
  ;; righter
  (let ((inn (gensym)))
    `(with-open-file (,inn ,file)
     (do ((,line (read-line ,inn nil ,inn)
                 (read-line ,inn nil ,inn)))
         ((eq ,line inn))
       ,@forms))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This creates a new symbol bound to &lt;code&gt;inn&lt;/code&gt; (&lt;code&gt;in&lt;/code&gt;&amp;rsquo;s name), and then uses it as the name of the variable bound to the stream. Code can&amp;rsquo;t then use any variable with this unique name.&lt;/p&gt;

&lt;p&gt;This works, but it&amp;rsquo;s ugly. Metatronic macros let you write the above like this:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defmacro/m with-file-lines ((line file) &amp;amp;body forms)
  ;; righter, easier
  `(with-open-file (&amp;lt;in&amp;gt; ,file)
     (do ((,line (read-line &amp;lt;in&amp;gt; nil &amp;lt;in&amp;gt;)
                 (read-line &amp;lt;in&amp;gt; nil &amp;lt;in&amp;gt;)))
         ((eq ,line &amp;lt;in&amp;gt;))
       ,@forms)))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this macro all symbols which look like &lt;code&gt;&amp;lt;&lt;/code&gt;&amp;hellip;&lt;code&gt;&amp;gt;&lt;/code&gt; (in any package) are rewritten to unique names, but all references to symbols with the same original name are to the same symbol&lt;sup&gt;&lt;a href="#2022-09-26-metatronic-macros-footnote-1-definition" name="2022-09-26-metatronic-macros-footnote-1-return"&gt;1&lt;/a&gt;&lt;/sup&gt;. This makes this common case more pleasant to do: macros written using &lt;code&gt;defmacro/m&lt;/code&gt; have less noise around their expansion.&lt;/p&gt;

&lt;p&gt;Metatronic macros go to some lengths to avoid leaking the rewritten symbols. Given this silly macro&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defmacro/m silly ()
  ''&amp;lt;silly&amp;gt;)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;then &lt;code&gt;(eq (silly) (silly))&lt;/code&gt; is false. Similarly given this:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defmacro/m also-silly (f)
  `(eq ,f '&amp;lt;silly&amp;gt;))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then &lt;code&gt;(also-silly '&amp;lt;silly&amp;gt;)&lt;/code&gt; will be false of course.&lt;/p&gt;

&lt;p&gt;There is &lt;code&gt;defmacro/m&lt;/code&gt;, &lt;code&gt;macrolet/m&lt;/code&gt; and &lt;code&gt;define-compiler-macro/m&lt;/code&gt;, and the implementation of metatronization is exposed if you need it.&lt;/p&gt;

&lt;p&gt;Documentation is &lt;a href="https://tfeb.github.io/tfeb-lisp-hax/#metatronic-macros"&gt;here&lt;/a&gt;, source code is &lt;a href="https://github.com/tfeb/tfeb-lisp-hax"&gt;here&lt;/a&gt;. It will be available in Quicklisp in due course.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class="footnotes"&gt;
 &lt;ol&gt;
  &lt;li id="2022-09-26-metatronic-macros-footnote-1-definition" class="footnote-definition"&gt;
   &lt;p&gt;in fact, a symbol whose name is &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt; is rewritten as a unique gensym as a special case. I am not sure if this is a good thing but it&amp;rsquo;s what happens.&amp;nbsp;&lt;a href="#2022-09-26-metatronic-macros-footnote-1-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content></entry>
 <entry>
  <title type="text">Two simple pattern matchers for Common Lisp</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2022/07/21/two-simple-pattern-matchers-for-common-lisp/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2022-07-21-two-simple-pattern-matchers-for-common-lisp</id>
  <published>2022-07-21T09:17:45Z</published>
  <updated>2022-07-21T09:17:45Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;I&amp;rsquo;ve written two pattern matchers for Common Lisp:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;code&gt;destructuring-match&lt;/code&gt;, or &lt;code&gt;dsm&lt;/code&gt;, is a &lt;code&gt;case&lt;/code&gt;-style construct which can match &lt;code&gt;destructuring-bind&lt;/code&gt;-style lambda lists with a couple of extensions;&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;spam&lt;/code&gt;, the simple pattern matcher, does not bind variables but lets you match based on assertions about, for instance, the contents of lists.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Both &lt;code&gt;dsm&lt;/code&gt; and &lt;code&gt;spam&lt;/code&gt; strive to be simple and correct.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h2 id="simplicity"&gt;Simplicity&lt;/h2&gt;

&lt;p&gt;Both &lt;code&gt;dsm&lt;/code&gt; and &lt;code&gt;spam&lt;/code&gt; are &lt;em&gt;simple&lt;/em&gt;: they do exactly one thing, and try to do that one thing well.&lt;/p&gt;

&lt;p&gt;You could think of &lt;code&gt;dsm&lt;/code&gt; as being to some other CL pattern matchers as Unix once was to Multics: &lt;code&gt;dsm&lt;/code&gt; is the result of me looking at those other systems and thinking &amp;lsquo;please, not that&amp;rsquo;.&lt;/p&gt;

&lt;p&gt;Those systems are vast, have several levels, and are extensible: some subset of them might do what I wanted to be able to do &amp;mdash; make writing macros less unpleasant &amp;mdash; but I&amp;rsquo;m not sure&lt;sup&gt;&lt;a href="#2022-07-21-two-simple-pattern-matchers-for-common-lisp-footnote-1-definition" name="2022-07-21-two-simple-pattern-matchers-for-common-lisp-footnote-1-return"&gt;1&lt;/a&gt;&lt;/sup&gt;. They are obsessed with performance.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dsm&lt;/code&gt; does one thing, and exports a single macro. If you know how to use &lt;code&gt;destructuring-bind&lt;/code&gt; and &lt;code&gt;case&lt;/code&gt; you already know almost all there is to know about &lt;code&gt;dsm&lt;/code&gt;: it&amp;rsquo;s a &lt;code&gt;case&lt;/code&gt; construct whose cases are &lt;code&gt;destructuring-bind&lt;/code&gt; lambda lists. &lt;code&gt;dsm&lt;/code&gt; doesn&amp;rsquo;t care about performance at all, because macroexpansion performance never matters.&lt;/p&gt;

&lt;p&gt;At least one of those matchers has almost as many commits in its repo as dsm has lines of code.&lt;/p&gt;

&lt;p&gt;Like Multics was, those hairy pattern matchers are fine systems. But there was a good reason that Thompson and Ritchie wrote something very different&lt;sup&gt;&lt;a href="#2022-07-21-two-simple-pattern-matchers-for-common-lisp-footnote-2-definition" name="2022-07-21-two-simple-pattern-matchers-for-common-lisp-footnote-2-return"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h2 id="destructuring-match--dsm"&gt;&lt;code&gt;destructuring-match&lt;/code&gt; / &lt;code&gt;dsm&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;in CL &lt;code&gt;destructuring-bind&lt;/code&gt; and, mostly equivalently, macro argument lists are both a blessing and a curse. They&amp;rsquo;re a blessing because they support destructuring, so you can write, for instance&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defmacro with-foo ((var &amp;amp;optional init) &amp;amp;body forms)
  ...)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;They&amp;rsquo;re a curse because they are so fragile: &lt;code&gt;with-foo&lt;/code&gt; can &lt;em&gt;only&lt;/em&gt; support that syntax and will fail with an ugly error message from the implementation when it is fed anything else.&lt;/p&gt;

&lt;p&gt;Writing robust macros in CL, especially macros which expect various different argument patterns, then turns into a great saga of manually checking argument patterns before using &lt;code&gt;destructuring-bind&lt;/code&gt; to actually bind things. The result of that, of course, is that very many CL macros are not robust and have terrible error reporting.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;destructuring-match&lt;/code&gt; does away with all this unpleasentness. It supports a slightly extended version of the lambda lists that &lt;code&gt;destructuring-bind&lt;/code&gt; supports, has &amp;lsquo;guard&amp;rsquo; clauses which allow additional checks, and will match a form against any number of lambda lists until one matches, with a fallback case.&lt;/p&gt;

&lt;p&gt;As an example here is a version of &lt;code&gt;with-foo&lt;/code&gt; which allows two patterns:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defmacro with-foo (&amp;amp;body forms)
  (destructuring-match forms
    (((var &amp;amp;optional init) &amp;amp;body body)
     (:when (symbolp var))
     ...)
    ((((var &amp;amp;optional type) &amp;amp;optional init) &amp;amp;body body)
     (:when (symbolp var))
     ...)
    (otherwise
     (error ...))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The guard clauses check that &lt;code&gt;var&lt;/code&gt; is a symbol before the match succeeds, and will therefore ensure that the second match is the one chosen for &lt;code&gt;(with-foo ((x y) 1) ...)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;destructuring-match&lt;/code&gt; also supports &amp;lsquo;blank&amp;rsquo; variables: any variable whose name is &lt;code&gt;_&lt;/code&gt; (in any package) is ignored, and all such variables are distinct. So for instance&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(destructuring-match l
  ((_ _ _) ...))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;will match if &lt;code&gt;l&lt;/code&gt; is a proper list with exactly three elements.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;destructuring-match&lt;/code&gt; it&amp;rsquo;s easy to write this macro&lt;sup&gt;&lt;a href="#2022-07-21-two-simple-pattern-matchers-for-common-lisp-footnote-3-definition" name="2022-07-21-two-simple-pattern-matchers-for-common-lisp-footnote-3-return"&gt;3&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defmacro define-matching-macro (name &amp;amp;body clauses)
  (let ((&amp;lt;whole&amp;gt; (make-symbol "WHOLE"))
        (&amp;lt;junk&amp;gt; (make-symbol "JUNK")))
    (destructuring-match clauses
      ((doc . the-clauses)
       (:when (stringp doc))
       `(defmacro ,name (&amp;amp;whole ,&amp;lt;whole&amp;gt; &amp;amp;rest ,&amp;lt;junk&amp;gt;)
          ,doc
          (destructuring-match ,&amp;lt;whole&amp;gt; ,@the-clauses)))
      (the-clauses
       `(defmacro ,name (&amp;amp;whole ,&amp;lt;whole&amp;gt; &amp;amp;rest ,&amp;lt;junk&amp;gt;)
          (destructuring-match ,&amp;lt;whole&amp;gt; ,@the-clauses))))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And this then allows the above &lt;code&gt;with-foo&lt;/code&gt; macro to be written like this:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(define-matching-macro with-foo
  ((_ (var &amp;amp;optional init) &amp;amp;body forms)
   (:when (symbolp var))
   ...)
  ((_ ((var &amp;amp;optional type) &amp;amp;optional init) &amp;amp;body forms)
   (:when (symbolp var))
   ...)
  (form
   (error "~S is bad syntax for with-foo" form)))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;dsm&lt;/code&gt; was not written with performance in mind but it seems to be, typically, around a tenth to a half the speed of &lt;code&gt;destructuring-bind&lt;/code&gt; while being far more powerful of course.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dsm&lt;/code&gt; can be found &lt;a href="https://tfeb.github.io/#destructuring-match-for-common-lisp"&gt;here&lt;/a&gt;. It will probably end up in Quicklisp in due course but currently it isn&amp;rsquo;t there, and some of its dependencies are also not up to date there.&lt;/p&gt;

&lt;h2 id="spam-the-simple-pattern-matcher"&gt;&lt;code&gt;spam&lt;/code&gt;, the simple pattern matcher&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;dsm&lt;/code&gt; has a lot of cases where it needs to check what the lambda list it is parsing and compiling looks like. To do this I wrote a bunch of predicate constructors and combinators, which return predicates which will check things. So for example:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;code&gt;(is 'foo)&lt;/code&gt; returns a function which checks its argument is &lt;code&gt;eql&lt;/code&gt; to &lt;code&gt;foo&lt;/code&gt;;&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;(some-of p1 ... pn)&lt;/code&gt; returns a function of one argument which will succeed if one of the predicates which are its arguments succeeds, so &lt;code&gt;(some-of (is 'foo) (is 'bar))&lt;/code&gt;;&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;(head-matches p1 ... pn)&lt;/code&gt; will succeed if the predicates which are its arguments succeed on the first elements of a list.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;There are several other predicate constructrors and predicate combinators, but &lt;code&gt;spam&lt;/code&gt; can use any predicate.&lt;/p&gt;

&lt;p&gt;There is then a &lt;code&gt;matches&lt;/code&gt; macro which uses these to match things, and a &lt;code&gt;matchp&lt;/code&gt; function which simply invokes a predicate.&lt;/p&gt;

&lt;p&gt;As an example, here&amp;rsquo;s part of a matcher for &lt;code&gt;&amp;amp;rest&lt;/code&gt; specifications in lambda lists.&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(matching ll
  ((head-matches (some-of (is '&amp;amp;rest) (is '&amp;amp;body))
                 (var)
                 (is '&amp;amp;key))
   ;; &amp;amp;rest x &amp;amp;key ...
   ...)
   ((head-matches (some-of (is '&amp;amp;rest) (is '&amp;amp;body))
                  (var)
                  (any))
    ;; &amp;amp;rest x with something else
    ...)
   ((list-matches (some-of (is '&amp;amp;rest) (is '&amp;amp;body))
                  (var))
    ;; &amp;amp;rest x and no more
    ...)
   (otherwise
    (error "oops")))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;spam&lt;/code&gt; is pretty useful, and code written using it is much easier to read than doing the equivalent checks manually. It is used extensively in the implementation of &lt;code&gt;dsm&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;spam&lt;/code&gt; is now one of &lt;a href="https://tfeb.github.io/#some-common-lisp-hacks"&gt;my CL hax&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class="footnotes"&gt;
 &lt;ol&gt;
  &lt;li id="2022-07-21-two-simple-pattern-matchers-for-common-lisp-footnote-1-definition" class="footnote-definition"&gt;
   &lt;p&gt;At the time of writing &lt;a href="https://github.com/guicho271828/trivia"&gt;Trivia&lt;/a&gt; supports lambda lists I think, but not destructuring-lambda lists: &lt;code&gt;(match '(1 (1)) ((lambda-list a (b)) (values a b)))&lt;/code&gt; will fail, for instance. I don&amp;rsquo;t know whether is it &lt;em&gt;meant&lt;/em&gt; to support destructuring lambda lists &amp;mdash; comments in the sources imply it is, but it clearly does not in fact.&amp;nbsp;&lt;a href="#2022-07-21-two-simple-pattern-matchers-for-common-lisp-footnote-1-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2022-07-21-two-simple-pattern-matchers-for-common-lisp-footnote-2-definition" class="footnote-definition"&gt;
   &lt;p&gt;I am aware of &lt;a href="https://dreamsongs.com/WIB.html"&gt;Gabriel&amp;rsquo;s &amp;lsquo;worse is better&amp;rsquo; paper&lt;/a&gt; and its various afterthoughts. &lt;code&gt;dsm&lt;/code&gt; is not like that: it is smaller and simpler, but is not intended to be worse. &lt;code&gt;dsm&lt;/code&gt; is to these other systems perhaps as Scheme was to CL. Gabriel also talks about these two options, of course.&amp;nbsp;&lt;a href="#2022-07-21-two-simple-pattern-matchers-for-common-lisp-footnote-2-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2022-07-21-two-simple-pattern-matchers-for-common-lisp-footnote-3-definition" class="footnote-definition"&gt;
   &lt;p&gt;Note this macro is 12 lines, half of which are handling the possible docstring.&amp;nbsp;&lt;a href="#2022-07-21-two-simple-pattern-matchers-for-common-lisp-footnote-3-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content></entry>
 <entry>
  <title type="text">Macroexpansion in Common Lisp</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2022/07/05/macroexpansion-in-common-lisp/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2022-07-05-macroexpansion-in-common-lisp</id>
  <published>2022-07-05T15:16:29Z</published>
  <updated>2022-07-05T15:16:29Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;Yet another description of macroexpansion in Common Lisp. There is nothing particuarly new here and it partly duplicates some previous articles: I just wanted to rescue the text.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;The following description is of how macroexpansion works in Common Lisp&lt;sup&gt;&lt;a href="#2022-07-05-macroexpansion-in-common-lisp-footnote-1-definition" name="2022-07-05-macroexpansion-in-common-lisp-footnote-1-return"&gt;1&lt;/a&gt;&lt;/sup&gt;. It is slightly simplified and I have not always mentioned when it is&lt;sup&gt;&lt;a href="#2022-07-05-macroexpansion-in-common-lisp-footnote-2-definition" name="2022-07-05-macroexpansion-in-common-lisp-footnote-2-return"&gt;2&lt;/a&gt;&lt;/sup&gt;. It is at least a partial duplicate of &lt;a href="../../../../2021/11/11/the-proper-use-of-macros-in-lisp/"&gt;this previous article&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="what-macros-are"&gt;What macros are&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Macros in CL are functions, written in ordinary CL, whose argument is source code, and whose value is other source code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Source code is represented as s-expressions: symbols, conses, and so on. Macros don&amp;rsquo;t do string-rewriting.&lt;/p&gt;

&lt;p&gt;The way to think slightly more abstractly about macros is that they are &lt;em&gt;functions between languages&lt;/em&gt;: a macro is a function which takes as an argument fragments of a language which includes that macro, and returns as a value either a fragment of a language which &lt;em&gt;doesn&amp;rsquo;t&lt;/em&gt; include the macro, or a fragment of a language which includes it in some weaker way.&lt;/p&gt;

&lt;p&gt;The aim of macros is to build, on top of the language you are given, another language which is closer to the language in which you want to express your programs. CL itself is one such language, built-up using a number of standard macros on top of a substrate language.&lt;/p&gt;

&lt;p&gt;People often think of macros as &amp;lsquo;functions which do not evaluate their arguments&amp;rsquo;: that&amp;rsquo;s really not right. They are functions &amp;mdash; perfectly ordinary functions, written in CL &amp;mdash; but their argument is source code, and their value is source code.&lt;/p&gt;

&lt;h2 id="how-macroexpansion-happens"&gt;How macroexpansion happens&lt;/h2&gt;

&lt;p&gt;[This is simplified.]&lt;/p&gt;

&lt;p&gt;Given some initial compound form &lt;code&gt;(m ...)&lt;/code&gt;, macroexpansion proceeds like this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start.&lt;/strong&gt; Given a form, it should be one of&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;a compound form &lt;code&gt;(m ...)&lt;/code&gt;,&lt;/li&gt;
 &lt;li&gt;or a non-compound form.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Compound form.&lt;/strong&gt; The form is &lt;code&gt;(m ...)&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;Look at &lt;code&gt;m&lt;/code&gt;: if it has an associated macro function (found using &lt;code&gt;macro-function&lt;/code&gt;) then simply call that function on the whole form &lt;code&gt;(m ...)&lt;/code&gt;: its result is a new form&lt;sup&gt;&lt;a href="#2022-07-05-macroexpansion-in-common-lisp-footnote-3-definition" name="2022-07-05-macroexpansion-in-common-lisp-footnote-3-return"&gt;3&lt;/a&gt;&lt;/sup&gt;. Recurse on this form from &lt;strong&gt;Start&lt;/strong&gt;.&lt;/li&gt;
 &lt;li&gt;If &lt;code&gt;m&lt;/code&gt; is not a macro, then it may be a special operator, such as &lt;code&gt;setq&lt;/code&gt; or &lt;code&gt;if&lt;/code&gt;. Consider appropriate forms in the body of this form for expansion: which forms are known by the rules of the special operator. For instance all the forms in &lt;code&gt;(if ...)&lt;/code&gt; are considered for expansion, while in &lt;code&gt;(setq &amp;lt;x&amp;gt; &amp;lt;y&amp;gt;)&lt;/code&gt; only &lt;code&gt;&amp;lt;y&amp;gt;&lt;/code&gt; is, and so on.&lt;/li&gt;
 &lt;li&gt;If it is not a macro and not a special form, then &lt;code&gt;(m ...)&lt;/code&gt; is assumed to be a function call, with &lt;code&gt;m&lt;/code&gt; denoting a function. All the forms in the body are now considered for macro expansion. Once that is done the expansion process is complete.&lt;/li&gt;
 &lt;li&gt;As a special case of the last case, &lt;code&gt;m&lt;/code&gt; may be &lt;code&gt;(lambda (...) ...)&lt;/code&gt;, so the whole form will be &lt;code&gt;((lambda (...) ...) ...)&lt;/code&gt;. In this case the forms in the body of the &lt;code&gt;lambda&lt;/code&gt; are considered for macroexpansion; otherwise this is the same as the last case&lt;sup&gt;&lt;a href="#2022-07-05-macroexpansion-in-common-lisp-footnote-4-definition" name="2022-07-05-macroexpansion-in-common-lisp-footnote-4-return"&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
 &lt;li&gt;There are no other cases.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Non-compound form.&lt;/strong&gt; There is nothing to do here.&lt;/p&gt;

&lt;p&gt;As I said, this is simplified: there are local macros for instance, and various other things. However one critical thing is that when expanding some macro form &lt;code&gt;(m ...)&lt;/code&gt;, the expansion carries on until it gets something which is not a macro form &lt;em&gt;before&lt;/em&gt; looking at whatever is in the body of the form. That&amp;rsquo;s critical: although it&amp;rsquo;s tempting to think that expansion should happen inside-out, it can&amp;rsquo;t work that way, because until the outer macro has done its work you can&amp;rsquo;t know if the things in its body even &lt;em&gt;should&lt;/em&gt; be candidates for macro expansion. There&amp;rsquo;s an example of this below.&lt;/p&gt;

&lt;h2 id="macros-the-hard-way"&gt;Macros the hard way&lt;/h2&gt;

&lt;p&gt;OK, I said that macros were just functions, and I meant that. Let&amp;rsquo;s write a macro &lt;code&gt;with-debugging&lt;/code&gt; which is like &lt;code&gt;progn&lt;/code&gt; but it will perhaps print what it is doing.&lt;/p&gt;

&lt;p&gt;So let&amp;rsquo;s write the macro function:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defvar *debugging* t)

(defun expand-with-debugging (form environment)
  (declare (ignore environment))        ;I'm not mentioning environments
  `(progn
     ,@(loop for thing in (rest form)
             collect `(when *debugging*
                        (format *debug-io* "~&amp;amp;~S~%" ',thing))
             collect thing)))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And we can test it:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (expand-with-debugging '(with-debugging (cons 1 2) 4) nil)
(progn
  (when *debugging* (format *debug-io* "~&amp;amp;~S~%" '(cons 1 2)))
  (cons 1 2)
  (when *debugging* (format *debug-io* "~&amp;amp;~S~%" '4))
  4)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now we can install it as the macro function for &lt;code&gt;with-debugging&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(setf (macro-function 'with-debugging) #'expand-with-debugging)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; (with-debugging
   (cons 1 2)
   4)
(cons 1 2)
4
4&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; (setf *debugging* nil)
nil

&amp;gt; (with-debugging
   (cons 1 2)
   4)
4&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;OK, here&amp;rsquo;s another macro done this way, and purpose of this one is to show you why macroexpansion has to happen outside in. Let&amp;rsquo;s say we want to be able to denote functions by &lt;code&gt;(fun (arg ...) form ...)&lt;/code&gt;, but we&amp;rsquo;d like to be able to debug the body with &lt;code&gt;with-debugging&lt;/code&gt;. We can do that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(defun expand-fun (form environment)
  (declare (ignore environment))        ;still not mentioning environments
  `(function (lambda ,(second form)
               ;; Not dealing with declarations
               (with-debugging ,@(cddr form)))))

(setf (macro-function 'fun) #'expand-fun)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And now&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (let ((*debugging* t))
    (funcall (fun (a) (+ a a)) 1))
(+ a a)
2&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now you can see why the macro expander has to work the way it does: the first form in the body of &lt;code&gt;fun&lt;/code&gt; should not be macroexpanded at all, and the remaining forms are going to get wrapped in a macro which isn&amp;rsquo;t there in the source at all. So macroexpansion has to go outside in, as described above.&lt;/p&gt;

&lt;h2 id="a-better-way"&gt;A better way&lt;/h2&gt;

&lt;p&gt;Well, you could write macros like that. Probably once they were written like that. But it&amp;rsquo;s a pain, because you almost never care about the first element of the form &amp;mdash; the macros own name &amp;mdash; and you have to manually take the rest of the form apart yourself. And also you need to deal with questions about making sure macros are defined at compile time and so on.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s what &lt;code&gt;defmacro&lt;/code&gt; does. It is itself a macro, and its expansion will involve setting the &lt;code&gt;macro-function&lt;/code&gt; of the macro to some appropriate thing. So using &lt;code&gt;defmacro&lt;/code&gt; I can write the &lt;code&gt;fun&lt;/code&gt; macro:&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;(defmacro fun ((&amp;amp;rest args) &amp;amp;body forms)
  ;; still not dealing with declarations
  `(function (lambda (,@args) (with-debugging ,@forms))))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is easier to understand of course. But all it is is a (fairly elaborate!) wrapper around what I did above.&lt;/p&gt;

&lt;h2 id="watching-the-detectives"&gt;Watching the detectives&lt;/h2&gt;

&lt;p&gt;Using &lt;a href="https://tfeb.github.io/tfeb-lisp-hax/#tracing-macroexpansion-trace-macroexpand"&gt;&lt;code&gt;trace-macroexpand&lt;/code&gt;&lt;/a&gt; you can watch macroexpansion happen.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; (needs (:org.tfeb.hax.trace-macroexpand :compile t :use t))
; Loading [...]
((:org.tfeb.hax.trace-macroexpand t))

&amp;gt; (trace-macroexpand t)
nil

&amp;gt; (trace-macro fun with-debugging)
&amp;gt; (setf *trace-macroexpand-print-length* nil
        *trace-macroexpand-print-level* nil)
nil

&amp;gt; (trace-macro fun with-debugging)
(fun with-debugging)

&amp;gt; (setf *debugging* nil)                
nil

&amp;gt; (funcall (fun (a) a) 1)
(fun (a) a)
 -&amp;gt; #'(lambda (a) (with-debugging a))
(with-debugging a)
 -&amp;gt; (progn (when *debugging* (format *debug-io* "~&amp;amp;~S~%" 'a)) a)
(with-debugging a)
 -&amp;gt; (progn (when *debugging* (format *debug-io* "~&amp;amp;~S~%" 'a)) a)
1&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that &lt;code&gt;with-debugging&lt;/code&gt; is expanded twice: this is an artifact of the implementation: there&amp;rsquo;s no promise that macros only get expanded once in interpreted code.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class="footnotes"&gt;
 &lt;ol&gt;
  &lt;li id="2022-07-05-macroexpansion-in-common-lisp-footnote-1-definition" class="footnote-definition"&gt;
   &lt;p&gt;This was once going to be a Stack Overflow answer, and I didn&amp;rsquo;t want to throw it away.&amp;nbsp;&lt;a href="#2022-07-05-macroexpansion-in-common-lisp-footnote-1-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2022-07-05-macroexpansion-in-common-lisp-footnote-2-definition" class="footnote-definition"&gt;
   &lt;p&gt;And of course I might just be wrong about some details.&amp;nbsp;&lt;a href="#2022-07-05-macroexpansion-in-common-lisp-footnote-2-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2022-07-05-macroexpansion-in-common-lisp-footnote-3-definition" class="footnote-definition"&gt;
   &lt;p&gt;I am not talking about the environment objects which get passed to macro functions.&amp;nbsp;&lt;a href="#2022-07-05-macroexpansion-in-common-lisp-footnote-3-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li id="2022-07-05-macroexpansion-in-common-lisp-footnote-4-definition" class="footnote-definition"&gt;
   &lt;p&gt;Another way of thinking about &lt;code&gt;((lambda (...) ...) ...)&lt;/code&gt; is that is is the same as &lt;code&gt;(funcall (function (lambda (...) ...)) ...)&lt;/code&gt; and, since &lt;code&gt;function&lt;/code&gt; is a special operator, its rules apply, and include expanding the forms in the body of the &lt;code&gt;(lambda (...) ...)&lt;/code&gt; form (and of course &lt;code&gt;lambda&lt;/code&gt; is itself a macro, so &lt;code&gt;(lambda (...) ...)&lt;/code&gt; expands to &lt;code&gt;(function (lambda (...) ...)))&lt;/code&gt; and then the rules for &lt;code&gt;function&lt;/code&gt; apply again). I am old enough to remember adding the macro for &lt;code&gt;lambda&lt;/code&gt; to various antique CLs.&amp;nbsp;&lt;a href="#2022-07-05-macroexpansion-in-common-lisp-footnote-4-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content></entry>
 <entry>
  <title type="text">Avoiding circularity: a simple example</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2022/03/23/avoiding-circularity-a-simple-example/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2022-03-23-avoiding-circularity-a-simple-example</id>
  <published>2022-03-23T17:54:40Z</published>
  <updated>2022-03-23T17:54:40Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;Here&amp;rsquo;s a simple example of dealing with a naturally circular function definition.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;Common Lisp has a predicate called &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_everyc.htm"&gt;&lt;code&gt;some&lt;/code&gt;&lt;/a&gt;. Here is what looks like a natural definition of a slightly more limited version of this predicate, which only works on lists, in Racket:&lt;/p&gt;

&lt;pre class="brush: racket"&gt;&lt;code&gt;(define (some? predicate . lists)
  ;; Just avoid the spread/nospread problem
  (some*? predicate lists))

(define (some*? predicate lists)
  (cond
    [(null? lists)
     ;; if there are no elements the predicate is not true
     #f]
    [(some? null? lists)
     ;; if any of the lists is empty we've failed
     #f]
    [(apply predicate (map first lists))
     ;; The predicate is true on the first elements
     #t]
    [else
     (some*? predicate (map rest lists))]))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, that looks neat, right? Except it is very obviously doomed because &lt;code&gt;some*?&lt;/code&gt; falls immediately into an infinite recursion.&lt;/p&gt;

&lt;p&gt;Well, the trick to avoid this is to check whether the predicate is &lt;code&gt;null?&lt;/code&gt; and handle that case explicitly:&lt;/p&gt;

&lt;pre class="brush: racket"&gt;&lt;code&gt;(define (some*? predicate lists)
  (cond
    [(null? lists)
     ;; 
     (error 'some? "need at least one list")]
    [(eq? predicate null?)
     ;; Catch the circularity and defang it
     (match lists
       [(list (? list? l))
        (cond
          [(null? l)
           #f]
          [(null? (first l))
           #t]
          [else
           (some? null? (rest l))])]
       [_ (error 'some? "~S bogus for null?" lists)])]
    [(some? null? lists)
     ;; if any of the lists is empty we've failed
     #f]
    [(apply predicate (map first lists))
     ;; The predicate is true on the first elements
     #t]
    [else
     (some*? predicate (map rest lists))]))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And this now works fine.&lt;/p&gt;

&lt;p&gt;Of course this is a rather inefficient version of such a predicate, but it&amp;rsquo;s nice. Well, I think it is.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Note: a previous version of this had an extremely broken version of &lt;code&gt;some*?&lt;/code&gt; which worked, by coincidence, sometimes.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Two understandable deficiencies in Common Lisp</title>
  <link rel="alternate" href="https://www.tfeb.org/fragments/2022/03/22/two-understandable-deficiencies-in-common-lisp/?utm_source=programming&amp;utm_medium=Atom" />
  <id>urn:https-www-tfeb-org:-fragments-2022-03-22-two-understandable-deficiencies-in-common-lisp</id>
  <published>2022-03-22T09:58:28Z</published>
  <updated>2022-03-22T09:58:28Z</updated>
  <author>
   <name>Tim Bradshaw</name></author>
  <content type="html">
&lt;p&gt;Common Lisp is, I think, a remarkably pleasant language, despite what some people like to say. Here are two small deficiencies, both of which are understandable in terms of the history of CL, and both of which ultimately hurt naïve programmers working in CL.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h2 id="the-default-floating-point-type-is-single-float"&gt;The default floating-point type is &lt;code&gt;single-float&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;There are two things that make this true:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/v_rd_def.htm"&gt;&lt;code&gt;*read-default-float-format*&lt;/code&gt;&lt;/a&gt; is initially &lt;code&gt;single-float&lt;/code&gt;, which means that, unless it is changed, &lt;code&gt;1.0&lt;/code&gt; reads as &lt;code&gt;1.0f0&lt;/code&gt;, a single float&lt;sup&gt;&lt;a href="#2022-03-22-two-understandable-deficiencies-in-common-lisp-footnote-1-definition" name="2022-03-22-two-understandable-deficiencies-in-common-lisp-footnote-1-return"&gt;1&lt;/a&gt;&lt;/sup&gt;;&lt;/li&gt;
 &lt;li&gt;The &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_float.htm"&gt;&lt;code&gt;float&lt;/code&gt;&lt;/a&gt; function will convert to a single float unless it is given a prototype which is not a single float: &lt;code&gt;(float 1)&lt;/code&gt; is &lt;code&gt;1.0f0&lt;/code&gt;, while to get a double float you would need &lt;code&gt;(float 1 1.0d0)&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;In addition things like &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/m_w_std_.htm"&gt;&lt;code&gt;with-standard-io-syntax&lt;/code&gt;&lt;/a&gt; bind &lt;code&gt;*read-default-float-format*&lt;/code&gt; to &lt;code&gt;single-float&lt;/code&gt;, so you have to do a little more work to make doubles the default.&lt;/p&gt;

&lt;p&gt;I think there are probably several historical reasons why this default was chosen:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;a long time ago memory was very expensive and single floats take, usually, half the memory of double floats, thus pushing people towards single floats;&lt;/li&gt;
 &lt;li&gt;a long time ago, perhaps, on some machines, single float operations were significantly faster than double float operations even before possible float consing was taken into account;&lt;/li&gt;
 &lt;li&gt;Lisp hardware companies with significant influence on the standard, notably Symbolics, made hardware which allowed single (32 bit) floats to be immediate objects, while double floats were not, and had simple-minded compilers which were not capable of optimizing double float operations, thus making double float arithmetic extremely slow compared to single float arithmetic, and these companies wanted their machines to seem fast (they never, really, were) for naïve users;&lt;/li&gt;
 &lt;li&gt;it was not clear that implementations would choose &lt;code&gt;single-float&lt;/code&gt; to mean &amp;lsquo;single precision IEEE 754 float&amp;rsquo; and &lt;code&gt;double-float&lt;/code&gt; to mean &amp;lsquo;double precision IEEE 754 float&amp;rsquo;, for instance it&amp;rsquo;s perfectly legal to have the &lt;code&gt;short-float&lt;/code&gt; type mean single precision IEEE 754 and all of the &lt;code&gt;single-float&lt;/code&gt;, &lt;code&gt;double-float&lt;/code&gt; and &lt;code&gt;long-float&lt;/code&gt; types mean double precision IEEE 754;&lt;/li&gt;
 &lt;li&gt;it wasn&amp;rsquo;t even even clear that &lt;a href="https://en.wikipedia.org/wiki/IEEE_754-1985"&gt;IEEE 754&lt;/a&gt; would come to dominate how machines implement floating-point: VAXes didn&amp;rsquo;t, and other machines of interest at the time also did not.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;So there are good historical reasons for this. However all implementations I&amp;rsquo;m aware of now translate &lt;code&gt;short-float&lt;/code&gt; to mean &lt;code&gt;single-float&lt;/code&gt;, &lt;code&gt;single-float&lt;/code&gt; to mean IEEE 754 single precision, &lt;code&gt;double-float&lt;/code&gt; to mean IEEE 754 double precision and &lt;code&gt;long-float&lt;/code&gt; to be the same as &lt;code&gt;double-float&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So what is the problem with the default float type being &lt;code&gt;single-float&lt;/code&gt; in the modern world? The answer is&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (log (/ 1 single-float-epsilon) 10)
7.22472&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In other words, single precision IEEE 754 arithmetic has about 7 significant figures of precision. For many purposes, and &lt;em&gt;especially&lt;/em&gt; for naïvely-written code that&amp;rsquo;s at best marginal and at worst less than that. On the other hand&lt;/p&gt;

&lt;pre class="brush: lisp"&gt;&lt;code&gt;&amp;gt; (log (/ 1 double-float-epsilon) 10)
15.954589770191001D0&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;which is almost 16 significant figures of precision, more than twice that of single precision.&lt;/p&gt;

&lt;p&gt;That&amp;rsquo;s why the default should have been double precision: it makes naïve code more likely to work, and people who are writing non-naïve code can use single precision if they need it.&lt;/p&gt;

&lt;h2 id="the-cl-user-package-is-defined-in-an-implementation-dependent-way"&gt;The &lt;code&gt;CL-USER&lt;/code&gt; package is defined in an implementation-dependent way&lt;/h2&gt;

&lt;p&gt;From &lt;a href="http://www.lispworks.com/documentation/HyperSpec/Body/11_abb.htm"&gt;the spec&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;The &lt;code&gt;COMMON-LISP-USER&lt;/code&gt; package is the current package when a Common Lisp system starts up. This package uses the &lt;code&gt;COMMON-LISP&lt;/code&gt; package. The &lt;code&gt;COMMON-LISP-USER&lt;/code&gt; package has the nickname &lt;code&gt;CL-USER&lt;/code&gt;. &lt;em&gt;The &lt;code&gt;COMMON-LISP-USER&lt;/code&gt; package can have additional symbols interned within it; it can use other implementation-defined packages.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;(My emphasis.)&lt;/p&gt;

&lt;p&gt;What this means is that when you start a CL environment, the current package may have all sorts of implementation-dependent symbols visible in it. You can see why this happened: if you&amp;rsquo;re implementing Super-Whizz-Bang CL which has all sorts of magic extra features, you want at least some of those features to be immediately available to users, rather than requiring them to pore over boring manuals to find them.&lt;/p&gt;

&lt;p&gt;But for users, and especially for naïve users, it&amp;rsquo;s a terrible choice: naïve users don&amp;rsquo;t know about packages so they write their programs in &lt;code&gt;CL-USER&lt;/code&gt;. And they also don&amp;rsquo;t really know which symbols available in &lt;code&gt;CL-USER&lt;/code&gt; come from &lt;code&gt;CL&lt;/code&gt; and are thus standard parts of the language, and which come from one of Super-Whizz-Bang CL&amp;rsquo;s implementation packages, and are &lt;em&gt;not&lt;/em&gt; standard parts of the language. So their programs turn into a mess where the portable parts are not distinct from the non-portable parts. The way the &lt;code&gt;CL-USER&lt;/code&gt; package is defined thus makes it harder for to write programs whose non-portable parts are well-isolated, and ultimately hurts the language.&lt;/p&gt;

&lt;p&gt;This is a direct conflict between implementors and users: implementors both want their extra features immediately available so their implementation is shinier and want to encourage users to use these extra features in a way which makes it hard to move their programs to other implementations; users, when they think about it, generally don&amp;rsquo;t want this second thing, at least.&lt;/p&gt;

&lt;p&gt;Instead, the language should have defined &lt;code&gt;CL-USER&lt;/code&gt; as a package which &lt;em&gt;only&lt;/em&gt; used &lt;code&gt;CL&lt;/code&gt;, and perhaps have defined another standard package, perhaps &lt;code&gt;IMPL-USER&lt;/code&gt;, which was defined the way &lt;code&gt;CL-USER&lt;/code&gt; is today.&lt;/p&gt;

&lt;h2 id="can-these-be-fixed"&gt;Can these be fixed?&lt;/h2&gt;

&lt;p&gt;While both of these problems could be fixed without changing the standard, I don&amp;rsquo;t think either can &lt;em&gt;realistically&lt;/em&gt; be fixed.&lt;/p&gt;

&lt;p&gt;For the &lt;code&gt;single-float&lt;/code&gt; problem there is nothing to stop implementations simply defining &lt;code&gt;short-float&lt;/code&gt; to mean IEEE 754 single precision and all the other types to mean IEEE 754 double precision. But all the existing code which assumes otherwise will then probably break in exciting ways. So this is unlikely to happen I expect.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;CL-USER&lt;/code&gt; problem could be fixed if implementations agree to define &lt;code&gt;CL-USER&lt;/code&gt; to use only &lt;code&gt;CL&lt;/code&gt; as it is allowed to do, and perhaps to define an &lt;code&gt;IMPL-USER&lt;/code&gt; package as above. Of course that will make implementations slightly less convenient to use, so the chances of it happening would be small, even if implementors actually talked to each other in any useful way which I suspect they no longer do. Worse than that, this change will break many programs written by naïve users which live in &lt;code&gt;CL-USER&lt;/code&gt;, and there are almost certainly lots of those.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;A moment of convenience, a lifetime of regret, as the old saying goes.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class="footnotes"&gt;
 &lt;ol&gt;
  &lt;li id="2022-03-22-two-understandable-deficiencies-in-common-lisp-footnote-1-definition" class="footnote-definition"&gt;
   &lt;p&gt;An earlier version of this article had single floats written as, for instance &lt;code&gt;1.0s0&lt;/code&gt;: that&amp;rsquo;s wrong, those are &lt;em&gt;short&lt;/em&gt; floats, single floats are &lt;code&gt;1.0f0&lt;/code&gt; for instance. These are almost certainly the same type on any current implementation (and I think on any implementation I have ever used, hence the mistake) but they don&amp;rsquo;t have to be. Thanks to Prem Nirved for finding this stupidity.&amp;nbsp;&lt;a href="#2022-03-22-two-understandable-deficiencies-in-common-lisp-footnote-1-return"&gt;↩&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content></entry></feed>