<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>John Jacobsen</title>
    <link>http://johnj.com/</link>
    <description>Recent content on John Jacobsen</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Thu, 17 Jul 2025 00:00:00 +0000</lastBuildDate><atom:link href="http://johnj.com/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>&#34;Sites of Arrival&#34; Group Show</title>
      <link>http://johnj.com/posts/soa/</link>
      <pubDate>Thu, 17 Jul 2025 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/soa/</guid>
      <description>
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/soa-postcard-group-back.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/soa-postcard-group-back_hu_c6923b069f4596da.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Cormorant:ital,wght@0,300..700;1,300..700&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;h2 style=&#34;font-size: 3em; font-family: Cormorant&#39;, serif;&#34;&gt;Sites of Arrival&lt;/h2&gt;
&lt;p&gt;
A group show of (mostly) figurative art at the Palette and Chisel
Academy of Fine Arts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.instagram.com/matthewbraunart/&#34;&gt;Matthew Braun&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;John Jacobsen&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.instagram.com/vseverini/&#34;&gt;Veronica Severini&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.instagram.com/donald.colley54/&#34;&gt;Donald Colley&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.instagram.com/murielannart/&#34;&gt;Muriel Christensen&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-1&#34;&gt;
Location and Hours
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
&lt;a href=&#34;https://paletteandchisel.org/&#34;&gt;Palette and Chisel Academy of Fine Arts&lt;/a&gt;&lt;br&gt;
August 8-17, 2025&lt;/p&gt;
&lt;p&gt;
Opening August 8, 6-9 PM&lt;/p&gt;
&lt;p&gt;
1012 N. Dearborn St.&lt;br&gt;
Chicago, IL 60610&lt;/p&gt;
&lt;p&gt;
Office phone: 312 642 4400&lt;br&gt;
Office email: fineart1012@sbcglobal.net&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
Works in the Show
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/na2025.jpeg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/na2025_hu_994d64122010bd8c.jpeg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Noli Appropinquare, oil on canvas, 40&amp;#34;x28&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/taygetus2025.jpeg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/taygetus2025_hu_c96e9d046dbaefa2.jpeg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Atop Taygetus, oil on panel, 12&amp;#34;x9&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/evening-canalscape.jpeg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/evening-canalscape_hu_1095fa287d5ced6c.jpeg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Evening Canalscape, oil on canvas, 12&amp;#34;x8&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/wall-town-denizens.jpeg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/wall-town-denizens_hu_523148f3c99556a3.jpeg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Wall Town Denizens, gouache on paper, 12&amp;#34;x9&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/road-embrace.jpeg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/road-embrace_hu_d8440d48f35facac.jpeg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Road Embrace, gouache on paper, 10&amp;#34;x7&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/pink-butte.jpeg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/pink-butte_hu_5904da17ca619fe8.jpeg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Pink Butte, oil on panel, 10&amp;#34;x10&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/grey-figure-study.jpeg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/grey-figure-study_hu_32db61444926b80d.jpeg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Grey Figure Study, gouache and ink on paper, 10&amp;#34;x7&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/four-women.jpeg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/four-women_hu_b1efef17c1b05298.jpeg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Four Women, oil on four panels, approx. 14&amp;#34;x7&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/figures-and-dog.jpeg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/figures-and-dog_hu_2c9fce544207b9f4.jpeg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Figures and Dog, gouache and ink on paper, 12&amp;#34;x9&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/woman-seated-at-night.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/woman-seated-at-night_hu_719fd6b19e5a4d0a.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Woman, Seated, at Night, oil on wood, 12&amp;#34;x9.5&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/female-figures.jpeg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/female-figures_hu_fd6b6f79af1de6e1.jpeg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Female Figures, graphite on paper, 14&amp;#34;x11&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/seated-and-standing-figures.jpeg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/seated-and-standing-figures_hu_e38d2045b71f2229.jpeg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Seated and Standing Figures, graphite on paper, 14&amp;#34;x11&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/seated-figures.jpeg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/seated-figures_hu_ce8fdab5021bc3e4.jpeg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Seated Figures, graphite on paper, 14&amp;#34;x11&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-3&#34;&gt;
Artist&amp;#39;s Statement
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
I have been showing works done from life at the Palette and Chisel for
several years.  Such studies are very helpful for training the eye and
are entirely consistent with the P&amp;amp;C’s founding mission: to provide a
place to draw, paint and sculpt from the model, and to show the
resulting artwork.&lt;/p&gt;
&lt;p&gt;
At the same time I have long maintained a practice of drawing and
painting from imagination, sometimes deriving finished work in the
studio from life studies.  Lessons learned from painstaking work from
life can blossom in the studio into more complex, multi-figure
compositions, wide-open spaces, and otherworldly color palettes.&lt;/p&gt;
&lt;p&gt;
Some of the work shown here was begun decades earlier and tinkered
with slowly over the years, each piece going back on the shelf for
long periods of time, and then coming out when inspiration strikes or
the solution to some unresolved problem suddenly becomes clear. Bodo’s
suggestion to join this show gave me the welcome nudge to complete
some of these long-evolving pieces.&lt;/p&gt;
&lt;p&gt;
I view each drawing or painting as a unique experiment in solving
certain problems simultaneously. The bedrock requirement of an artwork
is that it makes sense at the level of design, while also obeying the
laws of perspective, light, and anatomy, as well as the artist’s own
interior laws, which are only revealed through the process of painting
itself.&lt;/p&gt;
&lt;p&gt;
I am suspicious of paintings where the outcome seems to have been
decided in advance. Each of these pieces is as much a surprise to me
as it may be to the viewer.  Their logic is their own, though I have
tried to fill in the blanks.  As one of my art heroes, Gregory
Gillespie, once said, “Paintings make sense if I paint them beautiful
enough.”  Pretty much sums it up, though he set a high bar in that
regard.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-4&#34;&gt;
Biography
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
John Jacobsen was born in Madison, Wisconsin in the previous
millennium. He studied art and physics at the University of
Wisconsin–Madison and received his Ph.D. in 1996.  In addition to his
work as an artist, Jacobsen has had a long career as a physicist and
software engineer, traveling extensively to such places as CERN
(Geneva), Hawaii, Europe, and the Amundsen-Scott South Pole Station in
Antarctica, which he has visited ten times in his work on the AMANDA
and IceCube astrophysical experiments.&lt;/p&gt;
&lt;p&gt;
After living and exhibiting in the San Francisco Bay Area from
1997-2002, he moved to Chicago, where he currently lives.&lt;/p&gt;
&lt;p&gt;
Jacobsen’s artwork is influenced by his travels, as well as his
artistic idols, which include Gregory Gillespie, Odd Nerdrum, Andrew
Wyeth, and American “Golden Age” illustrators.  His teachers have
included notable printmakers Jack Damer and David H. Becker at
UW-Madison, and the painters Steven Assael and Andrew S. Conklin at
the Palette and Chisel Academy of Fine Arts in Chicago.&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Thanks to Bodo Stolczenberger for helping to arrange this show.&lt;/em&gt;&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-5&#34;&gt;
For news and updates
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Say hi &lt;a href=&#34;http://johnj.com/contact&#34;&gt;on email&lt;/a&gt;, or check me &lt;a href=&#34;https://www.instagram.com/eigenhombre/&#34;&gt;on Instagram&lt;/a&gt; (&lt;code class=&#34;verbatim&#34;&gt;eigenhombre&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Lisp Testing Fun</title>
      <link>http://johnj.com/posts/a-fun-little-testing-macro/</link>
      <pubDate>Fri, 11 Apr 2025 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/a-fun-little-testing-macro/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/verticals.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/verticals_hu_67b3acf8c49855f4.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
I&amp;#39;ve been making some progress with &lt;code class=&#34;verbatim&#34;&gt;steelcut&lt;/code&gt;, &lt;a href=&#34;https://github.com/eigenhombre/steelcut&#34;&gt;my Common Lisp
template generator&lt;/a&gt; (does every Lisper write one of these as a rite of
passage?), and I keep running into interesting problems which
have been fun to solve.&lt;/p&gt;
&lt;p&gt;
Whenever my code starts to accumulate any sort of complexity, I
try to err on the side of writing more tests, even for
&amp;#34;recreational&amp;#34; projects such as this one.  The tests help make it safe to make
changes, while also documenting the expected functionality.  But test
code can be fairly repetitive, often with many small variations and
lots of boilerplate, in the midst of which it can be hard to see the
forest for the trees.&lt;/p&gt;
&lt;p&gt;
Such was the case for &lt;code class=&#34;verbatim&#34;&gt;steelcut&lt;/code&gt; tests.  I found myself remembering
Paul Graham&amp;#39;s &lt;a href=&#34;https://www.paulgraham.com/icad.html&#34;&gt;line&lt;/a&gt;, &amp;#34;Any other regularity in the code is a sign, to me
at least, that I&amp;#39;m using abstractions that aren&amp;#39;t powerful enough –
often that I&amp;#39;m generating by hand the expansions of some macro that I
need to write.&amp;#34;&lt;/p&gt;
&lt;p&gt;
In my current non-Lisp programming work, I most often miss macros when
writing test code.  But in this case, the macro I (apparently) needed
to write &lt;a href=&#34;https://github.com/eigenhombre/steelcut/blob/1db2122b7cc620510fad030646cc32f4c58a1bcc/test/test.lisp#L82&#34;&gt;is here&lt;/a&gt;.  Very roughly speaking, &lt;code class=&#34;verbatim&#34;&gt;with-setup&lt;/code&gt; creates a
temporary directory, runs the template generator with a given list of
requested features, and allows the user to check properties of the
generated files.&lt;/p&gt;
&lt;p&gt;
The macro grew and shrank as I DRYed out and simplified the test code.
I realized many of my tests were checking the generated dependencies
for the projects (from the .ASD file), so it would be helpful if the
macro would make those available to the test code in the form of a
function the user could name.&lt;/p&gt;
&lt;p&gt;
This wound up being a sweet bit of sugar for my tests, but not every
test needed such a helper function.  Stubborn &amp;#34;unused variable&amp;#34;
warnings ensued, for those tests which don&amp;#39;t use the &lt;code class=&#34;verbatim&#34;&gt;deps&lt;/code&gt; symbol
bound by the macro.  I went back and forth with ChatGPT on this one
(it made several wrong suggestions) until I realized I could give the
variable an explicit &lt;code class=&#34;verbatim&#34;&gt;_&lt;/code&gt; name and change the behavior based on the
name.  This is something I&amp;#39;ve seen in other languages and was tickled
I could get it so easily here.&lt;/p&gt;
&lt;p&gt;
I find the resulting tests pretty easy to read:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(test needed-files-created
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (with-setup appname &amp;#34;testingapp&amp;#34; appdir _ +default-features+
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (loop for file in &amp;#39;(&amp;#34;Makefile&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        &amp;#34;Dockerfile&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        &amp;#34;.github/workflows/build.yml&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        &amp;#34;build.sh&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        &amp;#34;test.sh&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        &amp;#34;src/main.lisp&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        &amp;#34;src/package.lisp&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        &amp;#34;test/test.lisp&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        &amp;#34;test/package.lisp&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          do
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             (is (uiop:file-exists-p (join/ appdir file))))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(test cmd-feature-adds-dependency-and-example
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (with-setup appname &amp;#34;testingapp&amp;#34; appdir deps +default-features+
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (let ((main-text (slurp (join/ appdir &amp;#34;src/main.lisp&amp;#34;))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      ;; :cmd is not there:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (is (not (find :cmd (deps))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      ;; It doesn&amp;#39;t contain the example function:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (is (not (has-cmd-example-p main-text)))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ;; Add :cmd to features, should get the new dependency:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (with-setup appname &amp;#34;test2&amp;#34; appdir deps (cons :cmd +default-features+)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (let ((main-text (slurp (join/ appdir &amp;#34;src/main.lisp&amp;#34;))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      ;; :cmd is now there:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (is (find :cmd (deps)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      ;; It contains the example function:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (is (has-cmd-example-p main-text)))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;em&gt;N.B.&lt;/em&gt;: A keyword argument would also work, obviously.  For a macro
in production code, I would probably go that route instead.&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Fun
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
I&amp;#39;ve also been thinking about &lt;a href=&#34;https://news.ycombinator.com/item?id=43651576&#34;&gt;a recent post on Hacker News&lt;/a&gt;, and the
ensuing discussion, in which both the author and commenters point out
that programming Lisp is &lt;em&gt;fun&lt;/em&gt;.  While I must acknowledge that Lisp
has been a life-long attraction/distraction/diversion, I&amp;#39;m noticing
that the &lt;em&gt;way&lt;/em&gt; it is fun for me is evolving somewhat.&lt;/p&gt;
&lt;p&gt;
First, I used to find Common Lisp pretty painful because of all its
sharp edges – the language is so powerful and flexible, you can shoot
yourself in the foot pretty much any way you like, and it&amp;#39;s not as
easy as some newer languages to get started with.  But now, with LLMs,
it&amp;#39;s much easier to get help when you get into the weeds.  Sure, &amp;#34;the
corpus of training data was smaller for Lisp than for mainstream
languages,&amp;#34; blah, blah.  But often even the wrong answers from ChatGPT
point me in the right direction (some of this is probably just
&lt;a href=&#34;https://en.wikipedia.org/wiki/Rubber_duck_debugging&#34;&gt;rubberducking&lt;/a&gt;).  When one&amp;#39;s own ignorance is less of an obstacle, the
pointy bits become less intimidating.&lt;/p&gt;
&lt;p&gt;
Second, there are some &lt;em&gt;really&lt;/em&gt; good, and fun, books on Lisp.  &lt;a href=&#34;https://github.com/norvig/paip-lisp?tab=readme-ov-file&#34;&gt;PAIP&lt;/a&gt;,
&lt;a href=&#34;https://letoverlambda.com/&#34;&gt;Let Over Lambda&lt;/a&gt;, &lt;a href=&#34;https://gigamonkeys.com/book/&#34;&gt;Practical Common Lisp&lt;/a&gt;, &lt;a href=&#34;http://landoflisp.com/&#34;&gt;Land of Lisp&lt;/a&gt; (plus &lt;a href=&#34;https://www.youtube.com/watch?v=HM1Zb3xmvMc&#34;&gt;video&lt;/a&gt;!).
Lisp has some pretty mind-bending things in it, and I&amp;#39;m enjoying
taking the time to dig into some of these books again, understanding
things better than the first time I swung by.&lt;/p&gt;
&lt;p&gt;
Third, I&amp;#39;m regularly stunned by how fast Lisp is.  All the tests I&amp;#39;ve
been writing run effectively instantly at the REPL on my M1 Macbook
Air.  And now that I&amp;#39;m starting to get good enough at the language
that it is getting out of my way, that speed is more noticeable, and,
well, fun.&lt;/p&gt;
&lt;p&gt;
Finally, I am intrigued by the history of computing, of which Lisp has
been an important part.  This is worth saying more about in a future
post, but for the moment I find a stable, highly-performant, &lt;em&gt;fun&lt;/em&gt;
language that has intrigued people for decades to be more of interest
than the bleeding edge.  (I&amp;#39;m not hating on Rust.  Rust is nice.  But
I don&amp;#39;t find it fun, at least not yet.)&lt;/p&gt;
&lt;p&gt;
Beyond fun, I&amp;#39;m also enjoying &amp;#34;&lt;a href=&#34;https://stevelosh.com/blog/2018/08/a-road-to-common-lisp/#s4-escaping-the-hamster-wheel-of-backwards-incompatibility&#34;&gt;escaping the hamster wheel of backwards
incompatibility&lt;/a&gt;&amp;#34; for awhile.  While so many things around us crumble
and whirl, and new forms of AI scare the pants out of us as much as
they intrigue, older tools and traditions start to feel more like
comfortable tools that weigh down one&amp;#39;s hands satisfyingly and invite
calm creation.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>To The Metal... Compiling Your Own Language(s)</title>
      <link>http://johnj.com/posts/to-the-metal/</link>
      <pubDate>Tue, 06 Aug 2024 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/to-the-metal/</guid>
      <description>
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/eclipse.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/eclipse_hu_4b980836f660ca22.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Like many programmers, I have programming &lt;a href=&#34;http://johnj.com/posts/in-defense-of-hobbies/&#34;&gt;hobbies&lt;/a&gt;.  One of these is
implementing new languages.  My most recent language project, &lt;a href=&#34;https://github.com/eigenhombre/l1/&#34;&gt;l1&lt;/a&gt;, was
a Lisp dialect whose primary data types are symbols and
arbitrarily-large integers.&lt;/p&gt;
&lt;p&gt;
I&amp;#39;ve been happy with &lt;code class=&#34;verbatim&#34;&gt;l1&lt;/code&gt;, but it is interpreted; since I was actively
working on it last (2022), I&amp;#39;ve been wondering about the best way to
generate &lt;em&gt;compiled&lt;/em&gt; standalone executable programs, written in &lt;code class=&#34;verbatim&#34;&gt;l1&lt;/code&gt; or
any other language.&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
The Problem In General
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Execution models for programming languages take three basic
approaches, listed in increasing order of speed:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Tree-walking interpreter&lt;/strong&gt;: Programs are read and parsed into ASTs
in memory, then executed step-by-step by an interpreter.  This
is the approach &lt;code class=&#34;verbatim&#34;&gt;l1&lt;/code&gt; uses.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bytecode VM&lt;/strong&gt;: Programs are compiled into a sort of abstract
machine language, simpler than the physical processor&amp;#39;s, and
executed by a virtual machine (VM).  Java and Python work this way.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Machine code generation&lt;/strong&gt;: The code is directly compiled into
machine language and executed on the user&amp;#39;s hardware.  C and C++
programs work this way.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Languages using Option 2 often add just-in-time compilation to machine
code, for extra performance.  Option 3 is typically fastest, but is
sometimes skipped in introductory compiler classes and tutorials.  For
example, Robert Nystrom&amp;#39;s excellent &lt;em&gt;&lt;a href=&#34;https://craftinginterpreters.com/&#34;&gt;Crafting Interpreters&lt;/a&gt;&lt;/em&gt; book
devotes the first section to implementing a tree-walking interpreter
implementation in Java and the second half to a compiler and bytecode
VM written in C, with minimal coverage of how to target physical
hardware.  And the (also excellent) &lt;a href=&#34;https://dabeaz.com/compiler.html&#34;&gt;class on compiler writing&lt;/a&gt; that I
took from David Beazley, in its first incarnation, stopped at the
point of generating of so-called intermediate representation (IR)
output (though students in the current iteration of the class do
compile to native code, using LLVM).&lt;/p&gt;
&lt;p&gt;
Compiling to machine code is tricky because CPUs are inherently
complex. Real hardware is intricate, cumbersome, and unintuitive if
you&amp;#39;re primarily accustomed to high-level languages. Additionally,
there are numerous significant variants to consider (e.g., CPU/GPU,
ARM/Intel, 32-bit/64-bit architectures).&lt;/p&gt;
&lt;p&gt;
But targeting machine code rather than interpreters or bytecode VMs is
appealing, not just because it is an interesting challenge, but also
because the resulting artifacts are small, stand-alone, and typically
very fast.  While running Python, Ruby, and Java programs require the
appropriate infrastructure to be in place on the target machine at all
times, Go, Rust, and C programs (among others) benefit from targeting
the physical hardware: their programs tend to be smaller, and can be
deployed to identical computers simply by copying the executable file,
needing to deploy the interpreter, extra libraries, etc. to the target
machine(s).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
Small Is Beautiful
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
As a programmer who came up during the dawn of personal computers, I
have some nostalgia for an era when programs or even entire operating
systems fit on a few-hundred-kB floppy disk.  Much existing software
feels bloated to me, though some widespread tools are still lean and
fast. For illustration purposes, here are the physical sizes of some
of the venerable command-line Unix programs I use on a daily basis
(this is on MacOS):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Program&lt;/th&gt;
&lt;th class=&#34;align-right&#34;&gt;Size (kB)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;wc&lt;/code&gt;&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;cat&lt;/code&gt;&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;116&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;df&lt;/code&gt;&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;116&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;more&lt;/code&gt;&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;360&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
These were chosen more or less at random from my &lt;code class=&#34;verbatim&#34;&gt;bash&lt;/code&gt; history and
are representative of old-school Unix utilities.  For comparison,
iMovie on my Mac is &lt;strong&gt;2.8 GB&lt;/strong&gt;, several thousand times larger than the
largest of these.  Of course, the comparison is somewhat ludicrous -
iMovie does many amazing things… but I use all the above programs
hundreds or thousands of times more often than I do iMovie, so it&amp;#39;s
good that that they are compact and run quickly.  In a time of
increasingly bloated software stacks,
I find myself especially drawn to simple tools with small footprints.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-3&#34;&gt;
An Approach
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
If targeting physical hardware is hard, what tools can we use to make
the job easier?&lt;/p&gt;
&lt;p&gt;
I recently started learning about &lt;a href=&#34;https://llvm.org/&#34;&gt;LLVM&lt;/a&gt;, a modular set of compiler
tools which &amp;#34;can be used to develop a frontend for any programming
language and a backend for any instruction set architecture&amp;#34;
(&lt;a href=&#34;https://en.wikipedia.org/wiki/LLVM&#34;&gt;Wikipedia&lt;/a&gt;).  LLVM has been used heavily in the Rust toolchain and in
Apple&amp;#39;s developer tools.&lt;/p&gt;
&lt;p&gt;
The &amp;#34;modular&amp;#34; adjective is critical here: LLVM is separated into
front-end, back-end and optimizing parts thanks to a shared
&amp;#34;&lt;a href=&#34;https://en.wikipedia.org/wiki/Intermediate_representation&#34;&gt;intermediate representation&lt;/a&gt;&amp;#34; (IR) – a sort of portable assembly
language which represents simple computation steps in a
machine-independent but low-level manner.&lt;/p&gt;
&lt;p&gt;
The LLVM IR takes a little getting used to but, with a little
practice, is reasonably easy to read, and, more importantly, to
generate.&lt;/p&gt;
&lt;p&gt;
As an example, consider the following simple C program, &lt;code class=&#34;verbatim&#34;&gt;three.c&lt;/code&gt;,
which stores the number 3 in a variable and uses it as its exit code.
We will use &lt;code class=&#34;verbatim&#34;&gt;clang&lt;/code&gt;, the LLVM C/C++/Obj-C/… compiler for the LLVM
ecosystem:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ cat three.c
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;int x = 3;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;int main() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  return x;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ clang three.c -o three
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ./three; echo $?
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
One can easily view, and possibly even understand, the assembler
output for such a simple program:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ clang -O3 -S three.c -o three.s
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ cat -n three.s
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     1		.section	__TEXT,__text,regular,pure_instructions
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     2		.build_version macos, 14, 0	sdk_version 14, 4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     3		.globl	_main                           ; -- Begin function main
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     4		.p2align	2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     5	_main:                                  ; @main
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     6		.cfi_startproc
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     7	; %bb.0:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     8	Lloh0:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     9		adrp	x8, _x@PAGE
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    10	Lloh1:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    11		ldr	w0, [x8, _x@PAGEOFF]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    12		ret
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    13		.loh AdrpLdr	Lloh0, Lloh1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    14		.cfi_endproc
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    15	                                        ; -- End function
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    16		.section	__DATA,__data
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    17		.globl	_x                              ; @x
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    18		.p2align	2, 0x0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    19	_x:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    20		.long	3                               ; 0x3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    21
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    22	.subsections_via_symbols&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
In comparison, here is the LLVM IR for the same program:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ clang -S -emit-llvm three.c -o three.ll
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ cat -n three.ll
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     1	; ModuleID = &amp;#39;three.c&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     2	source_filename = &amp;#34;three.c&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     3	target datalayout = &amp;#34;e-m:o-i64:64-i128:128-n32:64-S128&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     4	target triple = &amp;#34;arm64-apple-macosx14.0.0&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     5
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     6	@x = global i32 3, align 4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     7
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     8	; Function Attrs: noinline nounwind optnone ssp uwtable(sync)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     9	define i32 @main() #0 {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    10	  %1 = alloca i32, align 4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    11	  store i32 0, ptr %1, align 4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    12	  %2 = load i32, ptr @x, align 4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    13	  ret i32 %2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    14	}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    15
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    16	attributes #0 = { noinline nounwind optnone ssp ;; .... very long list...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    17
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    18	!llvm.module.flags = !{!0, !1, !2, !3, !4}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    19	!llvm.ident = !{!5}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    20
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    21	!0 = !{i32 2, !&amp;#34;SDK Version&amp;#34;, [2 x i32] [i32 14, i32 4]}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    22	!1 = !{i32 1, !&amp;#34;wchar_size&amp;#34;, i32 4}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    23	!2 = !{i32 8, !&amp;#34;PIC Level&amp;#34;, i32 2}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    24	!3 = !{i32 7, !&amp;#34;uwtable&amp;#34;, i32 1}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    25	!4 = !{i32 7, !&amp;#34;frame-pointer&amp;#34;, i32 1}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    26	!5 = !{!&amp;#34;Apple clang version 15.0.0 (clang-1500.3.9.4)&amp;#34;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
There is a fair amount of stuff here, but a lot of it looks
suspiciously like metadata we don&amp;#39;t really care about for our
experiments going forward.  The, uh, &lt;code class=&#34;verbatim&#34;&gt;main&lt;/code&gt; region of interest is from
lines 9-14 – notice that the function definition itself looks a
little more readable than the assembly language version, but slightly
lower-level than the original C program.&lt;/p&gt;
&lt;p&gt;
You can turn the IR into a runnable program:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ clang -O3 three.ll -o three
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ./three; echo $?
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The approach I explore here is to &lt;em&gt;generate&lt;/em&gt; LLVM IR &amp;#34;by fair means or foul.&amp;#34;
Here, let&amp;#39;s just edit our IR down to something more minimal and see how it goes.
I suspect the &lt;code class=&#34;verbatim&#34;&gt;store&lt;/code&gt; of &lt;code class=&#34;verbatim&#34;&gt;0&lt;/code&gt; in &amp;#34;register&amp;#34; &lt;code class=&#34;verbatim&#34;&gt;%1&lt;/code&gt; is gratuitous, so
let&amp;#39;s try to remove it, along with all the metadata:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ cat 3.ll
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;target triple = &amp;#34;x86_64-apple-macosx14.0.0&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;@x = global i32 3, align 4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;define i32 @main() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  %1 = load i32, ptr @x, align 4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ret i32 %1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ clang -O3 3.ll -o 3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ./3; echo $?
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This is frankly not much more complicated than the C code, and it
shows a helpful strategy at work:&lt;/p&gt;
&lt;p&gt;
Step 1: To understand how to accomplish something in LLVM IR,
write the corresponding C program and use &lt;code class=&#34;verbatim&#34;&gt;clang&lt;/code&gt; to generate
the IR, being alert for possible &amp;#34;extra stuff&amp;#34; like we saw
in the example.&lt;/p&gt;
&lt;p&gt;
Step 2. Try to generate, and test, working programs from the IR you
write or adapt, making adjustments as desired.&lt;/p&gt;
&lt;p&gt;
There is another, optional step as well:&lt;/p&gt;
&lt;p&gt;
Step 3. Use, or write, language &amp;#34;bindings&amp;#34; to drive LLVM generation
from the language of your choice.  This is the step we will consider next.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-4&#34;&gt;
Enter Babashka
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
While one can write LLVM IR directly, as we have seen, we are
interested in compiling other languages (possibly higher-level ones of
our own invention), so we will want to &lt;em&gt;generate&lt;/em&gt; IR somehow.  For
this project I chose &lt;a href=&#34;https://babashka.org/&#34;&gt;Babashka&lt;/a&gt;, an implementation of the &lt;a href=&#34;https://clojure.org/&#34;&gt;Clojure&lt;/a&gt;
programming language I have found ideal for small projects where both
start-up speed and expressiveness are important.&lt;/p&gt;
&lt;p&gt;
(I assume some familiarity with Lisp and Clojure in this post; for those
just getting started, &lt;a href=&#34;https://www.braveclojure.com/&#34;&gt;Clojure for the Brave and True&lt;/a&gt; is a good introduction.)&lt;/p&gt;
&lt;p&gt;
The repo &lt;a href=&#34;https://github.com/eigenhombre/llbb&#34;&gt;https://github.com/eigenhombre/llbb&lt;/a&gt; contains the source files
discussed here.  The bulk of the code in this repo is in &lt;a href=&#34;https://github.com/eigenhombre/llbb/blob/master/llir.bb&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;llir.bb&lt;/code&gt;&lt;/a&gt;, a
source file which provides alternative definitions in Clojure for
common LLVM idioms.  Some of these are trivial translations:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(def m1-target &amp;#34;arm64-apple-macosx14.0.0&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn target [t] (format &amp;#34;target triple = \&amp;#34;%s\&amp;#34;&amp;#34; t))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
… whereas other expressions leverage the power of Clojure to a
greater degree.  For example, this section defines translations used
to represent arithmetic operations:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn arithm [op typ a b]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (format &amp;#34;%s %s %s, %s&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          (name? op)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          (name? typ)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          (sigil a)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          (sigil b)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn add [typ a b] (arithm :add typ a b))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn sub [typ a b] (arithm :sub typ a b))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn mul [typ a b] (arithm :mul typ a b))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn div [typ a b] (arithm :sdiv typ a b))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(comment
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (div :i32 :a :b)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;sdiv i32 %a, %b&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (add :i8 :x 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;add i8 %x, 1&amp;#34;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
You can see this approach at work by representing the C program
discussed earlier:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(module
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (assign-global :i :i32 3)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (def-fn :i32 :main []
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   (assign :retval (load :i32 :i))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   (ret :i32 :retval)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
which evaluates to&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;target triple = &amp;#34;arm64-apple-macosx14.0.0&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;@i = global i32 3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;define i32 @main() nounwind {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  %retval = load i32, i32* @i, align 4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ret i32 %retval
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
I use here a slightly different but equivalent pointer syntax for the
&lt;code class=&#34;verbatim&#34;&gt;load&lt;/code&gt; expression than output by &lt;code class=&#34;verbatim&#34;&gt;clang&lt;/code&gt; in the example above.&lt;/p&gt;
&lt;p&gt;
Two very small helper functions allow me to test out small programs quickly:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(require &amp;#39;[babashka.process :as sh])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn sh
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Use `bash` to run command(s) `s`, capturing both stdout/stderr
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  as a concatenated string.  Throw an exception if the exit code
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  is nonzero.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  [s]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let [{:keys [out err]}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        (sh/shell {:out :string, :err :string}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                  (format &amp;#34;bash -c &amp;#39;%s&amp;#39;&amp;#34; s))]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (str/join &amp;#34;\n&amp;#34; (remove empty? [out err]))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
and&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(require &amp;#39;[babashka.fs :as fs])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn compile-to
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Save IR `body` to a temporary file and compile it, writing the
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  resulting binary to `progname` in the current working directory.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  [progname body]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let [ll-file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        (str (fs/create-temp-file {:prefix &amp;#34;llbb-&amp;#34;, :suffix &amp;#34;.ll&amp;#34;}))]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (spit ll-file body)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (sh (format &amp;#34;clang -O3 %s -o %s&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                ll-file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                progname))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
These two together allow me to test small programs out quickly at the
REPL.  Some examples follow, obtained by running the C compiler for
equivalent programs, generating and inspecting the LLVM IR, and
translating them into new Clojure bindings as cleanly as possible.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Minimum viable program&lt;/strong&gt;: just return zero:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(compile-to &amp;#34;smallest-prog&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            (module
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             (def-fn :i32 :main []
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               (ret :i32 0))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(sh &amp;#34;./smallest-prog; echo -n $?&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#34;0&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;strong&gt;Argument count&lt;/strong&gt;: return, as the exit code, the number of arguments,
including the program name:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; Argument counting: return number of arguments as an exit code:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(compile-to &amp;#34;argcount&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            (module
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             (def-fn :i32 :main [[:i32 :arg0]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                 [:ptr :arg1_unused]]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               (assign :retptr (alloca :i32))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               (store :i32 :arg0 :ptr :retptr)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               (assign :retval (load :i32 :retptr))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               (ret :i32 :retval))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(sh &amp;#34;./argcount; echo -n $?&amp;#34;) ;;=&amp;gt; &amp;#34;1&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(sh &amp;#34;./argcount 1 2 3; echo -n $?&amp;#34;) ;;=&amp;gt; &amp;#34;4&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;strong&gt;Hello, world&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(let [msg &amp;#34;Hello, World.&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      n (inc (count msg))] ;; Includes string terminator
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (compile-to &amp;#34;hello&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              (module
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               (external-fn :i32 :puts :i8*)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               (def-global-const-str :message msg)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               (def-fn :i32 :main []
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                 (assign :as_ptr
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                         (gep (fixedarray n :i8)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                              (star (fixedarray n :i8))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                              (sigil :message)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                              [:i64 0]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                              [:i64 0]))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                 (call :i32 :puts [:i8* :as_ptr])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                 (ret :i32 0)))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(sh &amp;#34;./hello&amp;#34;) ;;=&amp;gt; &amp;#34;Hello, World.\n&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This is the first program one typically writes in a new programming
language.  Note that we use here idioms (&lt;code class=&#34;verbatim&#34;&gt;external-fn&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;call&lt;/code&gt;) to
define and invoke an external function from the C standard library.&lt;/p&gt;
&lt;p&gt;
Let&amp;#39;s see how big the resulting program is:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(sh &amp;#34;ls -l hello&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#34;-rwxr-xr-x  1 jacobsen  staff  33432 Aug 14 21:09 hello\n&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
At this point I want to pause to reconsider one of the points of this
exercise, which is to produce small programs. Here are the rough
executable sizes for a &amp;#34;Hello, World&amp;#34; example program in various
languages that I use frequently:&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Language&lt;/td&gt;
&lt;td&gt;Size&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;Relative Size&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Common Lisp&lt;/td&gt;
&lt;td&gt;38 MB&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;1151&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clojure&lt;/td&gt;
&lt;td&gt;3.4 MB&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;103&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;1.9 MB&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;58&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;33 kB&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LLVM IR&lt;/td&gt;
&lt;td&gt;33 kB&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
I threw Clojure in there for comparison even though, unlike the other
examples, the resulting überjar also requires a Java bytecode VM in
order to run.  The programs generated from C and from LLVM IR are
equivalent; this is not surprising, given that I used the C program to
guide my writing and translation of the LLVM IR.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-5&#34;&gt;
Building A Compiling Calculator
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
We are now ready to implement a &amp;#34;compiler&amp;#34; for something approaching a
useful language, namely, greatly reduced subset of &lt;a href=&#34;https://en.wikipedia.org/wiki/Forth_(programming_language&#34;&gt;Forth&lt;/a&gt;.  Forth is a
stack-based language created in the 1970s and still in use
today, especially for small embedded systems.&lt;/p&gt;
&lt;p&gt;
LLVM will handle the parts commonly known as &amp;#34;compiler backend&amp;#34; tasks,
and Babashka will provide our &amp;#34;frontend,&amp;#34; namely breaking the text into
tokens and parsing them.  This task is made easy for us, because Forth
is syntactically quite simple, and Babashka relatively powerful. Here are
the language rules we will adopt:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Program tokens are separated by whitespace.&lt;/li&gt;
&lt;li&gt;Non-numeric tokens are math operators.&lt;/li&gt;
&lt;li&gt;Only integer operands are allowed.&lt;/li&gt;
&lt;li&gt;Comments begin with &lt;code class=&#34;verbatim&#34;&gt;\\&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Forth expressions typically place the arguments first, and the operator
last (so-called &amp;#34;reverse-Polish notation&amp;#34;).  Here is an example program
which does some math and prints the result:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(def example &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2 2 +  \\ 4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;5 *    \\ multiply by five to get 20
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2 /    \\ divide by 2 -&amp;gt; 10
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;-1 +   \\ add -1 -&amp;gt; 9
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;8 -    \\ subtract 8 -&amp;gt; 1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.      \\ prints &amp;#39;1&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#34;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The code in &lt;a href=&#34;https://github.com/eigenhombre/llbb/blob/master/forth.bb&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;forth.bb&lt;/code&gt;&lt;/a&gt; handles the parser, whose goal is to consume the
raw program text and generate an abstract syntax tree (in our case, just
a list) of operations to translate into IR:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn strip-comments
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Remove parts of lines beginning with backslash
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  [s]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (str/replace s #&amp;#34;(?sm)^(.*?)\\.*?$&amp;#34; &amp;#34;$1&amp;#34;))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn tokenize
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Split `s` on any kind of whitespace
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  [s]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (remove empty? (str/split s #&amp;#34;\s+&amp;#34;)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defrecord node
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [typ val] ;; A node has a type and a value
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Object
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (toString [this]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (format &amp;#34;[%s %s]&amp;#34; (:typ this) (:val this))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; Allowed operations
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(def opmap {&amp;#34;+&amp;#34; :add
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &amp;#34;-&amp;#34; :sub
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &amp;#34;/&amp;#34; :div
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &amp;#34;*&amp;#34; :mul
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &amp;#34;.&amp;#34; :dot
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &amp;#34;drop&amp;#34; :drop})
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn ast
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Convert a list of tokens into an \&amp;#34;abstract syntax tree\&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  which in our Forth is just a list of type/value pairs.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  [tokens]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (for [t tokens
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        :let [op (get opmap t)]]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (cond
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      ;; Integers (possibly negative)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (re-matches #&amp;#34;^\-?\d+$&amp;#34; t)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (node. :num (Integer. t))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      ;; Operations
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      op (node. :op op)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      :else (node. :invalid :invalid))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Running this on our example,&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(-&amp;gt;&amp;gt; example
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     strip-comments
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     tokenize
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     ast
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (map str))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(&amp;#34;[:num 2]&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#34;[:num 2]&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#34;[:op :add]&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#34;[:num 5]&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#34;[:op :mul]&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#34;[:num 2]&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#34;[:op :div]&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#34;[:num -1]&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#34;[:op :add]&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#34;[:num 8]&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#34;[:op :sub]&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#34;[:op :dot]&amp;#34;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The remainder of &lt;code class=&#34;verbatim&#34;&gt;forth.bb&lt;/code&gt; essentially just implements the needed
operators, as well as the required stack and the reference to the &lt;code class=&#34;verbatim&#34;&gt;printf&lt;/code&gt;
C library function.  It is perhaps a bit lengthy to go through here in
its entirety, so I will share one example where Babashka helps:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn def-arithmetic-op [nam op-fn]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (def-fn :void nam []
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (assign :sp (call :i32 :get_stack_cnt))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (if-lt :i32 :sp 2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           (els)  ;; NOP - not enough on stack
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           (els
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            (assign :value2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    (call :i32 :pop))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            (assign :value1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    (call :i32 :pop))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            (assign :result (op-fn :i32 :value1 :value2))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            (call :void :push [:i32 :result])))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (ret :void)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This makes LLVM IR which does the following, in pseudo-code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;get current stack position; ensure at least two entries (else return)&lt;/li&gt;
&lt;li&gt;pop the operands off the stack&lt;/li&gt;
&lt;li&gt;apply the arithmetic operator to the operands&lt;/li&gt;
&lt;li&gt;put the result on the stack&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Implementing the four arithmetic operators is then as simple
as invoking&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(def-arithmetic-op :mul mul)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(def-arithmetic-op :add add)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(def-arithmetic-op :sub sub)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(def-arithmetic-op :div div)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
when generating the IR.&lt;/p&gt;
&lt;p&gt;
Aside from the general-purpose LLVM IR code (&lt;code class=&#34;verbatim&#34;&gt;llir.bb&lt;/code&gt;), the Forth
implementation is under two hundred lines.  It includes the invocation
to &lt;code class=&#34;verbatim&#34;&gt;clang&lt;/code&gt; to compile the temporary IR file to make the runnable
program.  Here&amp;#39;s an example compilation session:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ cat example.fs
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       \\ initial state          stack: []
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;3      \\ put 3 on stack.        stack: [3]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;99     \\ put 99 on stack.       stack: [3, 99]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;drop   \\ discard top item.      stack: [3]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;drop   \\ discard top item.      stack: []
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2 2    \\ put 2 on stack, twice: stack: [2, 2]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;+      \\ 2 + 2 = 4.             stack: [4]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;5 *    \\ multiply 4 * 5.        stack: [20]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2 /    \\ divide by 2.           stack: [10]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;-1 +   \\ add -1                 stack: [9]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;8 -    \\ subtract 8 -&amp;gt; 1        stack: [1]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.      \\ prints &amp;#39;1&amp;#39;             stack: [1]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;drop   \\ removes 1.             stack: []
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ./forth.bb example.fs
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ./example
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The resulting program is fast, as expected…&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ time ./example
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;real	0m0.007s
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;user	0m0.002s
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sys	0m0.003s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
… and small:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ls -l ./example
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;-rwxr-xr-x  1 jacobsen  staff  8952 Aug 16 09:52 ./example&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Let&amp;#39;s review what we&amp;#39;ve done: we have implemented a small subset of Forth,
writing a compiler front-end in Babashka/Clojure to translate source programs
into LLVM IR, and using &lt;code class=&#34;verbatim&#34;&gt;clang&lt;/code&gt; to turn the IR into compact binaries.  The
resulting programs are small and fast.&lt;/p&gt;
&lt;p&gt;
Sensible next steps would be to implement more of Forth&amp;#39;s stack
operators, and maybe start to implement the &lt;code class=&#34;verbatim&#34;&gt;:&lt;/code&gt; (colon) operator,
Forth&amp;#39;s mechanism for defining new symbols and functions.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-6&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-6&#34;&gt;
Lisp
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-6&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Instead, let&amp;#39;s implement a different variant of our arithmetic
calculating language, using Lisp syntax (&lt;a href=&#34;https://en.wikipedia.org/wiki/S-expression&#34;&gt;S-expressions&lt;/a&gt;).  Consider our
first Forth example:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2 2 +
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;5 *
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2 /
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;-1 +
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;8 -
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
In Lisp, this looks like:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ cat example.lisp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(print (- (+ -1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             (/ (* 5
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   (+ 2 2))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                2))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          8))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Rather than coming last, as they did before (&amp;#34;postfix&amp;#34; notation), our
operators come first (&amp;#34;prefix&amp;#34; notation). The order of operations is
determined by parentheses, as opposed to using stack as we did for
our Forth implementation.&lt;/p&gt;
&lt;p&gt;
Here Babashka helps us tremendously because such parenthesized prefix
expressions are valid &lt;a href=&#34;https://github.com/edn-format/edn&#34;&gt;EDN&lt;/a&gt; data, which the Clojure function
&lt;code class=&#34;verbatim&#34;&gt;clojure.edn/read-string&lt;/code&gt; can parse for us. But we need to convert the
resulting nested list into the &amp;#34;SSA&amp;#34; (&lt;a href=&#34;https://en.wikipedia.org/wiki/Static_single-assignment_form&#34;&gt;single static assignment&lt;/a&gt;)
expressions LLVM understands. This is relatively straightforward with
a recursive function which expands leaves of the tree and stores the
results as intermediate values:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn to-ssa [expr bindings]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (if (not (coll? expr))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    expr
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (let [[op &amp;amp; args] expr
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          result (gensym &amp;#34;r&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          args (doall
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                (for [arg args]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                  (if-not (coll? arg)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    arg
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    (to-ssa arg bindings))))]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (swap! bindings conj (concat [result op] args))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      result)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn convert-to-ssa [expr]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let [bindings (atom [])]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (to-ssa expr bindings)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    @bindings))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
We use &lt;code class=&#34;verbatim&#34;&gt;gensym&lt;/code&gt; here to get a unique variable name for each assignment,
and &lt;code class=&#34;verbatim&#34;&gt;doall&lt;/code&gt; to force the evaluation of the lazy for expansion of the
argument terms. The result:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(-&amp;gt;&amp;gt; &amp;#34;example.lisp&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     slurp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (edn/read-string)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     convert-to-ssa)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[(r623 + 2 2)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (r622 * 5 r623)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (r621 / r622 2)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (r620 + -1 r621)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (r619 - r620 8)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (r618 print r619)]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The next step will be to actually write out the corresponding LLVM
IR. The rest of &lt;code class=&#34;verbatim&#34;&gt;lisp.bb&lt;/code&gt; is satisfyingly compact.  Operators (we
have five, but more can easily be added), are just a map of symbols
to tiny bits of LLVM code:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(def ops
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  {&amp;#39;* #(mul :i32 %1 %2)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   &amp;#39;+ #(add :i32 %1 %2)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   &amp;#39;/ #(div :i32 %1 %2)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   &amp;#39;- #(sub :i32 %1 %2)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   &amp;#39;print
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   #(call &amp;#34;i32 (i8*, ...)&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          :printf
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          [:i8* :as_ptr]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          [:i32 (sigil %1)])})&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Similar to our Forth implementation, but even more compact, the main Babashka function,
after a brief setup for &lt;code class=&#34;verbatim&#34;&gt;printf&lt;/code&gt;, generates a series of SSA instructions.&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn main [[path]]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (when path
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (let [assignments (-&amp;gt;&amp;gt; path
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                           slurp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                           edn/read-string
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                           convert-to-ssa)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          outfile (-&amp;gt;&amp;gt; path
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                       fs/file-name
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                       fs/split-ext
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                       first)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          ir (module
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              (external-fn :i32 :printf :i8*, :...)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              (def-global-const-str :fmt_str &amp;#34;%d\n&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              (def-fn :i32 :main []
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                (assign :as_ptr
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        (gep (fixedarray 4 :i8)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                             (star (fixedarray 4 :i8))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                             (sigil :fmt_str)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                             [:i64 0]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                             [:i64 0]))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                ;; Interpolate SSA instructions / operator invocations:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                (apply els
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                       (for [[reg op &amp;amp; args] assignments
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                             :let [op-fn (ops op)]]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                         (if-not op-fn
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                           (throw (ex-info &amp;#34;bad operator&amp;#34; {:op op}))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                           (assign reg (apply op-fn args)))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                (ret :i32 0)))]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (compile-to outfile ir))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(main *command-line-args*)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Putting these parts together (see &lt;a href=&#34;https://github.com/eigenhombre/llbb/blob/master/lisp.bb&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;lisp.bb&lt;/code&gt;&lt;/a&gt; on GitHub), we have:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ./lisp.bb example.lisp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ./example
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
It, too, is small and fast:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ time ./example
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;real	0m0.006s
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;user	0m0.001s
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sys	0m0.003s
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ls -al ./example
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;-rwxr-xr-x  1 jacobsen  staff  33432 Aug 16 20:52 ./example&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
To say this is a &amp;#34;working Lisp compiler&amp;#34; at this point would be
grandiose (we still need functions, lists and other collection types,
eval, macros, …) but we have developed an excellent foundation
to build upon.&lt;/p&gt;
&lt;p&gt;
To summarize, the strategy we have taken is as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use a high level language (in our case, Babashka/Clojure) to parse
input and translate into LLVM IR;&lt;/li&gt;
&lt;li&gt;When needed, write and generate small C programs to understand the
equivalent IR to generate.&lt;/li&gt;
&lt;li&gt;Compile the IR to small, fast binaries using &lt;code class=&#34;verbatim&#34;&gt;clang&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-7&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-7&#34;&gt;
Alternatives and Future Directions
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-7&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
I should note that C itself has long been used as an intermediate
language, and we could have used it here instead of LLVM IR; I don&amp;#39;t
have a strong sense of the tradeoffs involved yet, but wanted to take
the opportunity to learn more about LLVM for this project.&lt;/p&gt;
&lt;p&gt;
LLVM is interesting to me because of the modularity of its toolchain;
it also provides a JIT compiler which allows one to build and execute
code at run-time.  We didn&amp;#39;t investigate tooling for that here (it
needs deeper LLVM language bindings than the homegrown Babashka code I
used), but it could provide a way to do run-time compilation similar
to what SBCL (a Common Lisp implementation which can compile functions
at run-time) does.&lt;/p&gt;
&lt;p&gt;
Here are some directions I&amp;#39;m considering going forward:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Try interfacing with external libraries, e.g. a &lt;a href=&#34;https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic&#34;&gt;bignum&lt;/a&gt; library;&lt;/li&gt;
&lt;li&gt;Implement more Forth functionality;&lt;/li&gt;
&lt;li&gt;Implement more Lisp, possibly including a significant subset of &lt;code class=&#34;verbatim&#34;&gt;l1&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Try a JIT-based approach, possibly using Rust as the host language.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-8&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-8&#34;&gt;
Conclusion
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-8&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Whenever possible, I want to make small, fast programs, and I like
playing with and creating small programming languages. LLVM provides a
fascinating set of tools and techniques for doing so, and using
Babashka to make small front-ends for IR generation turns out to be
surprisingly effective, at least for simple languages.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Wrangling Half a Thousand Dreams</title>
      <link>http://johnj.com/posts/wrangling-dreams/</link>
      <pubDate>Sat, 27 Apr 2024 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/wrangling-dreams/</guid>
      <description>
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/dreamsketch.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/dreamsketch_hu_20994df3834440ff.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
On Monday, February 4th, 1985, at the tender age of eighteen, I wrote
down in the back of my journal two meagre fragments of the previous
night&amp;#39;s dreams:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I’m at Fred’s and the cab is 45 minutes late.&lt;/p&gt;
&lt;p&gt;
Leaping over an empty oil drum on a highway.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
This is the first of several hundred dream entries I&amp;#39;ve accumulated
over nearly forty years. Though I&amp;#39;m not entirely sure what provided
the impulse at the time to start writing them down, I&amp;#39;ve always been
fascinated by dreams, and can remember a few childhood dreams as
clearly as anything else that happened when I was growing up.&lt;/p&gt;
&lt;p&gt;
Until recently, I hadn&amp;#39;t given much thought to the practice of dream
journaling, or even re-read many of the entries, which have been
scattered throughout a dozen or so handwritten notebooks and
electronic files. This year, however, my interest in dream journaling
peaked, which spurred me to start collecting all the entries into a
single e-book that I could read at leisure on the various devices in
my life.&lt;/p&gt;
&lt;p&gt;
The collating and formatting is now largely complete, and, while the
combined journal is a bit too personal to post publicly in its
entirety, I would like at least to share a few insights from the
project.&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-1&#34;&gt;
(In-)consistency
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
As of this morning, there are 470 dated entries. Each entry, typically
written first thing in the morning, captures at least one dream from
the previous night (unless you wake up in between, it&amp;#39;s hard to know
when one dream ends, and another begins).  Though the numbers average
to about one entry per month during my adult life so far, my actual
rate of dream journaling has been highly variable, and has tended to
track my rate of daytime journaling. Here are the number of dreams per
year, as of today:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1985:   68 ....................................................................
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1986:   59 ...........................................................
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1987:   10 ..........
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1988:    7 .......
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1989:    9 .........
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1990:   37 .....................................
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1991:    7 .......
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1992:   23 .......................
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1993:    4 ....
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1994:    1 .
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1996:    2 ..
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;1998:    2 ..
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2000:   10 ..........
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2001:    2 ..
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2002:   34 ..................................
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2003:    3 ...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2004:    3 ...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2005:    4 ....
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2006:    1 .
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2011:    4 ....
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2017:    2 ..
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2019:   68 ....................................................................
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2021:    2 ..
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2022:   22 ......................
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2023:   29 .............................
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;2024:   57 .........................................................
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;TOTAL: 470&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
I will say more about how the statistics were generated in a
moment. Each dot indicates a dated entry of one or more dreams from
the previous night.  Some years I averaged an entry or two a week;
other times I went for years with no entries.  That the data would be this
variable piqued my curiosity.&lt;/p&gt;
&lt;p&gt;
Naïvely, I might expect to have written more during times of crisis or
big change in my life, and that is approximately true. For example,
there are peaks during my first year in college (1985-1986), the year
I lived abroad in Switzerland (1990), and the year I had various
personal crises and moved away from the Bay Area (2002).  2019 was a
year of some tumult as well. But my interest in dreaming has waxed and
waned over time, and interest, while hard to track, certainly drives
the rate as well.&lt;/p&gt;
&lt;p&gt;
It is also well-known that remembering and writing down dreams one
morning makes it easier to do so the next morning, so I&amp;#39;d expect the
journals to clump somewhat in time.  However, given the sheer number
of entries, it surprises me a little to have gone literally years with
no entries at all.  There are very few entries in the interval from
2003 through 2018, and a few multi-year gaps.  For any &amp;#34;missed&amp;#34; year,
if you assume 3-6 dreams per night (a very rough, possibly bogus
average I found online), over a thousand dreams completely slipped
through the net. (By the same measure, my total average dream recall
since reaching adulthood has been less than one percent.)&lt;/p&gt;
&lt;p&gt;
The handwritten journals have some nice features compared to digital
files.  A few of them have small drawings or thumbnail sketches of a
particular moment or image from a dream.  They also show the
variability in my handwriting over the years (which has never been
great), and their proximity to &amp;#34;normal&amp;#34; diary entries help show what
else was going on at the time. (I typically would write the diary
entries forward from the front page of the journal, and dream
journal entries back-to-front from the last page, starting a new
journal book when the two met in the middle.)&lt;/p&gt;
&lt;p&gt;
Obviously, I&amp;#39;ll continue to hold onto the physical journals. But the
combined digital journal has two major advantages: it is much easier
to read, and all the dreams are in one place. These two together make
reading the journal as a whole much easier.  This, in turn, made
repeated images and common themes more apparent.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-2&#34;&gt;
Dream Content
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
It is a hallmark of dreams that they seem to defy characterization,
lurching from image to image in surprising ways, but I find some dream
topics cropping up consistently over the years, whereas others seem to
have come and gone.  Common topics over the years have included:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Moving through big, open landscapes, especially at night;&lt;/li&gt;
&lt;li&gt;Making art;&lt;/li&gt;
&lt;li&gt;Fighting, with people or animals;&lt;/li&gt;
&lt;li&gt;Family and friends;&lt;/li&gt;
&lt;li&gt;Teachers, mostly physics and art teachers I’ve studied with;&lt;/li&gt;
&lt;li&gt;Physics, and technology in general;&lt;/li&gt;
&lt;li&gt;Nuclear war/power/devices;&lt;/li&gt;
&lt;li&gt;Storms;&lt;/li&gt;
&lt;li&gt;Sex;&lt;/li&gt;
&lt;li&gt;Trains;&lt;/li&gt;
&lt;li&gt;Travel, especially Paris, Greece, New Zealand, and the South Pole.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some of these (sex, family) are probably common for most people;
others (nuclear devices, trains, Antarctica) maybe a little less so.&lt;/p&gt;
&lt;p&gt;
I also tried to spot changes over time. Common topics from earlier
years, that are now less common, included: flying or falling, flooding
or shallow water, war / soldiers / cops / authority figures, and being
in school.  More common topics these days include being in art
workshops; traveling through disused, dark interior spaces; and
programming or other computer work.&lt;/p&gt;
&lt;p&gt;
I have always resisted thinking about dreams as something demanding
interpretation, but the fact is they do come from somewhere, and are
probably informed by the events in our lives.  Reading through all the
repeated variations, I get the sense of my mind working through
things, though in exactly what way is obviously a mystery.&lt;/p&gt;
&lt;p&gt;
My point in thinking about evolution of dream content is not so much
to drive specific insights about my life, but rather to take a step
back and experience a broader sense of dreaming as a part of
life… to feel what it is like to be &amp;#34;one who dreams.&amp;#34;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-3&#34;&gt;
Making the Ebook
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
I won&amp;#39;t weigh this post down with too much technical detail, but
present a few details here in case anyone finds it helpful; others can
obviously skip this section.&lt;/p&gt;
&lt;p&gt;
When I started organizing things this year, the largest dream journal I had
was a single &lt;a href=&#34;https://orgmode.org/&#34;&gt;Emacs Org Mode&lt;/a&gt; file &lt;code class=&#34;verbatim&#34;&gt;dreams.org&lt;/code&gt;.  I used this as the nucleus
of the project, copying or typing all the content from the other sources,
sorted by increasing date.  Here are the first few lines:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#+TITLE: Dreams
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#+DATE: &amp;lt;2017-08-29 Tue&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#+OPTIONS: toc:nil num:nil
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;* 1985
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;** &amp;lt;1985-02-04 Mon&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;I&amp;#39;m at Fred&amp;#39;s and the cab is 45 minutes late.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Leaping over an empty oil drum on a highway.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;** &amp;lt;1985-02-05 Tue&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[...]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The plain text format is readable on its own, and editable in any
editor, though obviously Emacs has some advantages for this
format. Without any extra work, having the content in Org Mode
immediately allowed me to view the entire document as plain text, as
HTML in the browser, or as a PDF, thanks to Org Mode&amp;#39;s export
functionality.&lt;/p&gt;
&lt;p&gt;
During the long process of typing older dreams into this document
(doing only a few per day to keep the project from taking over my
life), I started looking for ways to turn the dream document into
something I could view on my phone, Kindle, iPad, Kobo reader, etc.  I
found I preferred reading old dream content on an e-ink display such
as the Kindle or Kobo rather than on a backlit screen, so an e-book
format such as EPUB seemed a natural next step.&lt;/p&gt;
&lt;p&gt;
I described my initial approach &lt;a href=&#34;http://johnj.com/posts/ebook-of-dreams/&#34;&gt;in an earlier blog post&lt;/a&gt;. The basic
idea was to tweak the Org Mode formatting slightly to make it
equivalent to Markdown and then use &lt;a href=&#34;https://calibre-ebook.com/&#34;&gt;Calibre&lt;/a&gt;&amp;#39;s &lt;code class=&#34;verbatim&#34;&gt;ebook-convert&lt;/code&gt; program
to turn that output into an EPUB file. However, that program ran more
slowly than I liked, and I found myself wishing I could customize the
output (especially the table of contents).  I also was curious what
exactly went into all those e-books I&amp;#39;ve been reading over the years
– what, exactly, did they look like, under the hood?&lt;/p&gt;
&lt;p&gt;
So, I decided to skip the middleman and write my own Org Mode to EPUB
converter.  &lt;a href=&#34;https://github.com/eigenhombre/dreambook/&#34;&gt;The result of that work is up on GitHub&lt;/a&gt;.  While some of
the details are out of scope for this article, I will say two things
about the approach I took.  First, I was very happy with my choice of
&lt;a href=&#34;https://github.com/babashka/babashka&#34;&gt;Babashka&lt;/a&gt; for the implementation.  Babashka is fast and expressive, and
I did not need any external libraries, relying only on the very
standard &lt;code class=&#34;verbatim&#34;&gt;zip&lt;/code&gt; program as the only external dependency.  My gratitude
to Michiel Borkent for Babashka continues undiminished.&lt;/p&gt;
&lt;p&gt;
(Ironically, while looking up Babashka tricks in Daniel Higgenbotham&amp;#39;s
excellent &lt;a href=&#34;https://www.braveclojure.com/quests/babooka/&#34;&gt;Babashka Babooka&lt;/a&gt;, I discovered he also uses a dream journal as
his example Babashka project.)&lt;/p&gt;
&lt;p&gt;
The other approach worth mentioning is the strategy I used to produce
a working EPUB.  This turned out to be more difficult than I thought,
as &lt;a href=&#34;https://en.wikipedia.org/wiki/EPUB&#34;&gt;EPUB is a rich and complex format&lt;/a&gt; with a number of historical
variants.  I spent a good amount of time with Google, ChatGPT, and
Wikipedia to try to get a simple example to load in both Calibre and
Apple Books; when this did not succeed, I switched gears and picked a
random e-book from &lt;a href=&#34;https://standardebooks.org/&#34;&gt;Standard Ebooks&lt;/a&gt; out of my collection, gradually
stripping out all the actual text content and extraneous data out
(zipping, importing and visually checking the files after each iteration) until I
had the barest minimum set of files, with two &amp;#34;Lorem ipsum…&amp;#34; style
chapters and a table of contents, which worked in both Calibre and
Books.&lt;/p&gt;
&lt;p&gt;
Then I automated the production of that minimum example using
Babashka, and &lt;a href=&#34;https://github.com/eigenhombre/minpub&#34;&gt;posted the results&lt;/a&gt;.  This provided something I could
build on to make my final dream e-book implementation, which has the
following features:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Cover art;&lt;/li&gt;
&lt;li&gt;Introduction and Collophon sections;&lt;/li&gt;
&lt;li&gt;Organization by month and year, with table of contents entries for each;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Correct conversion of the following formatting elements from Org Mode into the EPUB HTML:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;em&gt;Italic&lt;/em&gt;, &lt;strong&gt;boldface&lt;/strong&gt;, &lt;del&gt;strikethrough&lt;/del&gt;, &lt;span style=&#34;text-decoration: underline;&#34;&gt;underline&lt;/span&gt;, &lt;code class=&#34;verbatim&#34;&gt;code&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Sections and subsections (used to organize the dates as well as subsections for each day, as needed);&lt;/li&gt;
&lt;li&gt;Correctly-formatted beginning and ending quotes and apostrophes;&lt;/li&gt;
&lt;li&gt;French guillemets (a few of the dreams are written down in French or have French dialogue).&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The script uses an intermediate Markdown representation for the
content before converting to HTML, since the transformations are
simple and I have the idea I might eventually support Markdown in
addition to, or instead of, Org Mode.  The formatting requirements are
minimal enough to be easily supported by a sequence of regular
expressions to convert from one format to another.&lt;/p&gt;
&lt;p&gt;
The script&amp;#39;s output is the EPUB file itself, along with the statistics
display I posted above.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-4&#34;&gt;
Common Words
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
A special mode of the program (invoked with the &lt;code class=&#34;verbatim&#34;&gt;-w&lt;/code&gt; command-line
option) prints out the 300 most common words in the dreams:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;above across actually again against almost along am a... another
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;apartment are area around arrive art ask asks away beautiful bed been
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;before behind being below between big bike bit black blue boat body
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;both building buildings bunch can&amp;#39;t car cars city class close clothes
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;comes coming corner country couple dad dark d... different does
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;doesn&amp;#39;t dog doing don&amp;#39;t door down drawing dream drive driving each
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;e... either else end everyone family feel feeling few fight fighting
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;figure finally find fish floor flying food f... french friend friends
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;front game gets getting girl glass goes going gone gray great green
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ground group guy guys had hair hand hanging hard has having he&amp;#39;s head
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;hear help here high hill home house huge i&amp;#39;ll i&amp;#39;m i&amp;#39;ve inside is it&amp;#39;s
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;j... j... keep kind lake large last later least leave left light
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;little long looking looks lot lots love made madison makes making man
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;many maybe meet men mom more mostly move moving much myself name near
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;need next night off office old older open others outside painting
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;paper paris part party past path perhaps person p... p... phone
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;physics piece place plane playing point possibly probably pull put
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ready real realize really red remember restaurant ride right road room
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rooms run running same says school seems series several she&amp;#39;s short
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;should show showing side similar sit sitting slightly small somehow
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;someone something somewhat somewhere sort space spot stairs standing
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;start starts still stop strange street stuff suddenly sure swimming
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;table taken takes taking talk talking tell there&amp;#39;s thing things
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;thinking though three through together too top towards town train
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;trees truck try trying turn under very wait wake walk walking wall
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;walls wants was water we&amp;#39;re where while white whole why window&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
(In this list, the most common 100 English words have been subtracted
out to help distinguish the content from any other text.)&lt;/p&gt;
&lt;p&gt;
The words that stand out for me, aside from first names (which I elide
here using &lt;code class=&#34;verbatim&#34;&gt;...&lt;/code&gt;), are nouns which indicate settings, actions or
activities, and commonly occurring objects from the dreams.  I suppose
this list, or something like it, could be considered a sort of
&amp;#34;dreamer&amp;#39;s fingerprint.&amp;#34;  It would be interesting to compare with
someone else&amp;#39;s output (another English speaker, perhaps).  If you&amp;#39;re a
programmer and have a dream journal of your own, &lt;a href=&#34;https://github.com/eigenhombre/dreambook/blob/12acd59879b9a1b9c42b348e3d1ba9596cc41fca/src/dreambook/main.clj#L92&#34;&gt;here is a link to the
relevant code&lt;/a&gt; that you could adapt to generate the list. (Or, of
course, you could convert your journal to Org Mode and use &lt;a href=&#34;https://github.com/eigenhombre/dreambook/&#34;&gt;the
software I wrote&lt;/a&gt; &amp;#34;out of the box.&amp;#34;)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-5&#34;&gt;
Parting Thoughts
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Digging into this material, both the combined journal itself, and
automating the text conversion, has been engaging enough to consume
most of my limited free time over the past month or so.  I was
surprised at how fun it was to read through the collected dreams,
though I suspect the material would be much less entertaining for
anyone who didn&amp;#39;t know me well.  The writing itself tends to be more
compact and faster moving than my other writing.  In this regard it
sets an example I want to emulate in the rest of my writing.&lt;/p&gt;
&lt;p&gt;
The work also provoked contemplations about memory, a topic I tend to
think more about as I get older.  One mysterious aspect of dreams is
that, for the most part, we forget them in the morning.  They
disappear completely unless we make a record of them, giving them that
kick of energy they need to turn from virtual particles into real
ones.  In re-reading the dream entries, I was struck by the fact that,
not only did I have no memory of most of the dreams I&amp;#39;d collected, but
for the most part I had no memory at all of writing them down, either.
It was strange to confront a whole tranche of my life of which I had
basically no memory, having only the &amp;#34;evidence at hand&amp;#34; to work with.
In this regard, I felt at times a bit like a scientist studying someone
else&amp;#39;s dreams.&lt;/p&gt;
&lt;p&gt;
The collection of dreams is packed with myriad images, whether
strange, disturbing, or funny, or all three… each of them somehow
connected with my life.  As an artist who sometimes struggles to
figure out what to draw or paint, having a trove of material to work
with feels exciting and a little daunting.  Regardless of what any of
it means, the material is more &amp;#34;mine&amp;#34; than anything inspired by other
artists, or films, books, etc.  It&amp;#39;s up to me to see what, if anything,
I can actually do with it.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Programming Languages and Art Media</title>
      <link>http://johnj.com/posts/programming-languages-and-art-media/</link>
      <pubDate>Sun, 24 Mar 2024 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/programming-languages-and-art-media/</guid>
      <description>&lt;p&gt;
What computer programming languages &amp;#34;go with&amp;#34; (feel like) what art mediums?  Here is my first crack at the question.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Medium&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Clojure&lt;/td&gt;
&lt;td&gt;graphite&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Babashka&lt;/td&gt;
&lt;td&gt;charcoal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Common Lisp&lt;/td&gt;
&lt;td&gt;dip pens with india ink&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Emacs Lisp&lt;/td&gt;
&lt;td&gt;ball point&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;engraving&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C++&lt;/td&gt;
&lt;td&gt;etching&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Perl&lt;/td&gt;
&lt;td&gt;watercolor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;gouache&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;oil painting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;lithography&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sh&lt;/td&gt;
&lt;td&gt;woodcut&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bash&lt;/td&gt;
&lt;td&gt;linoleum cut&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;Procreate on the iPad&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;text-decoration: underline;&#34;&gt;&lt;span style=&#34;text-decoration: underline;&#34;&gt;&lt;span style=&#34;text-decoration: underline;&#34;&gt;_&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;text-decoration: underline;&#34;&gt;&lt;span style=&#34;text-decoration: underline;&#34;&gt;&lt;span style=&#34;text-decoration: underline;&#34;&gt;_&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(Copilot)&lt;/td&gt;
&lt;td&gt;collage&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
I&amp;#39;ve tried all of these except for the engraving, which I&amp;#39;d like to learn at some point.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>eBook of Dreams</title>
      <link>http://johnj.com/posts/ebook-of-dreams/</link>
      <pubDate>Tue, 13 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/ebook-of-dreams/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/dreambook.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/dreambook_hu_4e94e310b69e1720.jpg&#34; style=&#34;width:800px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Since at least the 1980s I&amp;#39;ve kept a (very intermittent) dream journal
in various forms, including&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;dedicated paper notebooks&lt;/li&gt;
&lt;li&gt;notes or drawings in sketchbooks&lt;/li&gt;
&lt;li&gt;fragments of entries in &lt;a href=&#34;http://johnj.com/posts/journaling-procedure/&#34;&gt;daily Org Mode diary pages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;individual iCloud Notes, one per dream&lt;/li&gt;
&lt;li&gt;a single, dedicated Org Mode file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lately I thought it might be interesting to review these and possibly
use them as ideas for artworks, and I&amp;#39;ve found last format to be most
amenable to later review (e.g., by exporting to a Web page or a
nicely-formatted PDF).&lt;/p&gt;
&lt;p&gt;
As an avid e-book reader, I wondered yesterday, How hard might it be to
turn such a dream journal into an e-book, for reading on one of my e-paper
devices?  (I bounce back and forth between a Kindle and a Kobo reader).&lt;/p&gt;
&lt;p&gt;
It turns out this is very easy and maps quite naturally into my existing
&amp;#34;book workflow,&amp;#34; which is, very briefly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;acquire (legally) one or more e-books&lt;/li&gt;
&lt;li&gt;import into &lt;a href=&#34;https://calibre-ebook.com/&#34;&gt;Calibre&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;plug in the e-reader device (I always keep WiFi off on these devices
to avoid the vendor pushing up unwanted updates)&lt;/li&gt;
&lt;li&gt;use Calibre to send the book to the device.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, my dream journal is in this format:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#+TITLE: Dreams
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#+DATE: &amp;lt;2017-08-29 Tue&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#+OPTIONS: toc:nil num:nil
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;* &amp;lt;2017-08-29 Tue&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;It was after hours in the lower, windowless floors of some science
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;building [....]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
I wanted to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Strip off the front matter;&lt;/li&gt;
&lt;li&gt;Convert the dates to chapter headers;&lt;/li&gt;
&lt;li&gt;Add a cover image, taken more or less at random from my library of
roughly 10,000 artistic reference photos and images.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For the cover, it was enough to simply pick one, crop it to roughly
the dimensions of my e-reader, and put it in the same directory as my
dream journal file.&lt;/p&gt;
&lt;p&gt;
With these requirements in mind, to save time on the regex wrangling,
I had a short conversation with ChatGPT, and an even shorter session
with my code editor, resulting in this &lt;a href=&#34;http://johnj.com/posts/in-praise-of-small-scripts/&#34;&gt;small bash script&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Define paths
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;DREAMFILE=&amp;#34;/Users/myuser/org/dreams.org&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;EPUB_OUTPUT=&amp;#34;$HOME/Desktop/dreams.epub&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;COVER_IMAGE=&amp;#34;/Users/myuser/org/dreams-cover.png&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Remove leading front matter and convert Markdown to temporary file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sed -E -e &amp;#39;1,/^$/d&amp;#39; -e &amp;#39;s/^\* &amp;lt;([0-9]{4}-[0-9]{2}-[0-9]{2} [A-Za-z]{3})&amp;gt;$/# \1/&amp;#39; &amp;#34;$DREAMFILE&amp;#34; &amp;gt; /tmp/dreams_tmp.md
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Import temporary Markdown file into Calibre
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ebook-convert /tmp/dreams_tmp.md &amp;#34;$EPUB_OUTPUT&amp;#34; --output-profile=tablet --cover=&amp;#34;$COVER_IMAGE&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Clean up temporary file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rm /tmp/dreams_tmp.md&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
I&amp;#39;m very happy with the results.  All that remains is to consolidate
some of the older dreams into the single Org Mode file I mentioned;
then I can update my eBook of Dreams periodically… and peer back
into the dream world at will.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Making A Tiny E-Paper Status Display for the Raspberry Pi Zero</title>
      <link>http://johnj.com/posts/e-paper-rpi-display/</link>
      <pubDate>Thu, 25 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/e-paper-rpi-display/</guid>
      <description>
&lt;p&gt;
I&amp;#39;ve gotten interested in Raspberry Pis again, having recently picked
up a Pi Zero 2 W.  Something about these cheap little boards that are
fully-functional Linux computers, &amp;#34;&lt;a href=&#34;http://www.roylongbottom.org.uk/Raspberry%20Pi%20Benchmarks.htm&#34;&gt;as powerful&lt;/a&gt;&amp;#34; as the VAXes I
originally learned Unix on, appeals to the young hacker in me who fell
in love with computers in the 1980s and is still able to be amazed by
their potential.  I&amp;#39;ve also been trying to get more comfortable doing
hardware projects, tinkering with an Arduino kit and brushing up on
the electronics I learned in college.&lt;/p&gt;
&lt;p&gt;
For my first &amp;#34;finished&amp;#34; project I wanted to work with an e-paper (also
known as e-ink) display.  These displays, used in most eBook readers
such as the Kindle, Nook, Kobo, etc., are great for low-power
applications, where information updates relatively infrequently, where
an external light source is available, and where monochrome output is
suitable.  Personally, I prefer no backlight and monochrome output,
frequently setting my iPhone screen to greyscale as a way of
reducing its stranglehold on my attention.&lt;/p&gt;
&lt;p&gt;
I like the idea of building devices which truly fade into the
background rather than being sources of interruption.  Devices that
don&amp;#39;t tell you things directly, but rather invite you to look their
way &lt;em&gt;when you care to&lt;/em&gt;.  I thought an enjoyable first project might be a
little computer that just quietly tells you about itself and doesn&amp;#39;t
do much else.  Tangentially, this relates to a movement known as &amp;#34;&lt;a href=&#34;https://en.wikipedia.org/wiki/Calm_technology&#34;&gt;calm
technology&lt;/a&gt;&amp;#34; which advocates for presenting information &lt;a href=&#34;https://www.karlstechnology.com/blog/designing-calm-technology/&#34;&gt;less
invasively&lt;/a&gt;, often in subliminal ways (&amp;#34;&lt;a href=&#34;https://www.etymonline.com/word/subliminal&#34;&gt;under the threshold of
consciousness&lt;/a&gt;&amp;#34;).&lt;/p&gt;
&lt;p&gt;
This post records what I needed to do to build such a small
e-paper-based device.  Since there were a lot of details I&amp;#39;m likely to
forget down the road, I used &lt;a href=&#34;https://howardism.org/Technical/Emacs/literate-devops.html&#34;&gt;Literate DevOps in Org Mode&lt;/a&gt; from this
document to be able to run and record (and re-run) most of the steps
while editing the document itself (see the linked &lt;a href=&#34;https://howardism.org/Technical/Emacs/literate-devops.html&#34;&gt;blog post&lt;/a&gt; for an
explanation).&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Supply List
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
I used the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vilros Raspberry Pi Zero 2 W Basic Starter Kit&lt;/li&gt;
&lt;li&gt;2.13 inch e-paper HAT from Waveshare&lt;/li&gt;
&lt;li&gt;128 GB MicroSD card (&lt;em&gt;way&lt;/em&gt; overkill)&lt;/li&gt;
&lt;li&gt;Solder and soldering iron&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I highly recommmend the Vilros kit - it was beautifully packaged and
had everything I needed.  I did have to solder the 40-pin GPIO
connector onto the Pi Zero.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/pion-halves.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/pion-halves_hu_2a1c892a8f0165c7.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Pi Zero and Waveshare hat (underside)
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Total cost was about $80, not counting the new soldering iron I had to
purchase after my old Radio Shack soldering iron shorted out, though
I could have saved money by buying a smaller SD card.&lt;/p&gt;
&lt;p&gt;
The Waveshare product is &lt;a href=&#34;https://www.waveshare.com/wiki/2.13inch_e-Paper_HAT_Manual#Overview&#34;&gt;reasonably well-documented&lt;/a&gt;, though they
recommend some steps I think are best avoided or changed.  The
software setup I used is shown next.  (The rest of this post is
somewhat technical – skip to the end if you just want to see the
pictures.)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
Dependencies
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
In honor of particle astrophysics, I gave the computer the name
&lt;code class=&#34;verbatim&#34;&gt;pion&lt;/code&gt;.  It runs Raspbian, which is a Debian variant.&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-3&#34;&gt;
Virtualenv-based setup
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
I prefer not to install Python dependencies into system directories,
because it&amp;#39;s better to isolate sets of dependencies across different
applications; the &lt;code class=&#34;verbatim&#34;&gt;venv&lt;/code&gt; module creates virtual environments
(&amp;#34;virtualenvs&amp;#34;) which do this.  Also, Waveshare&amp;#39;s guide recommends
&lt;code class=&#34;verbatim&#34;&gt;numpy&lt;/code&gt;, which is a heavyweight dependency I prefer to avoid unless I
need it, and as far as I can tell, we do not.  My dependency
installation steps were as follows (here and below, the command that
was issued has a grey background, and the output has a tan-colored
background):&lt;/p&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On pion:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt-get update -qq
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt-get install -yqq python3-pip
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python -m venv venv
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;source&lt;/span&gt; venv/bin/activate
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install -U -q setuptools
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install -q spidev
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install -q gpiozero
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install -q pillow&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&#34;example&#34;&gt;
Selecting previously unselected package python3-pip.
(Reading database ... [...progress info elided...]
Preparing to unpack .../python3-pip_23.0.1+dfsg-1+rpt1_all.deb ...
Unpacking python3-pip (23.0.1+dfsg-1+rpt1) ...
Setting up python3-pip (23.0.1+dfsg-1+rpt1) ...
Processing triggers for man-db (2.11.2-2) ...
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-4&#34;&gt;
Running the Demo
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Once the hardware was attached and the dependencies loaded, I had some
hope of interacting with the device.  The next step was to check out
the Waveshare e-paper repository from GitHub…&lt;/p&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone -q https://github.com/waveshare/e-Paper.git&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
… and then to try to run their demo script:&lt;/p&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; e-Paper/RaspberryPi_JetsonNano/python/examples
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;source&lt;/span&gt; ~/venv/bin/activate &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; python epd_2in13_V3_test.py&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&#34;example&#34;&gt;
/home/rpi/venv/lib/python3.11/site-packages/gpiozero/devices.py:295: PinFactoryFallback: Falling back from lgpio: No module named &amp;#39;lgpio&amp;#39;
  warnings.warn(
/home/rpi/venv/lib/python3.11/site-packages/gpiozero/devices.py:295: PinFactoryFallback: Falling back from rpigpio: No module named &amp;#39;RPi&amp;#39;
  warnings.warn(
/home/rpi/venv/lib/python3.11/site-packages/gpiozero/devices.py:295: PinFactoryFallback: Falling back from pigpio: No module named &amp;#39;pigpio&amp;#39;
  warnings.warn(
/home/rpi/venv/lib/python3.11/site-packages/gpiozero/devices.py:292: NativePinFactoryFallback: Falling back to the experimental pin factory NativeFactory because no other pin factory could be loaded. For best results, install RPi.GPIO or pigpio. See https://gpiozero.readthedocs.io/en/stable/api_pins.html for more information.
  warnings.warn(NativePinFactoryFallback(native_fallback_message))
INFO:root:epd2in13_V3 Demo
INFO:root:init and Clear
DEBUG:waveshare_epd.epd2in13_V3:e-Paper busy
DEBUG:waveshare_epd.epd2in13_V3:e-Paper busy release
DEBUG:waveshare_epd.epd2in13_V3:e-Paper busy
DEBUG:waveshare_epd.epd2in13_V3:e-Paper busy release
DEBUG:waveshare_epd.epd2in13_V3:e-Paper busy
DEBUG:waveshare_epd.epd2in13_V3:e-Paper busy release
DEBUG:waveshare_epd.epd2in13_V3:e-Paper busy
DEBUG:waveshare_epd.epd2in13_V3:e-Paper busy release
DEBUG:waveshare_epd.epd2in13_V3:e-Paper busy
DEBUG:waveshare_epd.epd2in13_V3:e-Paper busy release
INFO:root:1.Drawing on the image...
DEBUG:waveshare_epd.epd2in13_V3:e-Paper busy
[... lots more debugging info here...]
DEBUG:waveshare_epd.epd2in13_V3:e-Paper busy release
INFO:root:Goto Sleep...
DEBUG:waveshare_epd.epdconfig:spi end
DEBUG:waveshare_epd.epdconfig:close 5V, Module enters 0 power consumption ...
&lt;/pre&gt;
&lt;p&gt;
When I did this I saw their series of changes on the small screen
attached to the RPi Zero.  Exciting!  (The warnings in the output seem
to have to do w/ how the Python code wants to &amp;#34;speak GPIO&amp;#34; and does
not seem to negatively effect the outcome.)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-5&#34;&gt;
Rolling Our Own
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
I wanted to make my own display, and simply load the Waveshare driver
code as a Python package.  Unfortunately, I was unable to get
Waveshare&amp;#39;s (undocumented) &lt;code class=&#34;verbatim&#34;&gt;setup.py&lt;/code&gt; working with my virtualenv; the
quick-and-dirty workaround was to update &lt;code class=&#34;verbatim&#34;&gt;sys.path&lt;/code&gt; to find their
library, but use the virtualenv for the other dependencies installed
earlier.&lt;/p&gt;
&lt;p&gt;
As a proof of concept, I wrote a script to write the device IP address
to the screen:&lt;/p&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On pion:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cat &lt;span class=&#34;s&#34;&gt;&amp;lt;&amp;lt;EOF &amp;gt; /tmp/ip-demo.py
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;from PIL import Image, ImageDraw, ImageFont
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;import os
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;import socket
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;import sys
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;import warnings
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;SRCDIR = &amp;#34;/home/rpi/e-Paper/RaspberryPi_JetsonNano/python&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;sys.path.append(os.path.join(SRCDIR, &amp;#34;lib&amp;#34;))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;# Suppress GPIO library warning:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;with warnings.catch_warnings(action=&amp;#34;ignore&amp;#34;):
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;    from waveshare_epd import epd2in13_V4
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;def get_ip_address():
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;    s.connect((&amp;#39;8.8.8.8&amp;#39;, 80))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;    local_ip_address = s.getsockname()[0]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;    s.close()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;    return local_ip_address
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;picdir = os.path.join(SRCDIR, &amp;#39;pic&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;font16 = ImageFont.truetype(os.path.join(picdir, &amp;#39;Font.ttc&amp;#39;), 20)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;font24 = ImageFont.truetype(os.path.join(picdir, &amp;#39;Font.ttc&amp;#39;), 24)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;epd = epd2in13_V4.EPD()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;epd.init()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;image = Image.new(&amp;#39;1&amp;#39;, (epd.height, epd.width), 127)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;draw = ImageDraw.Draw(image)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;draw.text((10, 68), &amp;#39;pion ip address&amp;#39;, font = font16, fill = 0)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;draw.text((10, 90), f&amp;#39;{get_ip_address()}&amp;#39;, font = font24, fill = 0)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;epd.display(epd.getbuffer(image))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;epd.sleep()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;print(&amp;#34;OK&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;source&lt;/span&gt; venv/bin/activate &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; python /tmp/ip-demo.py&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&#34;example&#34;&gt;
OK
&lt;/pre&gt;
&lt;p&gt;
And here&amp;#39;s what it looked like on the Pi:&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/pion-ip.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/pion-ip_hu_2bbeefe20bda9d70.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-6&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-6&#34;&gt;
Prototyping a Better Display
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-6&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
At this point I felt ready to make a more informative display panel.
For this project I chose to display various information easily
accessible to the Pi:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&#34;verbatim&#34;&gt;hostname&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;On-board temperature&lt;/li&gt;
&lt;li&gt;IP address&lt;/li&gt;
&lt;li&gt;WiFi signal strength&lt;/li&gt;
&lt;li&gt;Uptime, including CPU busy fraction&lt;/li&gt;
&lt;li&gt;&amp;#34;Disk&amp;#34; (storage) size and usage fraction&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This meant reading online and running lots of little experiments to
try things out. The RPi Zero W 2 is powerful enough to edit and run
code on, but I&amp;#39;d rather use my editors on my laptop.  I did need to
explore the commands on the Pi needed to read out the quantities I was
interested in… here are some of the details. (This section relies
heavily on the the Literate Devops setup mentioned above; commands
were all launched on the RPi from this document, with the results
inserted directly inline.)&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-7&#34; class=&#34;outline-4&#34;&gt;
&lt;h4 id=&#34;headline-7&#34;&gt;
Temperature
&lt;/h4&gt;
&lt;div id=&#34;outline-text-headline-7&#34; class=&#34;outline-text-4&#34;&gt;
&lt;p&gt;
On Raspbian, &lt;code class=&#34;verbatim&#34;&gt;vcgencmd&lt;/code&gt; &lt;a href=&#34;https://www.tomshardware.com/how-to/raspberry-pi-benchmark-vcgencmd&#34;&gt;will tell you tons of things about your Pi&lt;/a&gt;.
Here we use it to read out the CPU temperature:&lt;/p&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On pion:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/usr/bin/vcgencmd measure_temp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&#34;example&#34;&gt;
temp=38.1&amp;#39;C
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-8&#34; class=&#34;outline-4&#34;&gt;
&lt;h4 id=&#34;headline-8&#34;&gt;
Memory
&lt;/h4&gt;
&lt;div id=&#34;outline-text-headline-8&#34; class=&#34;outline-text-4&#34;&gt;
&lt;p&gt;
&lt;code class=&#34;verbatim&#34;&gt;free&lt;/code&gt; is fairly common across Linux variants:&lt;/p&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On pion:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;free&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&#34;example&#34;&gt;
               total        used        free      shared  buff/cache   available
Mem:          436980      109240      213468         948      166464      327740
Swap:         102396           0      102396
&lt;/pre&gt;
&lt;p&gt;
It &lt;a href=&#34;https://www.man7.org/linux/man-pages/man1/free.1.html&#34;&gt;uses&lt;/a&gt; &lt;code class=&#34;verbatim&#34;&gt;/proc/meminfo&lt;/code&gt; under the hood:&lt;/p&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On pion:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cat /proc/meminfo&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&#34;example&#34;&gt;
MemTotal:         436980 kB
MemFree:          111828 kB
MemAvailable:     332116 kB
Buffers:           31068 kB
Cached:           220648 kB
SwapCached:         1184 kB
Active:           103120 kB
Inactive:         159140 kB
Active(anon):      10676 kB
Inactive(anon):       32 kB
Active(file):      92444 kB
Inactive(file):   159108 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:        102396 kB
SwapFree:          91900 kB
Zswap:                 0 kB
Zswapped:              0 kB
Dirty:               800 kB
Writeback:             0 kB
AnonPages:         10328 kB
Mapped:            29968 kB
Shmem:               164 kB
KReclaimable:      27584 kB
Slab:              43208 kB
SReclaimable:      27584 kB
SUnreclaim:        15624 kB
KernelStack:        1040 kB
PageTables:         1088 kB
SecPageTables:         0 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:      320884 kB
Committed_AS:     168456 kB
VmallocTotal:    1622016 kB
VmallocUsed:        7056 kB
VmallocChunk:          0 kB
Percpu:              416 kB
CmaTotal:         262144 kB
CmaFree:           86804 kB
&lt;/pre&gt;
&lt;p&gt;
Lots of interesting things here to try and understand someday… maybe.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-9&#34; class=&#34;outline-4&#34;&gt;
&lt;h4 id=&#34;headline-9&#34;&gt;
WiFi
&lt;/h4&gt;
&lt;div id=&#34;outline-text-headline-9&#34; class=&#34;outline-text-4&#34;&gt;
&lt;p&gt;
Searching around on online turned up two ways of getting WiFi signal strength:&lt;/p&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On pion:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; iwconfig wlan0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&#34;example&#34;&gt;
wlan0     IEEE 802.11  ESSID:&amp;#34;CornellCroft&amp;#34;
          Mode:Managed  Frequency:2.437 GHz  Access Point: F4:92:BF:7F:55:E4
          Bit Rate=72.2 Mb/s   Tx-Power=31 dBm
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Power Management:on
          Link Quality=64/70  Signal level=-46 dBm
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:1  Invalid misc:0   Missed beacon:0

&lt;/pre&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On pion:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cat /proc/net/wireless&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&#34;example&#34;&gt;
Inter-| sta-|   Quality        |   Discarded packets               | Missed | WE
 face | tus | link level noise |  nwid  crypt   frag  retry   misc | beacon | 22
 wlan0: 0000   61.  -49.  -256        0      0      0      1      0        0
&lt;/pre&gt;
&lt;p&gt;
I used the former.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-10&#34; class=&#34;outline-4&#34;&gt;
&lt;h4 id=&#34;headline-10&#34;&gt;
Disk Space
&lt;/h4&gt;
&lt;div id=&#34;outline-text-headline-10&#34; class=&#34;outline-text-4&#34;&gt;
&lt;p&gt;
&lt;code class=&#34;verbatim&#34;&gt;df&lt;/code&gt; &lt;a href=&#34;https://en.wikipedia.org/wiki/Df_(Unix)&#34;&gt;is at least 37 years old&lt;/a&gt; and works on almost anything Unix-like:&lt;/p&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On pion:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;df -k&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&#34;example&#34;&gt;
Filesystem     1K-blocks    Used Available Use% Mounted on
udev               81736       0     81736   0% /dev
tmpfs              43700     932     42768   3% /run
/dev/mmcblk0p2 122364296 4306628 111824324   4% /
tmpfs             218488       0    218488   0% /dev/shm
tmpfs               5120       8      5112   1% /run/lock
/dev/mmcblk0p1    522232   95702    426530  19% /boot/firmware
tmpfs              43696       0     43696   0% /run/user/1000
&lt;/pre&gt;
&lt;p&gt;
I only wanted the &amp;#34;root&amp;#34; filesystem, since it takes up almost all the space.&lt;/p&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On pion:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;df -k &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; egrep &lt;span class=&#34;s1&#34;&gt;&amp;#39;/$&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&#34;example&#34;&gt;
/dev/mmcblk0p2 122364296 4306624 111824328   4% /
&lt;/pre&gt;
&lt;p&gt;
I probably didn&amp;#39;t need to spring for 128 GB of storage on my MicroSD card.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-11&#34; class=&#34;outline-4&#34;&gt;
&lt;h4 id=&#34;headline-11&#34;&gt;
CPU Load and Uptime
&lt;/h4&gt;
&lt;div id=&#34;outline-text-headline-11&#34; class=&#34;outline-text-4&#34;&gt;
&lt;p&gt;
I found two methods:&lt;/p&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On pion:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uptime&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&#34;example&#34;&gt;
 16:21:16 up  1:15,  2 users,  load average: 0.08, 0.02, 0.01
&lt;/pre&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On pion:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cat /proc/uptime&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&#34;example&#34;&gt;
4544.69 18031.09
&lt;/pre&gt;
&lt;p&gt;
What is this proc file actually telling us?  RedHat &lt;a href=&#34;https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/s2-proc-uptime&#34;&gt;says&lt;/a&gt;,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The first value represents the total number of seconds the system has
been up. The second value is the sum of how much time each core has
spent idle, in seconds. Consequently, the second value may be greater
than the overall system uptime on systems with multiple cores.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
This implies that there are four cores on the board (something one can
confirm by looking at &lt;code class=&#34;verbatim&#34;&gt;/proc/cpuinfo&lt;/code&gt;); I actually didn&amp;#39;t know there
were four cores when I bought the unit.&lt;/p&gt;
&lt;p&gt;
Which suggests an interesting statistic, &amp;#34;Average CPU load since
boot&amp;#34;: (4544 * 4 - 18031) / 4544 * 4 = 0.8%.  I added that to my
dashboard.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-12&#34; class=&#34;outline-4&#34;&gt;
&lt;h4 id=&#34;headline-12&#34;&gt;
What else is there?
&lt;/h4&gt;
&lt;div id=&#34;outline-text-headline-12&#34; class=&#34;outline-text-4&#34;&gt;
&lt;p&gt;
There are always interesting things to be found in the proc
filesystem, which provides an easily-accessible file-like interface to
many aspects of the Linux kernel.&lt;/p&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On pion:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ls /proc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&#34;example&#34;&gt;
1     1485  272  4    48   72	asound	     kallsyms	    stat
10    1486  275  40   49   73	buddyinfo    key-users	    swaps
1012  1487  28	 41   490  813	bus	     keys	    sys
1070  15    29	 415  497  822	cgroups      kmsg	    sysrq-trigger
1071  16    293  416  5    918	cmdline      kpagecgroup    sysvipc
11    164   294  42   50   939	consoles     kpagecount     thread-self
1155  167   3	 421  503  94	cpu	     kpageflags     timer_list
1158  168   315  422  53   941	cpuinfo      latency_stats  tty
1159  17    317  423  54   942	crypto	     loadavg	    uptime
12    18    319  424  577  945	device-tree  locks	    version
1243  183   32	 426  587  947	devices      meminfo	    vmallocinfo
13    184   321  43   59   948	diskstats    misc	    vmstat
1327  19    322  430  590  95	driver	     modules	    zoneinfo
133   2     33	 433  6    951	execdomains  mounts
14    22    35	 434  60   952	fb	     net
140   228   36	 435  61   96	filesystems  pagetypeinfo
1411  23    374  436  62   967	fs	     partitions
1412  235   379  44   63   972	interrupts   schedstat
1418  24    38	 444  64   973	iomem	     self
1419  253   387  446  65   974	ioports      slabinfo
1484  27    39	 450  651  985	irq	     softirqs
&lt;/pre&gt;
&lt;p&gt;
Digging into these some other time might suggest more ideas for our
display.  (Incidentally, I remember from my time writing Linux device
drivers that it is not that hard to add &lt;code class=&#34;verbatim&#34;&gt;/proc&lt;/code&gt; entries to the kernel
– making a new proc file can be a good first kernel project.)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-13&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-13&#34;&gt;
Building the Mockup
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-13&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
With the above output snippets in hand I could go about building a mockup
to play around with locally on my laptop, then adapt to the Pi by wiring
in the actual shell commands in the appropriate places.&lt;/p&gt;
&lt;p&gt;
First, I created a new Python project for local use.  The only extra
library needed was &lt;code class=&#34;verbatim&#34;&gt;pillow&lt;/code&gt;, for image manipulation functions of the
kind used by the Waveshare demo.&lt;/p&gt;
&lt;p&gt;
I called my e-paper display &lt;code class=&#34;verbatim&#34;&gt;paperproto&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Locally, on my laptop:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; /Users/jacobsen/Programming/Python
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mkdir -p paperproto
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; paperproto
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python -m venv venv
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install pillow&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The &lt;a href=&#34;https://github.com/eigenhombre/paperproto&#34;&gt;resulting code is up on GitHub&lt;/a&gt;.  I won&amp;#39;t go through the entire
program, though it is based on the Python example I showed above.
There are, perhaps, two interesting features.  First, the elements in
the display are organized in a simple table which makes it easy to
play with the layout.  Here is the top-level table:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fields = [
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [None, get_hostname(), font24, [0, 0]],
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [None, get_ip_address(), font14, [0, 40]],
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [&amp;#34;WiFi&amp;#34;, get_wifi_strength(), font14, [120, 40]],
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [None, get_datetime(), font14, [0, 60]],
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [&amp;#34;Mem&amp;#34;, get_mem(), font14, [120, 60]],
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [&amp;#34;Disk&amp;#34;, get_disk(), font14, [0, 80]],
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [None, get_temp(), font14, [120, 80]],
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [&amp;#34;Up&amp;#34;, get_uptime(), font14, [0, 100]],
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The first field is an optional prefix for the information; the next,
an invocation of the relevant function to give the info in question;
followed by the font/size for the information.  The last column
consists of $x$, $y$ location.  By playing with these fields, the
design could be quickly changed.&lt;/p&gt;
&lt;p&gt;
Second, each of the functions shown has a &amp;#34;mockup&amp;#34; or local version, a
fixed string which was copied from the exploratory output shown above;
and a &amp;#34;real&amp;#34; or deployed version which executes on the Raspberry Pi
when it&amp;#39;s running &amp;#34;in production.&amp;#34; Here is an example of one of the
functions implemented in this dual manner:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;def get_uptime():
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    if is_pi:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        uptimestr = subprocess.check_output(&amp;#34;cat /proc/uptime&amp;#34;, shell=True).decode(
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &amp;#34;utf-8&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    else:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        uptimestr = &amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        4544.69 18031.09
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    match = re.search(r&amp;#34;(\d+\.\d+)\s+(\d+\.\d+)&amp;#34;, uptimestr)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    if not match:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        return &amp;#34;NO UPTIME&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    total_seconds = float(match.group(1))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    idle_cores = float(match.group(2))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    up_days = float(total_seconds / 86400)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    active_percent = float((1 - idle_cores / (4 * total_seconds)) * 100)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    return f&amp;#34;{up_days:.2f}d, active {active_percent:.2f}%&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This separation of mockup or &amp;#34;virtual hardware,&amp;#34; which can run
anywhere, and the &amp;#34;real&amp;#34; or target hardware, is something I have had
good success with in more serious embedded work.  The result in this case is
that I could iterate very quickly on my mockup, and produce something
like the following, without taking the trouble to copy things over to
the RPi:&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/proto.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/proto_hu_73d803cc39be8f2e.png&#34; style=&#34;width:400px; border:1px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
(&lt;code class=&#34;verbatim&#34;&gt;jjair&lt;/code&gt; is the hostname of my laptop, where the mockup is running.)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-14&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-14&#34;&gt;
Deployment
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-14&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Getting it to work on the Pi was as simple as copying the file over…&lt;/p&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Locally, on my laptop:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;scp /Users/jacobsen/Programming/Python/paperproto/proto.py pion:&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
… and making a small wrapper script to activate the virtualenv and
run the Python code:&lt;/p&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On pion:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cat &lt;span class=&#34;s&#34;&gt;&amp;lt;&amp;lt;EOF &amp;gt; proto
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;cd /home/rpi
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;source venv/bin/activate
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;python proto.py
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;chmod +x proto&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-15&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-15&#34;&gt;
Running &amp;#34;In Production&amp;#34;
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-15&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Finally we get to see the results!&lt;/p&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On pion:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./proto&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&#34;example&#34;&gt;
None pion 0 0
None 192.168.0.69 0 40
WiFi 70/70 -29 dBm 120 40
None 2024-01-24 14:23 0 60
Mem 25% 120 60
Disk 4G/122G 4% 0 80
None 38.6 C 120 80
Up 2.97d, active 0.57% 0 100
&lt;/pre&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/pion-final.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/pion-final_hu_817a573f332f8e42.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-16&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-16&#34;&gt;
Running It Periodically
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-16&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
We would like our display to regularly update and to survive reboots.
One option would be to create a long-running program which loops
forever, sleeping and then waking up to make its update.  And you
could make a &lt;code class=&#34;verbatim&#34;&gt;systemd&lt;/code&gt; service out of that, etc.  But &lt;code class=&#34;verbatim&#34;&gt;cron&lt;/code&gt; does this
sort of periodic thing wonderfully, and our wrapper script makes this
easy:&lt;/p&gt;
&lt;div class=&#34;src src-bash&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# On pion:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cat &lt;span class=&#34;s&#34;&gt;&amp;lt;&amp;lt;EOF &amp;gt; /tmp/cron
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;*/10 * * * * /home/rpi/proto &amp;gt;&amp;gt; /home/rpi/proto.out 2&amp;gt;&amp;amp;1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;crontab /tmp/cron &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm /tmp/cron&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
With the Pi on my desk and the cron job installed, I can see the
screen refreshing every ten minutes.  Job complete!&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/pion-in-situ.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/pion-in-situ_hu_e63c57e8382bc559.jpg&#34; style=&#34;width:200px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-17&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-17&#34;&gt;
Future Directions
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-17&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Here are some things I&amp;#39;d like to try:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Try a bigger display&lt;/li&gt;
&lt;li&gt;Look into wall-mounted displays&lt;/li&gt;
&lt;li&gt;Display remote info (weather, crime, financial, politics, …)&lt;/li&gt;
&lt;li&gt;Add sensors, e.g. air quality or room temperature, and make a
display for those&lt;/li&gt;
&lt;li&gt;Make it battery powered!  (But power consumption of Pis is
somewhat high for that.)&lt;/li&gt;
&lt;li&gt;Build a case for it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One final thing I might play with is partial updates to the display.
Waveshare supports a partial update mode where the entire screen need
not be redrawn when a region is changed.  Such updates are a little
more visually unobtrusive – as it is, the whole display flashes a few
times when it updates.&lt;/p&gt;
&lt;p&gt;
I&amp;#39;ve enjoyed having this little device on my desk this week.  I can
&lt;code class=&#34;verbatim&#34;&gt;ssh&lt;/code&gt; into it, poke around at the command line, shut it down and
unplug it, throw it in my backpack (wrapped in an ESD bag: no case yet!),
show it to friends.  When unplugged, the information on the display
stays unchanged until you plug it in again, another nice e-paper
feature. Otherwise it just sits there quietly, refreshing every ten
minutes, drawing a small amount of power, and forming a tiny part of
my physical and digital world.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>In Praise of Small Shell Scripts</title>
      <link>http://johnj.com/posts/in-praise-of-small-scripts/</link>
      <pubDate>Thu, 18 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/in-praise-of-small-scripts/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/tracks.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/tracks_hu_381adfbbca37b90d.png&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Over the decades I&amp;#39;ve relied heavily on &lt;code class=&#34;verbatim&#34;&gt;bash&lt;/code&gt; aliases and functions to
automate common tasks, resulting in a &lt;code class=&#34;verbatim&#34;&gt;.bash_profile&lt;/code&gt; that&amp;#39;s over a
thousand lines long.  But lately I find myself writing many small
scripts instead.&lt;/p&gt;
&lt;p&gt;
These tiny scripts, which live in a directory on my
&lt;code class=&#34;verbatim&#34;&gt;$PATH&lt;/code&gt;, have several advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They compose nicely, in line with &lt;a href=&#34;https://en.wikipedia.org/wiki/Unix_philosophy&#34;&gt;the Unix philosophy&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;They are reasonably portable.  If it works for me on Linux,
it&amp;#39;ll often work on my Mac, and &lt;em&gt;vice versa&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;They start quickly and are often as fast as something you&amp;#39;d write in
Python, Ruby, etc.&lt;/li&gt;
&lt;li&gt;Their file creation / modification times are distinct and provide a
history of what you worked on, when; by contrast, everything in
&lt;code class=&#34;verbatim&#34;&gt;.bash_profile&lt;/code&gt; is muddied together.&lt;/li&gt;
&lt;li&gt;They run in subprocesses without needing to get your
&lt;code class=&#34;verbatim&#34;&gt;.bash_profile&lt;/code&gt; involved (helpful for &lt;a href=&#34;https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-shell.html&#34;&gt;Org Babel&lt;/a&gt; or any situation
where you need to run your script from another program).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even something as trivial as an alias might get its own shell script,
if I can give it a name that&amp;#39;s easier to remember than the original
program name or combination of arguments.  Bash is an awkward language
for doing complex things, but expressive enough for simple tasks.  And
ChatGPT or other AI tools can often write simple scripts correctly for
you with little or no modification.&lt;/p&gt;
&lt;p&gt;
Here are some examples of small scripts I&amp;#39;ve been using recently:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&#34;verbatim&#34;&gt;ghjobs&lt;/code&gt; : Show status of my active CI jobs on GitHub (wrapper around
&lt;code class=&#34;verbatim&#34;&gt;gh&lt;/code&gt; tool); avoids having to go to the Web site, usable inside
&lt;code class=&#34;verbatim&#34;&gt;watch&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;&lt;code class=&#34;verbatim&#34;&gt;inprog&lt;/code&gt; / &lt;code class=&#34;verbatim&#34;&gt;ondeck&lt;/code&gt; : Show GitHub issues tagged as &amp;#34;in progress&amp;#34; or
&amp;#34;on deck,&amp;#34; across all my &amp;#34;work&amp;#34; repositories;&lt;/li&gt;
&lt;li&gt;(several programs) : Run one of many different build variants on the
embedded system I&amp;#39;m working on (build for Mac, build for target
hardware, build with fast tests, build all variants prior to pushing
code, etc.);&lt;/li&gt;
&lt;li&gt;(several programs) : Select random figurative references for
inspiration or to draw from (there are many variations of this one);&lt;/li&gt;
&lt;li&gt;&lt;code class=&#34;verbatim&#34;&gt;bashscript&lt;/code&gt; : Create a new &lt;code class=&#34;verbatim&#34;&gt;bash&lt;/code&gt; script in the appropriate place
(on &lt;code class=&#34;verbatim&#34;&gt;$PATH&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This last one is simple and helpful enough to show here:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;script_name=$1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cat &amp;lt;&amp;lt; EOF &amp;gt; ~/bin/$script_name
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;echo &amp;#34;OK&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;EOF
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;chmod +x ~/bin/$script_name&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Bash is boring and old (I still have &lt;code class=&#34;verbatim&#34;&gt;csh&lt;/code&gt; scripts from more than 30
years ago; &lt;code class=&#34;verbatim&#34;&gt;csh&lt;/code&gt; is &lt;a href=&#34;https://developer.ibm.com/tutorials/l-linux-shells/&#34;&gt;a close cousin&lt;/a&gt; of &lt;code class=&#34;verbatim&#34;&gt;bash&lt;/code&gt;).  It&amp;#39;s also everywhere
– on my Mac, inside my Docker containers, on my Raspberry Pi&amp;#39;s, on my
client&amp;#39;s servers, and on the cloud VMs I work on.&lt;/p&gt;
&lt;p&gt;
The &amp;#34;many small scripts&amp;#34; approach is complementary to how I use
&lt;code class=&#34;verbatim&#34;&gt;make&lt;/code&gt;, which I &lt;a href=&#34;http://johnj.com/posts/practices/#using-a-common-build-tool&#34;&gt;wrote about previously&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Finally, here&amp;#39;s the small script I wrote yesterday to hopefully &lt;a href=&#34;http://johnj.com/posts/2024-blogging-intentions/&#34;&gt;get me writing
more often&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;BLOGHOME=${BLOGHOME:-$HOME/Docs/websites/johnj22}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cd $BLOGHOME
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pwd
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;echo -n &amp;#34;Title for post: &amp;#34;; read title
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;postdate=$(date &amp;#39;+%Y-%m-%d&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;echo $title $postdate
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Turn the title lower case/kebab case, remove extra characters.  Thanks, ChatGPT!
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;title_kebab=$(echo &amp;#34;$title&amp;#34; |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              tr &amp;#39;[:upper:]&amp;#39; &amp;#39;[:lower:]&amp;#39; |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              tr -s &amp;#39;[:space:]&amp;#39; &amp;#39;-&amp;#39; |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              sed &amp;#39;s/[^a-z0-9-]//g; s/^-//; s/-$//&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;echo -n &amp;#34;$title&amp;#34; | pbcopy
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;file=&amp;#34;content/posts/$title_kebab&amp;#34;&amp;#34;.org&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;if [ ! -e $file ]; then
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    cat &amp;lt;&amp;lt;EOF &amp;gt; $file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;title: $title
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;date: $postdate
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;draft: true
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tags:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Org Mode stuff in case I export the document on its own without using Hugo:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#+OPTIONS: toc:nil num:nil
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;EOF
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fi
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ae $file  # `ae` is another small script: loads the resulting file in Emacs.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Typing &amp;#34;newpost&amp;#34; asks me for a title and pops me in my editor with all the
boilerplate needed to get me on my way.  Nice and easy.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>2024 Blogging Intentions</title>
      <link>http://johnj.com/posts/2024-blogging-intentions/</link>
      <pubDate>Wed, 17 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/2024-blogging-intentions/</guid>
      <description>
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/clouds-from-point.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/clouds-from-point_hu_24bf66dbc0c1c07.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
I can&amp;#39;t believe I haven&amp;#39;t written anything here in over a year.&lt;/p&gt;
&lt;p&gt;
I increasingly want to move my experimental, art, hobby, and
professional content away from platforms that exist to extract value
from me and my friends.  I&amp;#39;d also like to be less precious with this
space, to treat it in the casual, experimental fashion I would treat
Instagram or Facebook.  So I&amp;#39;m going to be playing around with posting
shorter posts, unfinished things, and worrying less about writing
complete articles (like I did at times while &lt;a href=&#34;http://johnj.com/tags/southpole/&#34;&gt;traveling to the Pole&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;
This is partly inspired by &lt;a href=&#34;https://www.calmabiding.me/&#34;&gt;recent efforts&lt;/a&gt; along somewhat similar lines
by my friend Stephen Starkey.&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Emacs, Continued
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
A few years ago I &lt;a href=&#34;http://johnj.com/posts/another-migration/&#34;&gt;started using the static site generator Hugo for
this site&lt;/a&gt;.  I think that&amp;#39;s still going reasonably well.&lt;/p&gt;
&lt;p&gt;
I use Emacs less than I used to, using VSCode for most programming
tasks recently (because Copilot).  But there are three things I still
use Emacs for habitually:&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-2&#34;&gt;
Writing prose
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Plain text is king, completely platform agnostic.  And though I&amp;#39;m not
sure why, I find it&amp;#39;s actually nice to use a different platform for
writing than for writing large amounts of production code.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-3&#34;&gt;
Git operations
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Magit is such a huge time saver.  I typically commit and push code
several, or dozens, of times a day – with Magit, these operations are
streamlined to the point where they are essentially frictionless.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-4&#34;&gt;
&amp;#34;&lt;a href=&#34;https://howardism.org/Technical/Emacs/literate-devops.html&#34;&gt;Literate Devops&lt;/a&gt;&amp;#34;
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Very often I want to record what I&amp;#39;m doing on some system in a
reproducible way without necessarily going through the process of
coding it up in a full-fledged infrastructure-as-code system like
Ansible, Terraform, etc.  Often the main thing is to record my
intentions (see &amp;#34;Writing prose,&amp;#34; above) and record the command-line
invocation required.  Org Mode and Org Babel are great for this.  I
also rely on &lt;code class=&#34;verbatim&#34;&gt;yasnippet&lt;/code&gt; to make this frictionless.  Here, for
example, is the snippet I use to create a Bash command:&lt;/p&gt;
&lt;pre class=&#34;example&#34;&gt;
#+BEGIN_SRC bash :exports both :results pp replace :eval never-export :prologue &amp;#34;exec 2&amp;gt;&amp;amp;1&amp;#34; :epilogue &amp;#34;true&amp;#34;
# Locally, on my laptop:
... actual shell command goes here ...
#+END_SRC
&lt;/pre&gt;
&lt;p&gt;
This snippet is bound to the abbreviation &lt;code class=&#34;verbatim&#34;&gt;begsh&lt;/code&gt;: when I type that
prefix plus &lt;code class=&#34;verbatim&#34;&gt;TAB&lt;/code&gt; I get the above Org-Babel snippet inserted directly
at point.  Then, to actually execute the command, typing &lt;code class=&#34;verbatim&#34;&gt;C-c C-c&lt;/code&gt;
within the code block runs it and &lt;em&gt;displays the results in the
document I&amp;#39;m writing.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
Here&amp;#39;s a slightly more complex snippet for executing code remotely on my Raspberry Pi 4:&lt;/p&gt;
&lt;pre class=&#34;example&#34;&gt;
#+BEGIN_SRC bash :async :exports both :results pp replace :eval never-export :prologue &amp;#34;exec 2&amp;gt;&amp;amp;1&amp;#34; :epilogue &amp;#34;true&amp;#34; :dir /ssh:4pi:
... actual shell command goes here ...
#+END_SRC
&lt;/pre&gt;
&lt;p&gt;
In this case, &lt;code class=&#34;verbatim&#34;&gt;C-c C-c&lt;/code&gt; actually runs the command remotely, on my Pi, and injects the
results directly into the document, as before.  The &lt;code class=&#34;verbatim&#34;&gt;:async&lt;/code&gt; option allows me to continue
editing elsewhere and wait for the results to be inserted when the command completes.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-5&#34;&gt;
Future Work
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
It would be nice to make adding images easier.  I still haven&amp;#39;t solved
the &amp;#34;post an image quickly or insert it into a document without
friction&amp;#34; problem (one of the things Instagram accomplishes… along
with a lot of extra stuff I wish they wouldn&amp;#39;t accomplish).  Ideally
adding images would be a drag-and-drop kind of operation, and would
handle any needed Bash, Emacs or Hugo operations automagically.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-6&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-6&#34;&gt;
Summary
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-6&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
I&amp;#39;m trying to use a set of simple tools to make blogging frictionless
and less precious… without indenturing myself to companies to whom &lt;a href=&#34;https://en.wikipedia.org/wiki/The_Social_Dilemma&#34;&gt;I
am the product&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Practices for Software Projects</title>
      <link>http://johnj.com/posts/practices/</link>
      <pubDate>Tue, 06 Sep 2022 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/practices/</guid>
      <description>&lt;p&gt;What follows is a selection of practices which I find helpful when
working with software projects, whether in public or in private, in
solo or in collaborative work.  Many of these practices are quite
standard, but some are, at best, unevenly practiced by either
commercial or academic software teams. Although they are especially
important for collaborative work, I like to follow these practices on
my own projects, both as a matter of professional habit, and because I
find them beneficial.  (This post is essentially an expanded version
of &lt;a href=&#34;https://gist.github.com/eigenhombre/204400c786f9dba3a8d3193d3ce1542a&#34;&gt;a
gist&lt;/a&gt;
which I made a few months ago, and which I have been endeavoring to
adhere to in my open source work ever since.)&lt;/p&gt;
&lt;div&gt;
    &lt;h2&gt;Table Of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#checklist&#34;&gt;Checklist&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#automated-tests&#34;&gt;Automated Tests&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&#34;#test-driven-development&#34;&gt;Test-Driven Development&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#probing-with-tests&#34;&gt;Probing With Tests&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#tradeoffs&#34;&gt;Tradeoffs&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#speed&#34;&gt;Speed&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#clean-tests&#34;&gt;Clean Tests&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#test-frameworks&#34;&gt;Test Frameworks&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#test-coverage&#34;&gt;Test Coverage&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#style-checks&#34;&gt;Style Checks&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#automated-builds&#34;&gt;Automated Builds&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&#34;#repeatability&#34;&gt;Repeatability&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#readmes&#34;&gt;READMEs&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#versions-and-releases&#34;&gt;Versions and Releases&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#issue-tracking&#34;&gt;Issue Tracking&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#other-helpful-practices&#34;&gt;Other Helpful Practices&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&#34;#using-a-common-build-tool&#34;&gt;Using a Common Build Tool&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#getting-invisible-feedback&#34;&gt;Getting &amp;ldquo;Invisible Feedback&amp;rdquo;&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#auto-generating-documentation&#34;&gt;Auto-Generating Documentation&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#summary&#34;&gt;Summary&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#acknowledgments&#34;&gt;Acknowledgments&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;


&lt;h1 id=&#34;checklist&#34;&gt;Checklist&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ll start with a checklist I use, then go into details for each item.
I try to check these items for each repository/project I work on.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Are there unit tests?
&lt;ul&gt;
&lt;li&gt;Are they maintained?&lt;/li&gt;
&lt;li&gt;Are they run often by developers&amp;hellip;&lt;/li&gt;
&lt;li&gt;&amp;hellip; and by builds that are triggered by every commit pushed to the
group repository?&lt;/li&gt;
&lt;li&gt;Is test coverage sufficient, to the extent agreed by the team?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Is there a README for the project?  Does it show:
&lt;ul&gt;
&lt;li&gt;What the project is for?&lt;/li&gt;
&lt;li&gt;How to build it and run tests?&lt;/li&gt;
&lt;li&gt;An example snippet showing it in action?&lt;/li&gt;
&lt;li&gt;Links to further documentation, if any?&lt;/li&gt;
&lt;li&gt;A license / copyright information?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Are builds generally repeatable?  Does firing the same build several
times for a recent commit yield the same result each time?&lt;/li&gt;
&lt;li&gt;Is an issue tracker being used to track bugs and planned work?&lt;/li&gt;
&lt;li&gt;Is there any relevant documentation that can be auto-generated?&lt;/li&gt;
&lt;li&gt;Is the software versioned?
&lt;ul&gt;
&lt;li&gt;Does your application / library know what version it is?&lt;/li&gt;
&lt;li&gt;Is the process of updating the version and releasing the code automated?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Are the following steps fully automated and executable via Make?
&lt;ul&gt;
&lt;li&gt;Running unit tests (&lt;code&gt;make test&lt;/code&gt; &amp;hellip; can be broken into &lt;code&gt;fast&lt;/code&gt; and &lt;code&gt;slow&lt;/code&gt; targets)&lt;/li&gt;
&lt;li&gt;Running code style checks and/or automated reformatting (&lt;code&gt;make lint&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Releasing the software, including building any needed artifacts (&lt;code&gt;make release&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Running all the tests in Docker, to ensure consistency with the automated build (&lt;code&gt;make docker&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;automated-tests&#34;&gt;Automated Tests&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s start with the most important item. Writing and continuously
running automated tests is always my first line of defense against
defects.  To quote &lt;a href=&#34;https://www.r7krecon.com/legacy-code&#34;&gt;Michael
Feathers&lt;/a&gt;,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Code without tests is bad code. It doesn&amp;rsquo;t matter how well written
it is; it doesn&amp;rsquo;t matter how pretty or object-oriented or
well-encapsulated it is. With tests, we can change the behavior of
our code quickly and verifiably. Without them, we don&amp;rsquo;t really know
if our code is getting better or worse.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;In what follows, &amp;ldquo;production code&amp;rdquo; means the code that actually does
what your program is trying to do.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a lot to be said about how to write tests, about the
difference between unit tests and integration tests, about test
frameworks, mocks, fakes, stubs, and so on.  These discussions shade
into ones about architectural patterns, object orientation,
organization of software into layers, etc.  To my view, these are all
secondary points. The main point is, is our software safe to change?
Only the presence, or absence, of tests, and the extent to which our
tests cover our production code determine the answer to this question.&lt;/p&gt;
&lt;h2 id=&#34;test-driven-development&#34;&gt;Test-Driven Development&lt;/h2&gt;
&lt;p&gt;When starting to write tests, a common question is, What should I
test? This question is usually easiest to answer &lt;em&gt;before you’ve
written the code you want to test&lt;/em&gt;. In that case, the the answer is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Write the tests that force you to write code that implements the
functionality you want.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;In other words, don&amp;rsquo;t write production code that a failing
test hasn&amp;rsquo;t forced you to write.  This is the key to test-driven
development (TDD).&lt;/p&gt;
&lt;p&gt;Note that I wrote &amp;ldquo;&lt;em&gt;a&lt;/em&gt; failing test,&amp;rdquo; above, rather than &amp;ldquo;failing tests&amp;rdquo;: the
process is best done in tiny increments, as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add a small increment of test code, which makes the tests fail
(&amp;ldquo;red&amp;rdquo;).&lt;/li&gt;
&lt;li&gt;Add a small increment of production code, which makes the tests
pass (&amp;ldquo;green&amp;rdquo;).&lt;/li&gt;
&lt;li&gt;Refactor as needed to keep the design of the code clean and simple
(repeat 3 in small steps, as needed, before going back to step 1).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ideally, each step in the &amp;ldquo;red&amp;hellip;green&amp;hellip;refactor&amp;hellip;&amp;rdquo; cycle is as
small as possible.  It should be the &amp;ldquo;red&amp;rdquo; step which actually pushes
you towards the functionality you want &amp;ndash; that failing test is a
statement about where you want the production code to go.&lt;/p&gt;
&lt;p&gt;If you find yourself writing multiple tests at once, or a more complex
test than is strictly needed at the moment, then stop and try to break
the problem into smaller steps.&lt;/p&gt;
&lt;p&gt;If you only write production code in response to a failing unit test,
then you know that code has both a reason to exist, and test coverage
for that code.  See Kent Beck&amp;rsquo;s &lt;em&gt;Test-Driven Development By Example&lt;/em&gt;
for a more detailed explanation of this process, or try it for
yourself.  I found when I adapted this pattern, about 14 years ago, my
productivity, the reliability of my software, and my enjoyment of
writing it, all increased noticeably.&lt;/p&gt;
&lt;h2 id=&#34;probing-with-tests&#34;&gt;Probing With Tests&lt;/h2&gt;
&lt;p&gt;On the other hand, maybe you&amp;rsquo;ve inherited some code from somebody
else. Or maybe you&amp;rsquo;ve written a bunch of untested code as a prototype,
and you want to consider it production code. In these situations, I
like to poke at the code in question using tests. These exploratory
tests can be a way to build understanding about how the code works,
and to document your findings. While reading the code under study, I
may find an area that looks like a defect: in that case, I write
tests to try to show the defect (or prove its absence).  Some of these
more speculative tests may not live on permanently in my test suite,
but they usually do.&lt;/p&gt;
&lt;p&gt;Importantly, whenever a defect is found, I always try to write a test
which detects that defect before I fix it, to guard against the defect
ever recurring.&lt;/p&gt;
&lt;h2 id=&#34;tradeoffs&#34;&gt;Tradeoffs&lt;/h2&gt;
&lt;p&gt;TDD affects development speed &amp;ndash; for very exploratory work, such as
building prototypes, it can be slower, though I find it usually helps
velocity as projects grow in complexity.  It definitely, in my
experience, helps add reliability.&lt;/p&gt;
&lt;p&gt;I like the analogy of rock climbing. If I&amp;rsquo;m scrambling over a short
wall, I don&amp;rsquo;t need a rope. Summiting a tall mountain face definitely
calls for serious protection. Bouldering close to the ground, not so
much, but be careful that your &amp;ldquo;bouldering&amp;rdquo; code doesn&amp;rsquo;t sneak into
your &amp;ldquo;summiting&amp;rdquo; code.&lt;/p&gt;
&lt;p&gt;There are times when strict TDD is less critical, and times when I
find it especially important. Obviously, for exploratory coding on a
prototype, TDD can be overkill.  Lispers armed with REPLs tend to be
especially comfortable with exploratory coding, but it is important to
shore up our REPL-driven snippets with tests, lest we lose the ability
to make changes safely. (A favorite technique for this situation is to
comment out bits of code and see if your existing tests fail, then TDD
your way back to bringing the code back in.)&lt;/p&gt;
&lt;p&gt;One place where I find TDD especially helpful is when the programming
is more difficult than usual.  With TDD, I handle the simple cases
first, and gradually add sophistication to my production code as I add
tests. As Robert Martin puts it: As the tests get more specific, the
production code becomes more general.&lt;/p&gt;
&lt;p&gt;If your software is hard to test, step back and take a look at the
design. A difficult testing story is often a symptom of an
overly-coupled design.  Picking apart the ball of yarn can be
difficult, and demands experience, but there are established
techniques for doing so. The book &lt;em&gt;Working Effectively with Legacy
Code&lt;/em&gt;, by Michael Feathers, treats this challenge in detail.&lt;/p&gt;
&lt;p&gt;While orienting your code around testability can help somewhat with
the design of that code (by encouraging less coupling, etc.), the
practice of TDD by itself will not guarantee a good, understandable,
maintainable design, as Rich Hickey explains in his talk &lt;a href=&#34;https://www.infoq.com/presentations/Simple-Made-Easy/&#34;&gt;Simple Made
Easy&lt;/a&gt; (which I highly recommend).  The wrong tests can actually
slow your ability to make design changes &amp;ndash; one needs to consider
design throughout the process, and be willing to rework both the tests
and the production code as needed if the design needs improving.&lt;/p&gt;
&lt;h2 id=&#34;speed&#34;&gt;Speed&lt;/h2&gt;
&lt;p&gt;A key point about all these tests: they must be fast. Fast, as in
running the entire test suite takes less than a couple seconds.  When
you start relying on tests as your safety net, you can only move as
fast as that net lets you move. If the tests take 10 seconds, a
minute, 10 minutes to run, progress will be slow. I often run my tests
multiple times a minute, literally every time I save a file in the
directory I&amp;rsquo;m working in. Or, if I am writing in a dialect of Lisp
such as Clojure or Common Lisp, I run the entire test suite with a
couple of keystrokes and expect instant visual feedback directly in my
editor. The good news is that most of the tests you write can be very
fast. Slow tests can be a design smell &amp;ndash; or at least a sign that
you&amp;rsquo;re testing at too high a level, through too many dependencies.  It
can take time to do the needed refactoring to make your tests fast,
but it is worth the investment.  Organizing your software in layers
and using mocking, dependency injection, or polymorphic dispatch&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
to implement simple test harnesses for individual layers can be
helpful here.&lt;/p&gt;
&lt;p&gt;Some tests are intrinsically slower. Examples include tests through a
database, or generative / fuzzing tests that programmatically generate
many examples and make assertions about program behavior while running
against those examples. These tests can run separately, such as after
every commit, or prior to a release. Invest in separating out slow
tests when needed.&lt;/p&gt;
&lt;h2 id=&#34;clean-tests&#34;&gt;Clean Tests&lt;/h2&gt;
&lt;p&gt;All code in your repository has a maintenance cost, including tests. I
try to keep test code as clean as production code. Because tests
can be repetitive, often with subtle variation between test cases, it
is important to use the abstractions available in your programming
language to make the test as clean and as readable as
possible. Squeezing out repetitive idioms is one area where
high-level languages such as Python, Clojure, or Lisps have an
advantage. But clean tests should be a goal regardless of language.&lt;/p&gt;
&lt;p&gt;Tests by example, also known as table-driven tests, are an excellent
way to get clean tests.  While Clojure&amp;rsquo;s &lt;code&gt;are&lt;/code&gt; macro (&lt;a href=&#34;http://johnj.com/posts/tests-by-example/&#34;&gt;trivially
portable to other Lisps&lt;/a&gt;)
gives the cleanest implementation I know of, table tests are also
common in Go and probably in several other languages as well.  It is
worth discovering if your language offers this construction, or, if
not, perhaps creating it, if possible.&lt;/p&gt;
&lt;h2 id=&#34;test-frameworks&#34;&gt;Test Frameworks&lt;/h2&gt;
&lt;p&gt;Though some communities (Java, Python) gravitate towards the
&lt;a href=&#34;https://en.wikipedia.org/wiki/XUnit&#34;&gt;xUnit&lt;/a&gt; style of test frameworks,
I find them to be overkill for most small projects, and for some large
ones.  Test frameworks try to address common areas of repetition in
tests, but the abstractions your project needs in order to write clean
tests may or may not be a natural fit for an existing, heavyweight
framework.  The job of your test framework is to make sure that every
assertion in your test suite is run, and that the build fails if any
of the assertions fail.  Good examples of lightweight test frameworks
include
&lt;a href=&#34;https://clojure.github.io/clojure/clojure.test-api.html&#34;&gt;&lt;code&gt;clojure.test&lt;/code&gt;&lt;/a&gt;
for Clojure and &lt;a href=&#34;https://github.com/lmj/1am&#34;&gt;1AM&lt;/a&gt; for Common Lisp
(perhaps with the addition of &lt;a href=&#34;http://johnj.com/posts/tests-by-example/&#34;&gt;my &lt;code&gt;are&lt;/code&gt;
macro&lt;/a&gt;).  Go&amp;rsquo;s &lt;code&gt;testing&lt;/code&gt; package is another.&lt;/p&gt;
&lt;p&gt;In some cases, a few test functions, a trivial test runner, and
judicious use of &lt;code&gt;assert&lt;/code&gt; are all you need.&lt;/p&gt;
&lt;h2 id=&#34;test-coverage&#34;&gt;Test Coverage&lt;/h2&gt;
&lt;p&gt;Tools are available for most languages which will generate test
coverage reports.  I am not a fan of strictly defined coverage targets
which fail test suites if coverage is below some fixed amount.
Nevertheless, I think that inspecting code coverage from time to time
can be helpful in identifying areas that need better tests.&lt;/p&gt;
&lt;p&gt;Discuss with your team what fraction of coverage you want to shoot for
in your project.  Some projects made up of mostly &lt;a href=&#34;https://en.wikipedia.org/wiki/Pure_function&#34;&gt;pure
functions&lt;/a&gt; can get to
100% easily, whereas others, perhaps heavy on error handling, UI code,
or integration with other services which are hard to mock, settle at
something less, perhaps 70%-80%.&lt;/p&gt;
&lt;p&gt;Monitor your repositories for slippage in coverage, and use coverage
reports to inform your work as you write code.&lt;/p&gt;
&lt;h1 id=&#34;style-checks&#34;&gt;Style Checks&lt;/h1&gt;
&lt;p&gt;It is my experience working with a variety of junior and senior
engineers that standardizing coding styles leads to more readable code
and higher quality overall.  Therefore, I like to run &amp;ldquo;linters&amp;rdquo; at the
same time I run my tests.  Linters are tools which check code style
according to agreed-upon guidelines and which raise an error when the
standard isn&amp;rsquo;t met.  Examples of linters are &lt;code&gt;lint&lt;/code&gt; in C,
&lt;code&gt;pycodestyle&lt;/code&gt; (formerly &lt;code&gt;pep8&lt;/code&gt;) in Python, and &lt;code&gt;kibit&lt;/code&gt; and &lt;code&gt;bikeshed&lt;/code&gt;
in Clojure.&lt;/p&gt;
&lt;p&gt;In addition to or in place of a linter, an automated code formatter, such
as &lt;code&gt;gofmt&lt;/code&gt; for the Go programming language, or &lt;code&gt;clang-format&lt;/code&gt; for C,
can reformat source code to adhere to community style rules.  Since
they fix style violations automatically, they have the benefit of not
slowing down your workflow or miring developers in endless
formatting discussions during code review, etc. The Go story is
especially successful in this regard, with the result that formatting
discussions are largely absent in the Go community.&lt;/p&gt;
&lt;p&gt;Most code formatters and style checkers are configurable.  These
options should be stored in a configuration inside the repository.  As
the team&amp;rsquo;s preferences and needs evolve, the configuration options can
be discussed and updated via pull requests or according to your team&amp;rsquo;s
code review procedures.&lt;/p&gt;
&lt;h1 id=&#34;automated-builds&#34;&gt;Automated Builds&lt;/h1&gt;
&lt;p&gt;Once the testing / linting rhythm is well established, automated
builds shore up the practice further. Every project should have a
primary build which is triggered on a build machine, known commonly as
a Continuous Integration (CI) server, whenever anybody pushes to the
master branch.  This build runs the automated tests for the project,
to ensure that no broken code gets shipped, or, if it does, that it
can be noticed and fixed as soon as possible.&lt;/p&gt;
&lt;p&gt;Rarely is the code I&amp;rsquo;m writing destined to run on the machine I&amp;rsquo;m
writing it on. Achieving fidelity between development and production
environments is frequently a challenge, though it is easier for some
languages than for others. Regardless of the language or target
platform, I&amp;rsquo;ll try to achieve as much parity as possible, generally
using Docker for builds.  The &lt;code&gt;Dockerfile&lt;/code&gt;s for these projects tend to
be simple: a few lines to install any needed dependencies, a line to
copy the files into the container, and a line to run the build tasks
using &lt;code&gt;make&lt;/code&gt; (more on that below).&lt;/p&gt;
&lt;p&gt;Since I host my repositories on GitHub, I use GitHub Actions for my
builds, generally running them within Docker except for highly
standardized builds such as for Go programs.&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;The history of the build success or failure can be easily seen on the
GitHub Actions page for that build.  If the history is not full of
mostly green builds, your developers are probably not running their
tests locally often enough, or there may a discrepancy between build and
development environments that needs addressing.&lt;/p&gt;
&lt;p&gt;I make sure that the README has a build badge which shows the most
recent build status.  These badges may seem frivolous, but I feel they
do give some insight into how well a project is maintained. Any build
failures also trigger an email to the committer, and optionally to any
people &amp;ldquo;watching&amp;rdquo; the repository on GitHub.&lt;/p&gt;
&lt;h2 id=&#34;repeatability&#34;&gt;Repeatability&lt;/h2&gt;
&lt;p&gt;Builds should be repeatable. That is to say, if a build fails for
particular commit, it should always fail, and if it succeeds for a
particular commit, it should always succeed.  Any other behavior makes
collaboration and troubleshooting harder (&amp;ldquo;it worked when I tried it /
on my machine&amp;rdquo;) and adds noise which slows the team down.  Tests that
fail only sometimes are usually a sign of race conditions,
particularly insidious bugs which tend to be hard to identify and
troubleshoot but which generally boil down to defects in the tests in
question and/or in the production code.&lt;/p&gt;
&lt;p&gt;To reiterate: unpredictable builds should be viewed as bugs, and
should not linger unaddressed.&lt;/p&gt;
&lt;h1 id=&#34;readmes&#34;&gt;READMEs&lt;/h1&gt;
&lt;p&gt;I like every repository to have a &lt;code&gt;README&lt;/code&gt; file, written in
&lt;a href=&#34;https://en.wikipedia.org/wiki/Markdown&#34;&gt;Markdown&lt;/a&gt;&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;. The file explains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;what the project is for;&lt;/li&gt;
&lt;li&gt;how to acquire, build and test it;&lt;/li&gt;
&lt;li&gt;gives an example snippet showing the project in action;&lt;/li&gt;
&lt;li&gt;provides links to further documentation, and&lt;/li&gt;
&lt;li&gt;has a license, along with a possible legal disclaimer (important for
open source projects where you may receive less legal cover, and
financial benefit, than for software written for the benefit of an
employer).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The example snippet shown in the README is especially important. It
not only gives a brief snapshot of your software in action, but it
also gives a feel for what it is like to use it and what it actually
does.  Examples can be found
&lt;a href=&#34;https://github.com/eigenhombre/hbook#examples&#34;&gt;here&lt;/a&gt; and
&lt;a href=&#34;https://github.com/eigenhombre/smallscheme#repl&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Whether for open source or closed/private work, stating license terms clearly
can be helpful. GitHub &lt;a href=&#34;https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/licensing-a-repository&#34;&gt;makes this especially
easy&lt;/a&gt;
now.  For closed-source, restricted repos I add a simple reminder in
place of a license: &amp;ldquo;&lt;code&gt;© &amp;lt;year&amp;gt; MyOrganization.  All rights reserved.&lt;/code&gt;&amp;rdquo;
For open source projects, I generally choose a fairly permissive
license, such as &lt;a href=&#34;https://choosealicense.com/licenses/mit/&#34;&gt;the one from
MIT&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On a personal note, for my own projects, I try to give every
repository its own unique artwork or photograph which appears at the
top of the README, an image ideally at least tangentially related in
to the project (this can be a challenge for a software project). I
find that it adds to my enjoyment while working on the software, and
helps me keep track of what repo I&amp;rsquo;m looking at at any given time. It
also ties my creative practices (painting, drawing, photography) with
my work in software development, areas of my life which otherwise
rarely overlap.&lt;/p&gt;
&lt;h1 id=&#34;versions-and-releases&#34;&gt;Versions and Releases&lt;/h1&gt;
&lt;p&gt;Your project should have versioned releases.  &lt;strong&gt;The process of making
releases should be entirely automated&lt;/strong&gt;. Typically, I make a release by
tagging the software in Git, and pushing the tags to GitHub. Depending
on the language and target platform, this could involve other steps,
like making a tarball, triggering a build on GitHub which makes the
release files available for download, or starting a deployment process
to a staging environment.&lt;/p&gt;
&lt;p&gt;Your program, Web service, app, or library should know and be able to
report what version it currently is.&lt;/p&gt;
&lt;p&gt;The release process should be scripted and have the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Make sure no code is uncommitted in the local directory&lt;/li&gt;
&lt;li&gt;Get the most recent version, e.g. &lt;code&gt;v0.0.99&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Determine the new version, e.g. &lt;code&gt;v0.0.100&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Update the local software so that it can report the new version
when asked&lt;/li&gt;
&lt;li&gt;Commit the updated local software, e.g. &lt;code&gt;git commit -am &amp;quot;Release v0.0.100&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Tag the new software, e.g. &lt;code&gt;git tag v0.0.100&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Push the new tag, e.g. &lt;code&gt;git push --tags&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Increment the local software version to indicate its &amp;ldquo;tainted&amp;rdquo;
(off-version) state, based on the new tagged version,
e.g. &lt;code&gt;v0.0.100-dirty&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Commit the local software again, e.g. &lt;code&gt;git commit -am &amp;quot;Taint post v0.0.100 release&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;An example release script can be seen
&lt;a href=&#34;https://github.com/eigenhombre/l1/blob/master/bumpver&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Any released artifacts (tarballs, jar files, etc.) should reflect the
release number, so if you&amp;rsquo;re generating release artifacts locally, it
should be done after Step 4, and before Step 8, above.  Otherwise, do
it on your CI server based on the tag you push in Step 7.&lt;/p&gt;
&lt;p&gt;This automation can take some effort up front to set up.  But it
removes a major source of resistance to doing releases, and allows for
tighter feedback loops.  An important component to this practice is to
keep the software releasable at all times &amp;ndash; use feature flags or
other mechanism to &amp;ldquo;hide&amp;rdquo; new features under development from users or
otherwise indicate their preliminary nature.  If software is always
releasable, and the automated tests are trustworthy, it will be safer
to quickly deploy bug fixes quickly when things go wrong, and
easier to track down bugs in production if they ever occur.&lt;/p&gt;
&lt;p&gt;If you can package your software using the target platform&amp;rsquo;s packaging
system (Homebrew, &lt;code&gt;apt&lt;/code&gt;, Clojars, PyPI, etc.), it goes a long way to
making installation easier, particularly when onboarding new
developers.  This is typically easier for open source projects, but
can be helpful for private repositories as well (an example is private
Maven repositories for the Clojure and Java ecosystems).&lt;/p&gt;
&lt;p&gt;A side note on semantic versioning: there are many passionate opinions
about how to do semver correctly. If you follow my open source
repositories, you&amp;rsquo;ll see mostly versions like &amp;ldquo;v0.0.123&amp;rdquo; rather than
&amp;ldquo;v1.10.1&amp;rdquo;.  I personally believe that semver is overrated &amp;ndash; in
particular, &lt;em&gt;breaking changes&lt;/em&gt; (so-called MAJOR revisions) are both
hostile to users and usually avoidable &amp;hellip; and should therefore be
extremely rare.  &lt;a href=&#34;https://www.youtube.com/watch?v=oyLBGkS5ICk&#34;&gt;This talk by Rich
Hickey&lt;/a&gt; explains the
viewpoint far better than I can.&lt;/p&gt;
&lt;p&gt;My advice is to avoid breaking changes whenever possible.  One
strategy for this is to version your APIs, so that older and newer
versions coexist together. Another is to simply call an existing
project done, and releasing a completely new project with extensive
changes, rather than breaking the old one for existing users.&lt;/p&gt;
&lt;h1 id=&#34;issue-tracking&#34;&gt;Issue Tracking&lt;/h1&gt;
&lt;p&gt;Your organization probably already does issue tracking, either through
JIRA or some similar system. If you don&amp;rsquo;t, consider using GitHub
Issues to track bugs and future work. I use these for my open source
projects, both to encourage other people to file issues, and to give
visibility into my to-do list.  When I make a commit, I tag the issue
number in the commit.  For example,&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git commit -am &amp;quot;Fix horrible race condition.  Fixes #66.&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;GitHub automatically cross links these commits with the issues
themselves, and in the case of the above example actually closes the
ticket automagically. JIRA can be configured to do the much same. This
kind of tracking can make it easier to understand what changes were
made when, and for what reason.  In some kinds of environments (e.g.,
highly regulated ones), this kind of change-tracking is a firm
requirement.&lt;/p&gt;
&lt;h1 id=&#34;other-helpful-practices&#34;&gt;Other Helpful Practices&lt;/h1&gt;
&lt;h2 id=&#34;using-a-common-build-tool&#34;&gt;Using a Common Build Tool&lt;/h2&gt;
&lt;p&gt;I frequently work in Python, C, Clojure, Go, and Common Lisp.  Each of
these languages has its own toolchain, which may be more or less
standard for the language, but I find that using
&lt;a href=&#34;https://en.wikipedia.org/wiki/Make_(software)&#34;&gt;&lt;code&gt;make&lt;/code&gt;&lt;/a&gt; to automate most
common tasks makes it very easy for me to remember how to carry them
out.&lt;/p&gt;
&lt;p&gt;Here are some make targets I write for most projects:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;make test&lt;/code&gt; runs all the unit tests locally.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make lint&lt;/code&gt; does any style checks.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make&lt;/code&gt; on its own runs any tests and linting / style checking (this
typically matches what runs on the build server after every push).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make release&lt;/code&gt; does everything needed to cause a release to be created.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make docker&lt;/code&gt; runs tests and linting steps inside a Docker container.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Though make is an old tool, with a strange, if powerful, syntax, it is
very fast, and relatively simple to use for the above use cases.  (I
find many modern build tools to be slower and more awkward to use than
Make for common operational tasks.)  The practice of using Make in
this way can be helpful in larger organizations, where several
different languages may be in use, and where developers may switch
from project to project with some regularity.  Some of my repos which
use this pattern are &lt;a href=&#34;https://github.com/eigenhombre/l1&#34;&gt;&lt;code&gt;l1&lt;/code&gt; (Go)&lt;/a&gt;,
&lt;a href=&#34;https://github.com/eigenhombre/smallscheme&#34;&gt;&lt;code&gt;smallscheme&lt;/code&gt; (Python)&lt;/a&gt;,
&lt;a href=&#34;https://github.com/eigenhombre/oatmeal&#34;&gt;&lt;code&gt;oatmeal&lt;/code&gt; (Clojure)&lt;/a&gt;,
&lt;a href=&#34;https://github.com/eigenhombre/cl-oju&#34;&gt;&lt;code&gt;cl-oju&lt;/code&gt; (Common Lisp)&lt;/a&gt;,
&lt;a href=&#34;https://github.com/eigenhombre/lexutil&#34;&gt;&lt;code&gt;lexutil&lt;/code&gt; (Go)&lt;/a&gt; and
&lt;a href=&#34;https://github.com/eigenhombre/hbook&#34;&gt;&lt;code&gt;hbook&lt;/code&gt; (Common Lisp)&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;getting-invisible-feedback&#34;&gt;Getting &amp;ldquo;Invisible Feedback&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;This trick relates to the &amp;ldquo;fast feedback&amp;rdquo; requirement mentioned
earlier and applies primarily to local development. If you can get
your computer to speak out loud, you can run your builds in another
terminal window and not even look at that window most of the time.
For example, on my Mac, I have the following running much of the day:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;conttest &#39;make &amp;amp;&amp;amp; say ok || say fail&#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here &lt;a href=&#34;https://github.com/eigenhombre/conttest&#34;&gt;&lt;code&gt;conttest&lt;/code&gt;&lt;/a&gt; is a
continuous testing tool I wrote, which runs the supplied argument, a
shell command, every time the current directory is updated.  When I
save a file I&amp;rsquo;m editing, I instantly hear the result.  If my tests are
doing what I think they should be doing in the moment, I can simply
hear the results as I go, without looking away from the code.  Once
again, this little genie is especially helpful when my tests are fast.&lt;/p&gt;
&lt;h2 id=&#34;auto-generating-documentation&#34;&gt;Auto-Generating Documentation&lt;/h2&gt;
&lt;p&gt;Look for opportunities to automate your documentation. Examples
include &lt;a href=&#34;https://github.com/eigenhombre/l1/blob/master/l1.md#api-index&#34;&gt;API documentation generated from the source
code&lt;/a&gt;,
&lt;a href=&#34;https://en.wikipedia.org/wiki/Literate_programming&#34;&gt;literate
programs&lt;/a&gt;, and
automating updates to READMEs based on program output (for example,
see &lt;a href=&#34;https://github.com/eigenhombre/l1/blob/master/updatereadme.py&#34;&gt;how the L1 README is
updated&lt;/a&gt;).&lt;/p&gt;
&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;Although these practices require some up-front investment, I find that
they increase my efficiency overall, especially when I&amp;rsquo;m working with
other collaborators.  Good, clean operational practices like these can
cut back on common sources of pain when working on long-running
software projects.&lt;/p&gt;
&lt;h1 id=&#34;acknowledgments&#34;&gt;Acknowledgments&lt;/h1&gt;
&lt;p&gt;My views have been influenced by discussions with former colleagues at
OppFi and OpinionLab over the past eight years.  &lt;a href=&#34;https://github.com/timhc22&#34;&gt;Timothy
Coleman&lt;/a&gt; wrote the original version of the
&lt;code&gt;bumpver&lt;/code&gt; release script linked above.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Examples include using protocols in Clojure, generics in Common
Lisp, and interfaces in Go.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;I prefer to run even Clojure builds in Docker, since I&amp;rsquo;ve been
bitten by subtle differences between my local and the target
deployment environments).&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;I actually prefer Org Mode for my own writing, but GitHub&amp;rsquo;s
Markdown support is better than its support for Org Mode.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Adding Tail Call Optimization to A Lisp Written in Go</title>
      <link>http://johnj.com/posts/tco/</link>
      <pubDate>Mon, 08 Aug 2022 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/tco/</guid>
      <description>
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/swirl5.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/swirl5_hu_20fd4752b571d675.jpg&#34; style=&#34;width:300px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
The last few days have been devoted to improving &lt;a href=&#34;https://github.com/eigenhombre/l1/&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;l1&lt;/code&gt;&lt;/a&gt;, the homegrown lisp I
&lt;a href=&#34;http://johnj.com/posts/l1/&#34;&gt;wrote about&lt;/a&gt; earlier this year.  A number of changes have landed in the
last week:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Implemented &lt;a href=&#34;https://github.com/eigenhombre/l1/issues/36&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;let&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://github.com/eigenhombre/l1/issues/42&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;defn&lt;/code&gt;&lt;/a&gt; and sugar for &lt;a href=&#34;https://github.com/eigenhombre/l1/issues/38&#34;&gt;quote&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Figured out &lt;a href=&#34;https://github.com/eigenhombre/l1#emacs-integration&#34;&gt;basic REPL integration&lt;/a&gt; with Emacs;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/eigenhombre/l1/issues/27&#34;&gt;Added numeric comparison operators&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/eigenhombre/l1/issues/33&#34;&gt;Reviewed my Minimum Viable Repo&lt;/a&gt; checklist for this project;&lt;/li&gt;
&lt;li&gt;Fixed &lt;a href=&#34;https://github.com/eigenhombre/l1/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc+label%3Abug&#34;&gt;four bugs&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also implemented the bulk of the automated tests &lt;a href=&#34;https://github.com/eigenhombre/l1/blob/master/tests.l1&#34;&gt;in the language
itself&lt;/a&gt;.  This was a decisive step forward in both ease of creating new
tests and confidence that the language was approaching something usable.&lt;/p&gt;
&lt;p&gt;
The work I&amp;#39;m happiest with, though, because it taught me the most, was implementing
&lt;a href=&#34;https://en.wikipedia.org/wiki/Tail_call&#34;&gt;tail call optimization&lt;/a&gt; (TCO) in the language, which the rest of this post will be about.&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Motivation
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
The need for some form of TCO became clear as I started to write more small programs in &lt;code class=&#34;verbatim&#34;&gt;l1&lt;/code&gt;.
Perhaps the simplest example is one that sums all the natural numbers up to $n$:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn sum-to-acc (n acc)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (cond ((zero? n) acc)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        (t (sum-to-acc (- n 1) (+ n acc)))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn sum-to (n)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (sum-to-acc n 0))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Calling &lt;code class=&#34;verbatim&#34;&gt;sum-to&lt;/code&gt; for small $n$ worked fine:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(sum-to 100)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;5050&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
However, larger $n$ blew up spectacularly:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(sum-to (* 1000 1000))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;runtime: goroutine stack exceeds 1000000000-byte limit
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;runtime: sp=0x14020500360 stack=[0x14020500000, 0x14040500000]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fatal error: stack overflow
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;runtime stack:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;runtime.throw({0x10289aa2b?, 0x10294ddc0?})
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	/opt/homebrew/Cellar/go/1.18.3/libexec/src/runtime/panic.go:992 +0x50
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;runtime.newstack()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	/opt/homebrew/Cellar/go/1.18.3/libexec/src/runtime/stack.go:1101 +0x46c
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;runtime.morestack()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	/opt/homebrew/Cellar/go/1.18.3/libexec/src/runtime/asm_arm64.s:314 +0x70
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goroutine 1 [running]:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;strings.(*Reader).ReadByte(0x1401c2820e0?)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	/opt/homebrew/Cellar/go/1.18.3/libexec/src/strings/reader.go:66 +0x98 fp=0x14020500360 sp=0x14020500360 pc=0x102883348
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;math/big.nat.scan({0x0, 0x1401c2820e0?, 0x0}, {0x1028dc7c8, 0x1401c2820e0}, 0xa, 0x0)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	/opt/homebrew/Cellar/go/1.18.3/libexec/src/math/big/natconv.go:126 +0x80 fp=0x14020500430 sp=0x14020500360 pc=0x10288b1e0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This happens, of course, because &lt;code class=&#34;verbatim&#34;&gt;sum-to-acc&lt;/code&gt; calls itself a million times,
each time storing a copy of its local bindings on the stack, which
eventually consumes all the space on the stack.&lt;/p&gt;
&lt;p&gt;
Getting simple recursive functions like this to work for large $n$ is
especially important because &lt;code class=&#34;verbatim&#34;&gt;l1&lt;/code&gt; doesn&amp;#39;t have loops (yet)!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
The Optimization
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
The solution is hinted at already in my test case.  Note that I did
not write &lt;code class=&#34;verbatim&#34;&gt;sum-to&lt;/code&gt; as a single recursive function, as follows:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn sum-to-notail (n)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (cond ((zero? n) 0)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        (t (+ n (sum-to-notail (- n 1))))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
While this function looks slightly simpler, it is harder for a
compiler or interpreter to optimize.  The difference is that, whereas
&lt;code class=&#34;verbatim&#34;&gt;sum-to-notail&lt;/code&gt; does some work after calling itself (by adding &lt;code class=&#34;verbatim&#34;&gt;n&lt;/code&gt; to
the result), &lt;code class=&#34;verbatim&#34;&gt;sum-to-acc&lt;/code&gt; calls itself from the &lt;em&gt;tail position&lt;/em&gt;; that is,
the function &lt;em&gt;returns immediately after calling itself&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;
People have &lt;a href=&#34;https://dspace.mit.edu/handle/1721.1/5753&#34;&gt;long realized&lt;/a&gt; that function calls from the tail position
can be replaced by updating the return address and then jumping
directly to the the new function without adding new information to the
stack.  This is something I had heard about for years and used in
various &amp;#34;functional&amp;#34; languages, without ever really implementing
myself (and therefore fully understanding).  It&amp;#39;s an easy thing to take for
granted without knowing anything about how it&amp;#39;s actually implemented
under the hood.  The failure of &lt;code class=&#34;verbatim&#34;&gt;sum-to-acc&lt;/code&gt; and similar recursive
functions, described above, meant I would have to learn.&lt;/p&gt;
&lt;p&gt;
Two very different blog posts were helpful to me in pointing the way
forward: &lt;a href=&#34;https://www.geoffreylitt.com/2018/01/15/adding-tail-calls-optimization-to-a-lisp-interpreter.html&#34;&gt;Adding tail call optimization to a Lisp interpreter in Ruby&lt;/a&gt;,
and &lt;a href=&#34;https://eklitzke.org/how-tail-call-optimization-works&#34;&gt;How Tail Call Optimization Works&lt;/a&gt;.  The posts focus on very
different languages (Ruby vs. C / assembler), but they each revolve
around what are effectively &lt;code class=&#34;verbatim&#34;&gt;GOTO&lt;/code&gt; statements.  I&amp;#39;m old enough to
remember BASIC and the pernicious &lt;code class=&#34;verbatim&#34;&gt;GOTO&lt;/code&gt; statement leading to
&amp;#34;spaghetti code.&amp;#34;  I doubt I&amp;#39;ve ever used a &lt;code class=&#34;verbatim&#34;&gt;GOTO&lt;/code&gt; statement in
production code, whose use in modern programming languages fell out of
favor in the aftermath of Dijkstra&amp;#39;s famous &lt;a href=&#34;https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf&#34;&gt;Go To Statement Considered
Harmful&lt;/a&gt; paper.  But the ability to transfer control to another part of
your program without invoking a function call is key to the
optimization.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-3&#34;&gt;
The Approach
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Since the strategy is general, let&amp;#39;s lose all the parentheses for a
moment and rewrite &lt;code class=&#34;verbatim&#34;&gt;sum-to-acc&lt;/code&gt; in language-agnostic pseudo-code:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;function sum-to-acc(n sum)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   if n == 0, then return sum
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   return sum-to-acc(n - 1, n + sum)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
In most languages (without TCO), when this function is called, the
values of &lt;code class=&#34;verbatim&#34;&gt;n&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;sum&lt;/code&gt;, as well as the return address, will be put on
the stack, whose evolution looks something like the following.&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-1&#34; href=&#34;#footnote-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; first invocation: [n=5, sum=0,  ret=sum-to:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;second invocation: [n=4, sum=5,  ret=sum-to-acc:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   [n=5, sum=0,  ret=sum-to:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; third invocation: [n=3, sum=9,  ret=sum-to-acc:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   [n=4, sum=5,  ret=sum-to-acc:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   [n=5, sum=0,  ret=sum-to:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fourth invocation: [n=2, sum=12, ret=sum-to-acc:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   [n=3, sum=9,  ret=sum-to-acc:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   [n=4, sum=5,  ret=sum-to-acc:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   [n=5, sum=0,  ret=sum-to:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; fifth invocation: [n=1, sum=14, ret=sum-to-acc:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   [n=2, sum=12, ret=sum-to-acc:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   [n=3, sum=9,  ret=sum-to-acc:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   [n=4, sum=5,  ret=sum-to-acc:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   [n=5, sum=0,  ret=sum-to:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; sixth invocation: [n=0, sum=15, ret=sum-to-acc:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   [n=1, sum=14, ret=sum-to-acc:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   [n=2, sum=12, ret=sum-to-acc:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   [n=3, sum=9,  ret=sum-to-acc:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   [n=4, sum=5,  ret=sum-to-acc:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   [n=5, sum=0,  ret=sum-to:...]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
At the sixth invocation, our terminating condition is reached, and 15
is returned, with all the pending stack frames popped off the stack.&lt;/p&gt;
&lt;p&gt;
With TCO, the implementation looks more like the following:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;function sum-to-acc(n sum)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;TOP:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   if n == 0, then return sum
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   n = n - 1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   sum = sum + n
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   GOTO TOP&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
as a result, the evolution of the stack looks as follows:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; first invocation: [n=5, sum=0, ret=sum-to:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;second invocation: [n=4, sum=5, ret=sum-to:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; third invocation: [n=3, sum=9, ret=sum-to:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;fourth invocation: [n=2, sum=12, ret=sum-to:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; fifth invocation: [n=1, sum=14, ret=sum-to:...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; sixth invocation: [n=0, sum=15, ret=sum-to:...]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
All those extra stack frames are gone: recursion has turned into a form of iteration.&lt;/p&gt;
&lt;p&gt;
Implementing TCO, then, has two ingredients:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Replace the values of the current arguments with their new values directly.&lt;/li&gt;
&lt;li&gt;Jump straight to the next call of the function without adding to the stack;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This low-level, imperative optimization makes high-level,
functional, recursive implementations efficient.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-4&#34;&gt;
Implementation
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
In thinking about the implementation for &lt;code class=&#34;verbatim&#34;&gt;l1&lt;/code&gt;, I was pleased to learn
that Go actually has a &lt;code class=&#34;verbatim&#34;&gt;goto&lt;/code&gt; statement.  However, my implementation
was poorly set up to use it.&lt;/p&gt;
&lt;p&gt;
Early in the implementation of &lt;code class=&#34;verbatim&#34;&gt;l1&lt;/code&gt;, I noticed that each data type
(numbers, atoms, and lists) had its own evaluation rules, so it made
sense to make use of Go&amp;#39;s features supporting polymorphism, namely
interfaces and receivers.  I had a &lt;code class=&#34;verbatim&#34;&gt;Sexpr&lt;/code&gt; interface which looked like the following:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;type Sexpr interface {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	String() string
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	Eval(*env) (Sexpr, error)  // &amp;lt;--------
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	Equal(Sexpr) bool
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Numbers and atoms, for example, had fairly simple &lt;code class=&#34;verbatim&#34;&gt;Eval&lt;/code&gt;
implementations.  For example,&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;func (a Atom) Eval(e *env) (Sexpr, error) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	if a.s == &amp;#34;t&amp;#34; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		return a, nil
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	ret, ok := e.Lookup(a.s)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	if ok {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		return ret, nil
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	ret, ok = builtins[a.s]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	if ok {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		return ret, nil
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	return nil, fmt.Errorf(&amp;#34;unknown symbol: %s&amp;#34;, a.s)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
And, of course, numbers eval to themselves:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;func (n Number) Eval(e *env) (Sexpr, error) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	return n, nil
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Lists, as you would expect, were more complicated – evaluating a list
expression needs to handle special forms&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-2&#34; href=&#34;#footnote-2&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;,
user-defined functions, and built-in functions.  Following the classic
&lt;a href=&#34;https://en.wikipedia.org/wiki/Structure_and_Interpretation_of_Computer_Programs&#34;&gt;Structure and Interpretation of Computer Programs&lt;/a&gt;, I separated the
core logic for function application into separate &lt;code class=&#34;verbatim&#34;&gt;Eval&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;Apply&lt;/code&gt;
phases.  And to prevent the &lt;code class=&#34;verbatim&#34;&gt;Eval&lt;/code&gt; for lists from getting too large, I
broke out the evaluation rules for different cases (e.g. for &lt;code class=&#34;verbatim&#34;&gt;let&lt;/code&gt; and
&lt;code class=&#34;verbatim&#34;&gt;cond&lt;/code&gt; special forms and for function application) into their own
functions.&lt;/p&gt;
&lt;p&gt;
In other words, I had evaluation logic spread over ten functions in
five files.  Sadly, the need to jump back to the beginning of an
evaluation rather than recursively calling &lt;code class=&#34;verbatim&#34;&gt;Eval&lt;/code&gt; again meant that
several of those nicely broken out functions had to be brought
together into a single function, because &lt;code class=&#34;verbatim&#34;&gt;goto&lt;/code&gt; &lt;a href=&#34;https://go.dev/ref/spec#Goto_statements&#34;&gt;does not support
jumping from one function to another&lt;/a&gt;.  (C has &lt;code class=&#34;verbatim&#34;&gt;setjmp&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;longjmp&lt;/code&gt;,
which effectively do this, but I would want to upgrade my IQ by a
few points before applying them in this situation.)&lt;/p&gt;
&lt;p&gt;
There were actually three cases where I was performing an evaluation
step right before returning, and the &lt;code class=&#34;verbatim&#34;&gt;goto&lt;/code&gt; pattern could be used:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;When evaluating code in the tail position of a user-defined function;&lt;/li&gt;
&lt;li&gt;When evaluating code in the last expression in a &lt;code class=&#34;verbatim&#34;&gt;let&lt;/code&gt; block;&lt;/li&gt;
&lt;li&gt;When evaluating code in the chosen branch of a &lt;code class=&#34;verbatim&#34;&gt;cond&lt;/code&gt; clause.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I wound up with code which with looks like the following.  Several
steps are indicated only with comments.  Note the tiny, easy-to-miss
&lt;strong&gt;&lt;code class=&#34;verbatim&#34;&gt;top:&lt;/code&gt;&lt;/strong&gt; label at the very beginning:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;// lisp.go
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;func eval(expr Sexpr, e *env) (Sexpr, error) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;strong&gt;top:&lt;/strong&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	switch t := expr.(type) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	case Atom:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		return evAtom(t, e)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	case Number:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		return expr, nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	// ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	case *ConsCell:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		if t == Nil {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			return Nil, nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		// special forms:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		if carAtom, ok := t.car.(Atom); ok {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			switch {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			case carAtom.s == &amp;#34;quote&amp;#34;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				return t.cdr.(*ConsCell).car, nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			case carAtom.s == &amp;#34;cond&amp;#34;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				pairList := t.cdr.(*ConsCell)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				if pairList == Nil {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					return Nil, nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				for {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					if pairList == Nil {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						return Nil, nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					pair := pairList.car.(*ConsCell)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					ev, err := eval(pair.car, e)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					if err != nil {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						return nil, err
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					if ev == Nil {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						pairList = pairList.cdr.(*ConsCell)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						continue
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					expr = pair.cdr.(*ConsCell).car
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;strong&gt;goto top&lt;/strong&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			// ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The code so far shows the evaluation for atoms, numbers, and &lt;code class=&#34;verbatim&#34;&gt;cond&lt;/code&gt;
statements.  &lt;code class=&#34;verbatim&#34;&gt;cond&lt;/code&gt; does not introduce any new bindings, but when the
first truthy condition is encountered, it evaluates the next argument
as its final act.  So the code above simply replaces the expression to
be evaluated, &lt;code class=&#34;verbatim&#34;&gt;expr&lt;/code&gt;, with the expression from the matching clause,
and then restarts the evaluation via &lt;code class=&#34;verbatim&#34;&gt;goto&lt;/code&gt;, without the overhead of a
separate function call.&lt;/p&gt;
&lt;p&gt;
The code for &lt;code class=&#34;verbatim&#34;&gt;let&lt;/code&gt; is somewhat similar:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			case carAtom.s == &amp;#34;let&amp;#34;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				args := t.cdr.(*ConsCell)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				if args == Nil {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					return nil, fmt.Errorf(&amp;#34;let requires a binding list&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				// ... code to set up let bindings ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				body := args.cdr.(*ConsCell)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				var ret Sexpr = Nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				for {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					var err error
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					if body == Nil {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						return ret, nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					// Implement TCO for `let`:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					if body.cdr == Nil {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						expr = body.car
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						e = &amp;amp;newEnv
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						&lt;strong&gt;goto top&lt;/strong&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					ret, err = eval(body.car, &amp;amp;newEnv)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					if err != nil {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;						return nil, err
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					body = body.cdr.(*ConsCell)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
The &lt;code class=&#34;verbatim&#34;&gt;for&lt;/code&gt; loop invokes a new &lt;code class=&#34;verbatim&#34;&gt;eval&lt;/code&gt; for each expression in the body of
the &lt;code class=&#34;verbatim&#34;&gt;let&lt;/code&gt;, &lt;em&gt;except&lt;/em&gt; for the last one: when the last expression is
reached, (the &lt;code class=&#34;verbatim&#34;&gt;cdr&lt;/code&gt; is &lt;code class=&#34;verbatim&#34;&gt;Nil&lt;/code&gt;), the last &lt;code class=&#34;verbatim&#34;&gt;eval&lt;/code&gt; is done by jumping to
the beginning of the function, once it has updated its environment to
point to include the new bindings.&lt;/p&gt;
&lt;p&gt;
The last use of this pattern is in function invocation proper, which looks similar:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			// (... code to set up new environment based on passed arguments ...)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			var ret Sexpr = Nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			for {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				if lambda.body == Nil {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					return ret, nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				// TCO:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				if lambda.body.cdr == Nil {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					expr = lambda.body.car
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					e = &amp;amp;newEnv
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;strong&gt;goto top&lt;/strong&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				ret, err = eval(lambda.body.car, &amp;amp;newEnv)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				if err != nil {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					return nil, err
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				lambda.body = lambda.body.cdr.(*ConsCell)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;
I&amp;#39;ve skipped various parts of &lt;code class=&#34;verbatim&#34;&gt;eval&lt;/code&gt; that aren&amp;#39;t relevant for TCO
optimization – if you&amp;#39;re interested, you can &lt;a href=&#34;https://github.com/eigenhombre/l1/blob/5873705ab1badb16dd1f1586bb7cc13467287187/lisp.go#L126&#34;&gt;check out the code&lt;/a&gt;
yourself.&lt;/p&gt;
&lt;p&gt;
To be clear, what we are optimizing is all tail calls, not just
recursive ones – though the recursive ones were the primary objective
due to the stack overflows reported above.&lt;/p&gt;
&lt;p&gt;
The end result is that &lt;code class=&#34;verbatim&#34;&gt;sum-to&lt;/code&gt; now can complete for large values of
$n$:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(sum-to (* 1000 1000))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;500000500000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Incidentally, a variant of our test case failed before I added the TCO
optimization to &lt;code class=&#34;verbatim&#34;&gt;let&lt;/code&gt; shown above; this now works, as well:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn sum-to-acc-with-let (n acc)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let ((_ 1))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (cond ((zero? n) acc)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          (t (sum-to-acc-with-let (- n 1) (+ n acc))))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn sum-to-with-let (n) (sum-to-acc-with-let n 0))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(sum-to-with-let (* 1000 1000))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;500000500000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-5&#34;&gt;
Conclusion
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Getting tail-call optimization to work was very satisfying… though
the &lt;code class=&#34;verbatim&#34;&gt;eval&lt;/code&gt; implementation is certainly more complex than before.  (Ah,
optimization!)&lt;/p&gt;
&lt;p&gt;
To ensure TCO continues to work, variants of &lt;code class=&#34;verbatim&#34;&gt;sum-to&lt;/code&gt; with and without &lt;code class=&#34;verbatim&#34;&gt;let&lt;/code&gt; are &lt;a href=&#34;https://github.com/eigenhombre/l1/blob/5873705ab1badb16dd1f1586bb7cc13467287187/Makefile#L17&#34;&gt;run
on every build&lt;/a&gt;, along with a few other short example programs.&lt;/p&gt;
&lt;p&gt;
After implementing TCO in my own code, I can appreciate and understand
the optimization better when I see it in the wild.  I fully expect to
use the pattern again when implementing future lisps (yes, I hope there
will be more).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr class=&#34;footnotes-separatator&#34;&gt;
&lt;div class=&#34;footnote-definitions&#34;&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-1&#34;&gt;&lt;a href=&#34;#footnote-reference-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;Note that this is a somewhat abstract representation: the details are language-specific.  The &lt;code class=&#34;verbatim&#34;&gt;ret=sum-to:...&lt;/code&gt; notation means that when the function returns, control will pass back to where it left off inside the &lt;code class=&#34;verbatim&#34;&gt;sum-to&lt;/code&gt; function.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-2&#34;&gt;&lt;a href=&#34;#footnote-reference-2&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;A special form is one that does not follow the normal evaluation rule for functions – it may evaluate its arguments once, many times, or not at all.  (I am glossing over macros for the time being; &lt;code class=&#34;verbatim&#34;&gt;l1&lt;/code&gt; does not have them yet.)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Tests by Example in Clojure and Common Lisp</title>
      <link>http://johnj.com/posts/tests-by-example/</link>
      <pubDate>Wed, 13 Jul 2022 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/tests-by-example/</guid>
      <description>&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/cosb-crab-88.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/cosb-crab-88_hu_21d61e4557aed826.png&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Histogram made by a 1980&amp;#39;s version of the author.
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
While playing around with some dice-rolling simulations recently in
Common Lisp (a topic for some future post, perhaps), I looked around
for a way of making histograms.  Finding none close to hand (it being
Common Lisp), it wasn&amp;#39;t too hard to &lt;a href=&#34;https://github.com/eigenhombre/hbook&#34;&gt;&amp;#34;roll my own&amp;#34; library&lt;/a&gt; (it
being… Common Lisp) to create text-based histograms in the tradition
of &lt;a href=&#34;https://cds.cern.ch/record/307945/files/&#34;&gt;libraries from CERN&lt;/a&gt; that I used as a fledgling physicist in the
late 1980s.&lt;/p&gt;
&lt;p&gt;
Since the project was just for fun, I drove most of the code forward
just by REPLing.  But I am trying to follow the same habits in my &amp;#34;for
fun&amp;#34; GitHub repositories as I would for paid work.  This means, among
other things, unit tests (in fact, for critical work I still prefer to
use &lt;a href=&#34;https://en.wikipedia.org/wiki/Test-driven_development&#34;&gt;TDD&lt;/a&gt; when I can).&lt;/p&gt;
&lt;p&gt;
So, in fleshing the tests out after the fact, I found myself
writing somewhat repetitive code that looked like this:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(test hist-values-test
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let ((h (histogram &amp;#39;(1 2) 2)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (is (= 2 (hist-count h)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (is (= 1 (hist-min h)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (is (= 2 (hist-max h)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (is (equalp #(1 1) (hist-bin-heights h)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (is (equalp #(1 2) (hist-bin-xs h))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let ((h (histogram &amp;#39;(1 2 1) 2)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (is (= 2 (hist-count h)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (is (= 1 (hist-min h)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (is (= 2 (hist-max h)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (is (equalp #(2 1) (hist-bin-heights h)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (is (equalp #(1 2) (hist-bin-xs h))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let ((h (histogram &amp;#39;(1 2 2 3) 3)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (is (= 3 (hist-count h)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (is (= 1 (hist-min h)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (is (= 3 (hist-max h)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (is (equalp #(1 2 1) (hist-bin-heights h)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (is (equalp #(1 2 3) (hist-bin-xs h)))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This is using the minimalist &lt;a href=&#34;https://github.com/lmj/1am&#34;&gt;1AM&lt;/a&gt; testing library, which I like for its
simplicity.  It is also similar to the standard &lt;a href=&#34;https://clojure.github.io/clojure/clojure.test-api.html&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;clojure.test&lt;/code&gt;&lt;/a&gt; library
I&amp;#39;m used to in Clojure.  It lacks, however, one important feature of
&lt;code class=&#34;verbatim&#34;&gt;clojure.test&lt;/code&gt;, namely the &lt;code class=&#34;verbatim&#34;&gt;are&lt;/code&gt; macro.  The macro allows one to
represent tests as a table of examples:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; Clojure code:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(deftest example
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (are
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [nums       prod]         ;; [1]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (= prod (reduce * nums))  ;; [2]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    []          1             ;; [3]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [1]         1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [0]         0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [0 1]       0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [1 1]       1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [2 2]       4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [2 3]       6
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [-1 -1]     1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [2 2 2]     8
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [1000 1000] 1000000))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
An invocation of &lt;code class=&#34;verbatim&#34;&gt;are&lt;/code&gt; has three parts: a vector of symbols to be
bound to values from the examples to follow [1]; the expression to be
evaluated for each example [2]; and the actual examples [3], with one
example per line being the usual, but optional, convention.  (In the
code above I have added extra spaces to make clear that &lt;code class=&#34;verbatim&#34;&gt;nums&lt;/code&gt; goes
with the first column of data, and &lt;code class=&#34;verbatim&#34;&gt;prod&lt;/code&gt; goes with the second
column.)&lt;/p&gt;
&lt;p&gt;
If at first you didn&amp;#39;t understand that code being tested ([2]) was
related to multiplication, you&amp;#39;d probably be able to figure it out
just by looking at the examples.  This is the primary advantage of
&lt;code class=&#34;verbatim&#34;&gt;are&lt;/code&gt;, namely that examples often provide as good or better
documentation than a written description of functionality does.&lt;/p&gt;
&lt;p&gt;
Missing such a compact testing idiom for my unit tests, I found myself
wondering how hard it would be to port it to Common Lisp.  The answer,
as you might expect, was: Not that hard.  As is often the case, there
is &lt;a href=&#34;https://github.com/clojure/clojure/blob/master/src/clj/clojure/test.clj#L572&#34;&gt;not much actual Clojure code&lt;/a&gt; behind the function in question, and
the corresponding Common Lisp code is similarly compact, as we shall
see.&lt;/p&gt;
&lt;p&gt;
If you look at the actual function definition in &lt;code class=&#34;verbatim&#34;&gt;clojure.test&lt;/code&gt;, most
of the macro proper is error checking; the actual work is delegated to
a completely different namespace, &lt;code class=&#34;verbatim&#34;&gt;clojure.template&lt;/code&gt; (in what follows, I
will ignore the error checking):&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; Clojure code:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defmacro are [argv expr &amp;amp; args]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ;; ... error checking
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  `(clojure.template/do-template ~argv (is ~expr) ~@args)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ;; ... error checking
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
A few macro expansions shows what&amp;#39;s happening:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; Clojure code:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(macroexpand-1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#39;(are [nums prod]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (= prod (reduce * nums))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    []      1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [1]     1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [2 2 2] 8))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;gives&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(clojure.template/do-template
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [nums prod]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (clojure.test/is (= prod (reduce * nums)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; []      1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [1]     1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [2 2 2] 8)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;code class=&#34;verbatim&#34;&gt;do-template&lt;/code&gt; is also a macro.  Simply running &lt;code class=&#34;verbatim&#34;&gt;macroexpand-1&lt;/code&gt; again shows
what it does:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; Clojure code:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(macroexpand-1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#39;(clojure.template/do-template
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   [nums prod]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   (clojure.test/is (= prod (reduce * nums)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   []      1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   [1]     1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   [2 2 2] 8))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;gives&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(do (clojure.test/is (= 1 (reduce * [])))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (clojure.test/is (= 1 (reduce * [1])))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (clojure.test/is (= 8 (reduce * [2 2 2]))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The expanded code is exactly equivalent to what you would write if you
didn&amp;#39;t have the &lt;code class=&#34;verbatim&#34;&gt;are&lt;/code&gt; macro.  This is accomplished by simply repeating
the code being invoked, but substituting the actual example values for
&lt;code class=&#34;verbatim&#34;&gt;nums&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;prod&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
In order to do accomplish the same in Common Lisp, we take a bottom-up approach.
First, we need to split our test cases into groups corresponding to
the number of columns in our &lt;code class=&#34;verbatim&#34;&gt;argv&lt;/code&gt; vector (in this case, 2):&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(let ((cases &amp;#39;(#()      1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               #(1)     1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               #(2 2 2) 8)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (partition-n 2 2 cases))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;((#()      1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (#(1)     1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (#(2 2 2) 8))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The output looks very similar to &lt;code class=&#34;verbatim&#34;&gt;cases&lt;/code&gt;, but each pair has been
grouped into its own list.  Here I use &lt;code class=&#34;verbatim&#34;&gt;partition-n&lt;/code&gt; from &lt;a href=&#34;https://github.com/eigenhombre/cl-oju&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;cl-oju&lt;/code&gt;&lt;/a&gt;, a
Common Lisp library I wrote specifically to take advantage of sequence
idioms from the Clojure core library; &lt;code class=&#34;verbatim&#34;&gt;partition-n&lt;/code&gt; is a translation
of Clojure&amp;#39;s &lt;code class=&#34;verbatim&#34;&gt;partition&lt;/code&gt; function.  (&lt;a href=&#34;https://github.com/clojure/clojure/blob/master/src/clj/clojure/template.clj#L55&#34;&gt;The equivalent code&lt;/a&gt; in
&lt;code class=&#34;verbatim&#34;&gt;clojure.template&lt;/code&gt; also uses &lt;code class=&#34;verbatim&#34;&gt;partition&lt;/code&gt; for the same purpose.)&lt;/p&gt;
&lt;p&gt;
We now need to flesh out those cases by making use of each example in
the expression being tested, whose Common Lisp translation is&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(is (= prod (reduce #&amp;#39;* nums)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
For example, if &lt;code class=&#34;verbatim&#34;&gt;nums&lt;/code&gt; is &lt;code class=&#34;verbatim&#34;&gt;#(2 2 2)&lt;/code&gt;, then &lt;code class=&#34;verbatim&#34;&gt;prod&lt;/code&gt; should be &lt;code class=&#34;verbatim&#34;&gt;8&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
In other words, we want our test cases to be:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(is (= 1 (reduce #&amp;#39;* #())))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(is (= 1 (reduce #&amp;#39;* #(1))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(is (= 8 (reduce #&amp;#39;* #(2 2 2)))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The replacement of symbols with their actual values in the Clojure
code &lt;a href=&#34;eww:&#34;&gt;is accomplished&lt;/a&gt; with a tree-walking function called
&lt;code class=&#34;verbatim&#34;&gt;postwalk-replace&lt;/code&gt;.  We can do it in Common Lisp with the &lt;code class=&#34;verbatim&#34;&gt;subst&lt;/code&gt;
function, which works on linear or nested lists:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(subst 3 &amp;#39;b &amp;#39;(* (+ b b) (/ b (- b b))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(* (+ 3 3) (/ 3 (- 3 3)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
But because we have multiple bindings or example arguments we have to
convert, we need to do it repeatedly:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defun apply-bindings (bindings case expr)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (loop with ret = expr
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        for b in bindings
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        for c in case
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        do (setf ret (subst c b ret))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        finally (return ret)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(apply-bindings &amp;#39;(x y) &amp;#39;(2 3) &amp;#39;(+ x y))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(+ 2 3)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Now we have everything we need to expand our test cases:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(let ((argv &amp;#39;(nums prod))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (expr &amp;#39;(is (= prod (reduce #&amp;#39;* nums))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (c (length argv))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (cases &amp;#39;(#()      1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               #(1)     1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               #(2 2 2) 8)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (loop for case in (partition-n c c cases)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        collect (apply-bindings argv case expr)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;((IS (= 1 (REDUCE #&amp;#39;* #())))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (IS (= 1 (REDUCE #&amp;#39;* #(1))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (IS (= 8 (REDUCE #&amp;#39;* #(2 2 2)))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
All the macro has to do is wrap this in a &lt;code class=&#34;verbatim&#34;&gt;progn&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defmacro are (argv expr &amp;amp;rest cases)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Analog of clojure.test/are.  Apply multiple assertions
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  based on some set up code and variations of one or more
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  variable bindings.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let ((c (length argv)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    `(progn ,@(loop for case in (partition-n c c cases)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    collect (apply-bindings argv case expr)))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
giving, for our example:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(macroexpand-1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#39;(are (nums prod)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   (is (= prod (reduce #&amp;#39;* nums)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   #()      1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   #(1)     1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   #(2 2 2) 8))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(PROGN
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (IS (= 1 (REDUCE #&amp;#39;* #())))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (IS (= 1 (REDUCE #&amp;#39;* #(1))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (IS (= 8 (REDUCE #&amp;#39;* #(2 2 2)))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This is equivalent to the macroexpansion of Clojure&amp;#39;s &lt;code class=&#34;verbatim&#34;&gt;are&lt;/code&gt; that we
saw above.  I leave as an exercise for the reader a further
exploration of &lt;code class=&#34;verbatim&#34;&gt;clojure.template/apply-template&lt;/code&gt; and its use in the
&lt;code class=&#34;verbatim&#34;&gt;do-template&lt;/code&gt; macro; and the addition of error checking such as making
sure the number example values is a multiple of the number of binding
arguments.&lt;/p&gt;
&lt;p&gt;
One rough edge that I glossed over: in my first attempt, my macro couldn&amp;#39;t find
&lt;code class=&#34;verbatim&#34;&gt;apply-bindings&lt;/code&gt; at compile time until I wrapped that function&amp;#39;s definition as follows:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(eval-when (:compile-toplevel :load-toplevel :execute)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (defun apply-bindings (...) ...))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This is apparently needed for functions used by macros defined in the
same file; it&amp;#39;s not an issue for functions defined in other
files. Since Clojure has a single-pass compiler, this sort of ceremony
is not needed for Clojure macros.&lt;/p&gt;
&lt;p&gt;
I expect to use this macro again, so will probably spin it out into a
small stand-alone library or incorporate it into a thin wrapper around
1AM.  Here it is in action in the &lt;code class=&#34;verbatim&#34;&gt;hbook&lt;/code&gt; library where our discussion started:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(test hist-values-test
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (are (h c mn mx heights xs)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (progn
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (is (= c (hist-count h)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (is (= mn (hist-min h)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (is (= mx (hist-max h)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (is (equalp heights (hist-bin-heights h)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (is (equalp xs (hist-bin-xs h))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (histogram &amp;#39;(1 2)     2)   2 1 2 #(1 1)   #(1 2)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (histogram &amp;#39;(1 2 1)   2)   2 1 2 #(2 1)   #(1 2)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (histogram &amp;#39;(1 2 2 3) 3)   3 1 3 #(1 2 1) #(1 2 3)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The code which &lt;code class=&#34;verbatim&#34;&gt;are&lt;/code&gt; makes possible is usually denser and can be
harder to parse initially than more repetitive test code would, as is
clear from this example.  However, I find the brevity of &lt;code class=&#34;verbatim&#34;&gt;are&lt;/code&gt; tests
extremely helpful, especially when comparing the test examples to each
another.  Such examples are especially helpful when calling out edge
cases where behavior changes. I have given such tables to stakeholders
many times, in order to make sure we are aligned on what the behavior
should be. (Even if the stakeholder doesn&amp;#39;t care about the details of
your implementation or your test code &lt;em&gt;per se&lt;/em&gt;, they probably &lt;em&gt;will&lt;/em&gt;
care about the specific examples you provide).&lt;/p&gt;
&lt;p&gt;
Parenthetically, here is &lt;a href=&#34;https://github.com/eigenhombre/hbook&#34;&gt;the histogramming library&lt;/a&gt; in action, showing the
distribution of the sum of 1000 six-sided dice:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defun d () (1+ (random 6)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defun dn (n) (loop repeat n sum (d)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(princ (hbook (loop repeat 100000 collect (dn 1000))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              80
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              30))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      4962                                       X  X
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      4791                                       X  X
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      4620                                     X X  X X
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      4449                                     X X  X X
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      4278                                     X XXXXXX X
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      4106                                     X XXXXXX X
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      3935                                   X XXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      3764                                   XXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      3593                                   XXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      3422                                   XXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      3251                                   XXXXXXXXXXXXX X
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      3080                                  XXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      2909                                X XXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      2738                                XXXXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      2566                                XXXXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      2395                                XXXXXXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      2224                               XXXXXXXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      2053                              XXXXXXXXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      1882                              XXXXXXXXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      1711                              XXXXXXXXXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      1540                             XXXXXXXXXXXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      1369                             XXXXXXXXXXXXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      1198                           XXXXXXXXXXXXXXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      1027                           XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       856                         XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       684                         XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       513                       XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       342                       XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       171                    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         0 X   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX    X
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                     111222233344544544443332211111
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                            11223568933623981977003313702313558540076333111
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      11244625381526456400925471219232518023527888048930961854221 1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           1   11235564827658185382948873231241519783970927498485883199710549330480234    1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           33333333333333333333333333333333333333333333333333333333333333333333333333333333
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           22222222233333333333333334444444444444445555555555555555666666666666666677777777
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           45566788900122344556778990112334456678890011233455677899001223445667889901123345
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           40639628518417306395285184073062952851740739629528417406396295184173063962851841
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           ................................................................................
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           04826059371504826159371604827159372604827159382604837159382604937159482604937150
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           02457912468913578024579134680135780246791346802357902467913568023579124689135680&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>(Yet Another) Lisp In Go</title>
      <link>http://johnj.com/posts/l1/</link>
      <pubDate>Sun, 27 Mar 2022 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/l1/</guid>
      <description>
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/l1.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/l1_hu_dae8791e33075232.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
For the past month I&amp;#39;ve been spending some free time writing another
Lisp implementation, this time in Go.  &lt;a href=&#34;http://johnj.com/posts/scheme-in-python/&#34;&gt;My previous attempt&lt;/a&gt; was a
subset of Scheme made in preparation for a class on the classic
&lt;a href=&#34;https://mitpress.mit.edu/sites/default/files/sicp/index.html&#34;&gt;Structure and Interpretation of Computer Programs&lt;/a&gt;.  That project
was great fun and I learned a lot.&lt;/p&gt;
&lt;p&gt;
I started learning Go late last year and began thinking about writing
another Lisp.  Go has garbage collection, a feature that has long
been an essential part of most Lisps&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-1&#34; href=&#34;#footnote-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.
Getting GC essentially for free would save a lot of time and effort.&lt;/p&gt;
&lt;p&gt;
Go is also extremely fast. For applications where startup performance is
not an issue, I&amp;#39;m pretty happy with Clojure most of the time.  But
working with Common Lisp in recent years, and Go more recently, has
spoiled me and made me hungry for more performance, especially for
short-running command-line utilities.&lt;/p&gt;
&lt;p&gt;
There are obviously other Lisps written in Go already, including
&lt;a href=&#34;https://github.com/candid82/joker&#34;&gt;Joker&lt;/a&gt;, a Clojure interpreter and linter.  But I wasn&amp;#39;t particularly
interested with implementing a particular Lisp dialect; rather, I
wanted to try to implement a language core that one could extend in a
variety of different directions, including &lt;a href=&#34;http://www.paulgraham.com/rootsoflisp.html&#34;&gt;implementing the language
in itself&lt;/a&gt;.  Other possible directions include graphics programming,
text-based games, and scripting. The working name of this Lisp is &lt;code class=&#34;verbatim&#34;&gt;l1&lt;/code&gt;
(&amp;#34;el-one&amp;#34;), hinting at a possible series of small, experimental Lisps.&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Features
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Here is a summary of what&amp;#39;s implemented &amp;amp; planned:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;l1 has&lt;/th&gt;
&lt;th&gt;doesn&amp;#39;t have&lt;/th&gt;
&lt;th&gt;will have&lt;/th&gt;
&lt;th&gt;might get&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;integers (&lt;a href=&#34;https://stackoverflow.com/questions/17564335/golang-math-big-what-is-the-max-value-of-big-int&#34;&gt;essentially unlimited size&lt;/a&gt;)&lt;/td&gt;
&lt;td&gt;keywords&lt;/td&gt;
&lt;td&gt;macros&lt;/td&gt;
&lt;td&gt;curses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;comments (&lt;code class=&#34;verbatim&#34;&gt;;; ....&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;maps&lt;/td&gt;
&lt;td&gt;syntax quote&lt;/td&gt;
&lt;td&gt;graphics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;atoms&lt;/td&gt;
&lt;td&gt;strings&lt;/td&gt;
&lt;td&gt;reader macros (`, &amp;#39;, …)&lt;/td&gt;
&lt;td&gt;subprocess / shells&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lists&lt;/td&gt;
&lt;td&gt;namespaces&lt;/td&gt;
&lt;td&gt;REPL / editor integration&lt;/td&gt;
&lt;td&gt;big floats&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4 special forms: &lt;code class=&#34;verbatim&#34;&gt;cond&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;def&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;lambda&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;quote&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;exceptions&lt;/td&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;let&lt;/code&gt; (as a macro)&lt;/td&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;error&lt;/code&gt; equiv.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;16 built-in functions&lt;/td&gt;
&lt;td&gt;loops&lt;/td&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;defun&lt;/code&gt; / &lt;code class=&#34;verbatim&#34;&gt;defn&lt;/code&gt; (as a macro)&lt;/td&gt;
&lt;td&gt;tail call optimization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;recursion&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;closures&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;byte code compilation/interpretation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
Performance
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
The &lt;a href=&#34;https://github.com/eigenhombre/l1/&#34;&gt;current implementation is on GitHub&lt;/a&gt;.  Its speed surprises me a bit.&lt;/p&gt;
&lt;p&gt;
Consider the following program in &lt;code class=&#34;verbatim&#34;&gt;l1&lt;/code&gt;, which computes a factorial:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; fact.l1: Return the factorial of `n`:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(def fact
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (lambda (n)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (cond ((eq 0 n) 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             (t (* n (fact (- n 1)))))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(print (fact 100))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;outputting&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;933262154439441526816992388562667004907159682643816214685929638
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;952175999932299156089414639761565182862536979208272237582511852
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;10916864000000000000000000000000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Its equivalent in Clojure (or its nimble alternative implementations,
Babashka or Joker) can be written as follows:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; fact.clj: Return the factorial of `n`:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(def fact
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (fn [n]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (cond (= 0 n) 1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          :else (*&amp;#39; n (fact (- n 1))))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(println (fact 100))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;… and in my Python Scheme implementation as&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; fact.scm
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(define (fact n)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (if (= n 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (* n (fact (- n 1)))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(display (fact 100))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
I also did the equivalent for Common Lisp.  I used &lt;a href=&#34;https://github.com/eigenhombre/oatmeal/&#34;&gt;Oatmeal&lt;/a&gt; to make a
skeleton Lisp project and used that to create an executable program
called &lt;code class=&#34;verbatim&#34;&gt;fact&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
The execution times break down thusly:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Running It&lt;/th&gt;
&lt;th class=&#34;align-right&#34;&gt;Execution Time (ms)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Clojure&lt;/td&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;clojure -M fact.clj&lt;/code&gt;&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;1729&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Babashka&lt;/td&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;bb fact.clj&lt;/code&gt;&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;smallscheme&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;scheme.py fact.scm&lt;/code&gt;&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;120&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Common Lisp&lt;/td&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;./fact&lt;/code&gt;&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;68&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Joker&lt;/td&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;joker fact.clj&lt;/code&gt;&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;59&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;l1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;l1 fact.l1&lt;/code&gt;&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
This is a very limited benchmark!  However, it does give a flavor for
start-up times.  Note that &lt;code class=&#34;verbatim&#34;&gt;l1&lt;/code&gt; is a tree-walking interpreter; I
wonder what speed might be possible if implemented with a byte code
interpreter.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-3&#34;&gt;
Lexing
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
I started the journey by writing the lexer.  A post on Hacker News led me
to &lt;a href=&#34;https://www.youtube.com/watch?v=HxaD_trXwRE&#34;&gt;this video&lt;/a&gt; where Rob Pike, of the core Go language team, describes
an elegant design for a lexer used in the Go templating library.  I
was able to extract the relevant bits into a fairly &lt;a href=&#34;https://github.com/eigenhombre/lexutil/&#34;&gt;general-purpose
library&lt;/a&gt; that I then used for this Lisp with &lt;a href=&#34;https://github.com/eigenhombre/l1/blob/master/lex.go&#34;&gt;relatively little code&lt;/a&gt; (of
course, one shouldn&amp;#39;t expect too much code when lexing a Lisp, since
there is not much syntax).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-4&#34;&gt;
Fun With Atoms and Lists
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
You may have noticed the lack of character strings in the feature
table, above.  &lt;a href=&#34;https://github.com/norvig/paip-lisp&#34;&gt;Many interesting Lisp programs&lt;/a&gt; don&amp;#39;t use traditional
strings (arrays of characters encoded as bytes), and I am curious to
see what can be done strictly without them, though I could see adding
them at some point.&lt;/p&gt;
&lt;p&gt;
Without strings, one will probably want to manipulate atoms in various
ways.  As a start, &lt;code class=&#34;verbatim&#34;&gt;l1&lt;/code&gt; introduces the notion of &amp;#34;splitting&amp;#34; (creating
a list from an atom or number) and &amp;#34;fusing&amp;#34; (joining such a list back
together again):&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;gt; (split (quote greenspun))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(g r e e n s p u n)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;gt; (split 1395871)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(1 3 9 5 8 7 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;gt; (fuse (quote (1 2 3 4 5)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;12345
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;gt; (randigits 10)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(6 1 5 4 4 8 8 3 0 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;gt; (randigits 10)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(2 7 5 4 7 9 1 6 6 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;gt; (fuse (randigits 1000))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;797522288353215977146173184650097900747324790200919947108552266
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;896559408664559755127840959435738695979408193086120089317097735
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;733247509700258597497415541421859295990446300938230591278544826
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;160148998280910399112793807480556810085222871423786728939605143
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;312291343715625109027024093962060686621901049553518883581864852
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;832439160531395519838325036388642484613231265974048363263732041
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;737675913066537856875008449087672272329301144164887429770199070
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;521721230755123684155760268379043481645391533460833091119801604
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;531684362848585264816725347753593965869286499060052823295397069
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;598147167103689429912992818647290966641807288375144076084638850
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;885562168375457674623070776900707693203757775691854059277861315
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;130019383408298242102129643369889134587749005021251080452606062
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;217504938911721968545635428643266561957454859338694605115003758
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;001930119736513921576952435852918640253473323143920762789645830
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;700672642264667728965761815048634636071828415705273836146286590
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;4892309215088593977646507232497245814663081971549675531
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-5&#34;&gt;
Testing
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
As with previous Lisps I&amp;#39;ve worked on, most of the tests were
represented in Go code as strings containing &lt;a href=&#34;https://github.com/eigenhombre/l1/blob/master/eval_test.go&#34;&gt;Lisp code and the
expressions they evaluate to&lt;/a&gt;.  Here are some examples, taken more or
less at random.&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        // `split` function
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {Cases(S(&amp;#34;(split)&amp;#34;, &amp;#34;&amp;#34;, &amp;#34;expects a single argument&amp;#34;))},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {Cases(S(&amp;#34;(split 1)&amp;#34;, &amp;#34;(1)&amp;#34;, OK))},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {Cases(S(&amp;#34;(split -1)&amp;#34;, &amp;#34;(-1)&amp;#34;, OK))},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {Cases(S(&amp;#34;(split -321)&amp;#34;, &amp;#34;(-3 2 1)&amp;#34;, OK))},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {Cases(S(&amp;#34;(split (quote a))&amp;#34;, &amp;#34;(a)&amp;#34;, OK))},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {Cases(S(&amp;#34;(split (quote (a b c)))&amp;#34;, &amp;#34;&amp;#34;, &amp;#34;expects an atom or a number&amp;#34;))},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {ECases(S(&amp;#34;(split (quote greenspun))&amp;#34;, &amp;#34;(g r e e n s p u n)&amp;#34;, OK))},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {ECases(S(&amp;#34;(split (* 12345 67890))&amp;#34;, &amp;#34;(8 3 8 1 0 2 0 5 0)&amp;#34;, OK))},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {ECases(S(&amp;#34;(len (split (* 99999 99999 99999)))&amp;#34;, &amp;#34;15&amp;#34;, OK))},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {ECases(S(&amp;#34;(split (quote greenspun))&amp;#34;, &amp;#34;(g r e e n s p u n)&amp;#34;, OK))},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {ECases(S(&amp;#34;(split (* 12345 67890))&amp;#34;, &amp;#34;(8 3 8 1 0 2 0 5 0)&amp;#34;, OK))},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {Cases(S(&amp;#34;(fuse (quote (1 2)))&amp;#34;, &amp;#34;12&amp;#34;, OK))},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {ECases(S(&amp;#34;(+ 2 (fuse (quote (1 2 3))))&amp;#34;, &amp;#34;125&amp;#34;, OK))},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {ECases(S(&amp;#34;(fuse (split 1295807125987))&amp;#34;, &amp;#34;1295807125987&amp;#34;, OK))},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {ECases(S(&amp;#34;(len (randigits 10))&amp;#34;, &amp;#34;10&amp;#34;, OK))},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {ECases(S(&amp;#34;((lambda (x) (+ 1 x)) 1)&amp;#34;, &amp;#34;2&amp;#34;, OK))},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {ECases(
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                S(&amp;#34;(def incrementer (lambda (n) (lambda (x) (+ x n))))&amp;#34;, &amp;#34;&amp;lt;lambda(n)&amp;gt;&amp;#34;, OK),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                S(&amp;#34;(def inc (incrementer 1))&amp;#34;, &amp;#34;&amp;lt;lambda(x)&amp;gt;&amp;#34;, OK),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                S(&amp;#34;(inc 5)&amp;#34;, &amp;#34;6&amp;#34;, OK),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                S(&amp;#34;(def add2 (incrementer 2))&amp;#34;, &amp;#34;&amp;lt;lambda(x)&amp;gt;&amp;#34;, OK),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                S(&amp;#34;(add2 5)&amp;#34;, &amp;#34;7&amp;#34;, OK),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        )},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Here &lt;code class=&#34;verbatim&#34;&gt;Cases&lt;/code&gt; is a utility function that create a local environment (a
possibly nested set of variable bindings) and evaluates one or more
expressions in that environment; &lt;code class=&#34;verbatim&#34;&gt;ECases&lt;/code&gt; (&lt;code class=&#34;verbatim&#34;&gt;E&lt;/code&gt; for Exemplary) is the
same, but saves its test cases in an &lt;a href=&#34;https://github.com/eigenhombre/l1/blob/master/examples.txt&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;examples.txt&lt;/code&gt;&lt;/a&gt; file which stores
a reduced set of illustrative cases, e.g. for adding to the README.
&lt;code class=&#34;verbatim&#34;&gt;S&lt;/code&gt; is a function which takes an expression to evaluate, the result
that should obtain, or an error message fragment which is expected if
the expression should fail.&lt;/p&gt;
&lt;p&gt;
This seems to be a good way to test a new language
implementation, though I plan to implement some generative / &amp;#34;fuzzing&amp;#34;
tests as well, since I doubt all the bugs have been found yet.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-6&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-6&#34;&gt;
Further Work
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-6&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Macros are next.  I&amp;#39;m pretty sure I know how I want to do them, and
for me the power of macros is the whole point of Lisp, or at least a
big part of the point.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-7&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-7&#34;&gt;
A Final Note on Performance, and Conclusion
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-7&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
To return to the performance discussion, above: a reasonable person
might object that &lt;code class=&#34;verbatim&#34;&gt;l1&lt;/code&gt; is so lean on features, that it&amp;#39;s not at all
surprising that it starts fast.  Clojure, on the other hand, leverages
the JVM, which has been tuned for decades for speed in long-running
processes, and also provides a thoughtful and comprehensive language
design that does many things no hobby language could easily support.&lt;/p&gt;
&lt;p&gt;
That being said, one thing I am excited about with this project is
this: pretty much anything I can do in Go (which is very many things)
can be added to my Lisp without &lt;em&gt;too&lt;/em&gt; much effort.  Conversely, to add
features to a Common Lisp or Clojure implementation would be very
difficult indeed.  Building a small language core that you can extend
in a variety of directions is a fun, if not necessarily entirely
practical, way to go.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr class=&#34;footnotes-separatator&#34;&gt;
&lt;div class=&#34;footnote-definitions&#34;&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-1&#34;&gt;&lt;a href=&#34;#footnote-reference-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;I met a speaker at LambdaJam 2015 who used his own Lisp for music performance. It was not garbage-collected, for real-time performance.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Migrating, Again</title>
      <link>http://johnj.com/posts/another-migration/</link>
      <pubDate>Thu, 03 Feb 2022 21:33:17 -0600</pubDate>
      
      <guid>http://johnj.com/posts/another-migration/</guid>
      <description>





&lt;a href=&#34;http://johnj.com/IMG_0565.jpeg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_0565_hu_ef9199bd3efc7f0b.jpeg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;p&gt;
For the fifth or sixth time I am performing a major migration of this site
from one implementation to another.&lt;/p&gt;
&lt;p&gt;
I&amp;#39;d like to do more writing, but &lt;a href=&#34;https://github.com/eigenhombre/organa&#34;&gt;the blogging sofware I wrote&lt;/a&gt; a few
years ago has been slowing me down, literally: it takes several
seconds to generate the whole site (something I do repeatedly when I
am making changes or additions to the site).  I want to be able to
post more freely, in smaller chunks, with frequent edits – to some
extent, to replicate the ease with which I can post on social media.&lt;/p&gt;
&lt;p&gt;
I also want to break down the walls between my artistic and my
software development work.  I&amp;#39;ve long tried to keep them separate
somehow and it no longer feels right, or even honest, to do this.&lt;/p&gt;
&lt;p&gt;
So: how to reduce friction in posting, and marry art and tech-related
posts in a single site?&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Past Lives
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Previously, this site was written in:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Post Format&lt;/th&gt;
&lt;th&gt;Static?&lt;/th&gt;
&lt;th class=&#34;align-right&#34;&gt;Era&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pure HTML&lt;/td&gt;
&lt;td&gt;HTML&lt;/td&gt;
&lt;td&gt;Y&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;1994&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Various hand-rolled Perl scripts&lt;/td&gt;
&lt;td&gt;HTML&lt;/td&gt;
&lt;td&gt;Y&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;2000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&#34;http://blosxom.sourceforge.net/&#34;&gt;Blosxom&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;Y&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;2005&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jekyll&lt;/td&gt;
&lt;td&gt;Markdown&lt;/td&gt;
&lt;td&gt;Y&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hand-built Django / Python app&lt;/td&gt;
&lt;td&gt;text / custom&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;2009&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hand-built &lt;a href=&#34;https://github.com/eigenhombre/unmark&#34;&gt;Clojure app (1)&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/S-expression&#34;&gt;S-expressions&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Y&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;2015&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hand-built &lt;a href=&#34;https://github.com/eigenhombre/organa&#34;&gt;Clojure app (2)&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://orgmode.org/&#34;&gt;Org Mode&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Y&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;2016&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;???&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td class=&#34;align-right&#34;&gt;now&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
One common thread: I&amp;#39;ve had good results with &amp;#34;static&amp;#34; Web sites:
generate content locally at home, then sync that content to the cloud.
The resulting Web sites load fast and are easy to cache.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
Requirements
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
What I want from the next iteration:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;FAST: less than 3 seconds to regenerate the entire site.  Ideally,
live-update browser pages when the site regenerates.&lt;/li&gt;
&lt;li&gt;A smooth path for integrating images of artworks in progress, and
technical blogging, on the same platform.&lt;/li&gt;
&lt;li&gt;Handle math expressions.&lt;/li&gt;
&lt;li&gt;Handle image galleries.&lt;/li&gt;
&lt;li&gt;A little &lt;em&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Wabi-sabi&#34;&gt;wabi-sabi&lt;/a&gt;&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Bonus if I can write my content in &lt;a href=&#34;https://orgmode.org/&#34;&gt;Org Mode&lt;/a&gt; instead of Markdown.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-3&#34;&gt;
Hugo
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
I&amp;#39;ve been diving deep into &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt; because it checks most of those
boxes: the site you&amp;#39;re currently looking at was
generated with Hugo&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-1&#34; href=&#34;#footnote-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.
(Currently it takes less than a tenth of a second to generate the entire site.)&lt;/p&gt;
&lt;p&gt;
Hugo does have a learning curve compared to other systems, which makes
sense given the richness of its feature set.  I found some helpful
hints on &lt;a href=&#34;https://lucidmanager.org/productivity/create-websites-with-org-mode-and-hugo/&#34;&gt;this site&lt;/a&gt; for working with Org Mode in Hugo.&lt;/p&gt;
&lt;p&gt;
So far, I&amp;#39;ve been happy with Hugo, though it&amp;#39;s a little strange to use
someone else&amp;#39;s software for this site!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr class=&#34;footnotes-separatator&#34;&gt;
&lt;div class=&#34;footnote-definitions&#34;&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-1&#34;&gt;&lt;a href=&#34;#footnote-reference-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;Any &lt;em&gt;wabi-sabi&lt;/em&gt;, always hard to come by on a computer, probably has to emerge from the visual design and, maybe, the writing.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>About</title>
      <link>http://johnj.com/about/</link>
      <pubDate>Wed, 02 Feb 2022 20:17:03 -0600</pubDate>
      
      <guid>http://johnj.com/about/</guid>
      <description>&lt;p&gt;
See &lt;a href=&#34;http://johnj.com/now&#34;&gt;my Now Page&lt;/a&gt; for what I&amp;#39;m up to these days.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>From Elegance to Speed</title>
      <link>http://johnj.com/posts/from-elegance-to-speed/</link>
      <pubDate>Wed, 25 Sep 2019 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/from-elegance-to-speed/</guid>
      <description>
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Making Things Fast
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/plane.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/plane_hu_a29fb6edbf8b159e.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
A while back, we used &lt;a href=&#34;http://johnj.com/posts/lazy-physics/&#34;&gt;a toy particle physics trigger&lt;/a&gt; to explore
concepts in lazy evaluation and functional programming in Clojure. We
came up with the following function which selected groups of eight
events clustered close together in time:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn smt-8 [times]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (-&amp;gt;&amp;gt; times
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (partition 8 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (map (juxt identity
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                  (comp (partial apply -)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        (juxt last first))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (filter (comp (partial &amp;gt; 1000) second))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Though elegant, this function processed events at a rate of 250 kHz,
which I found slightly disappointing, performance-wise.&lt;/p&gt;
&lt;p&gt;
I have been interested in writing faster programs lately, which is one
of the reasons I&amp;#39;ve been &lt;a href=&#34;http://johnj.com/posts/lisp-projects/&#34;&gt;learning Common Lisp&lt;/a&gt;. Common Lisp lets you
create extremely high-level programming constructs, but also lets you
get closer to the metal when you need to. In this post we&amp;#39;ll look at
some ways for improving performance and compare our results to the
original 250 kHz event rate.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
First Steps
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
The first step is to translate our code as is to Common Lisp. We&amp;#39;re
going to punt entirely on the question of laziness for this post,
though we might take it up in the future.&lt;/p&gt;
&lt;p&gt;
Here&amp;#39;s my first attempt. We have to start with our source of random
times. In Clojure, we had:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(def times (iterate #(+ % (rand-int 1000)) 0))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Since I&amp;#39;m going to benchmark performance, we&amp;#39;ll need to set a limit to the number of events (times) we&amp;#39;ll process. So, in Common Lisp:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defun time-sequence (n)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (loop repeat n
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     for y = 0 then (+ y (random 1000))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     collect y))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
where &lt;code class=&#34;verbatim&#34;&gt;n&lt;/code&gt; is the number of event times to process.  Here and
throughout what follows, I&amp;#39;m using the &lt;code class=&#34;verbatim&#34;&gt;loop&lt;/code&gt; macro, which is a Swiss
army knife for iteration with a somewhat strange, non-Lispy, but
readable syntax.&lt;/p&gt;
&lt;p&gt;
We also want to set our random state so as to guarantee different
results each time we execute our simulation:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(setf *random-state* (make-random-state t))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
My first attempt in Common Lisp looked like this benchmarking snippet:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(timing
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (length
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (-&amp;gt;&amp;gt; 1000000
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         time-sequence
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (partition-n 8 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (mapcar (juxt #&amp;#39;car (compose #&amp;#39;car #&amp;#39;last) #&amp;#39;identity))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (mapcar #&amp;#39;(lambda (l) `(,(- (cadr l) (car l)) ,(caddr l))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (remove-if-not #&amp;#39;(lambda (l) (&amp;lt; (car l) 1000))))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This is less lovely than the Clojure, partly because of all the
hash-quoting of functions (Common Lisp is a &lt;a href=&#34;https://stackoverflow.com/questions/4578574/what-is-the-difference-between-lisp-1-and-lisp-2&#34;&gt;Lisp-2&lt;/a&gt;, and Clojure is a
Lisp 1). &lt;code class=&#34;verbatim&#34;&gt;-&amp;gt;&amp;gt;&lt;/code&gt; is from the &lt;code class=&#34;verbatim&#34;&gt;arrow-macros&lt;/code&gt; library, and &lt;code class=&#34;verbatim&#34;&gt;compose&lt;/code&gt; is
from the &lt;code class=&#34;verbatim&#34;&gt;cl-utilities&lt;/code&gt; library.  The other Clojure-ish functions,
&lt;code class=&#34;verbatim&#34;&gt;partition-n&lt;/code&gt; (a replacement for Clojure&amp;#39;s &lt;code class=&#34;verbatim&#34;&gt;partition&lt;/code&gt;, whose name
collides with an entirely different function in Common Lisp) and
&lt;code class=&#34;verbatim&#34;&gt;juxt&lt;/code&gt; are from &lt;a href=&#34;https://github.com/eigenhombre/cl-oju&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;cl-oju&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://github.com/eigenhombre/cl-oju&#34;&gt;a small library&lt;/a&gt; I&amp;#39;ve been writing for those
still-frequent times when I want a Clojure function or idiom in Common
Lisp. (The library ignores laziness for now, since I haven&amp;#39;t needed it
yet.)&lt;/p&gt;
&lt;p&gt;
&lt;code class=&#34;verbatim&#34;&gt;timing&lt;/code&gt; is a macro I adapted from &lt;a href=&#34;https://lispcookbook.github.io/cl-cookbook/dates_and_times.html&#34;&gt;the Common Lisp Cookbook&lt;/a&gt;, which
captures both the results of a computation and the elapsed CPU time
used (not wall clock time) in msec:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defmacro timing (&amp;amp;body forms)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let ((run1 (gensym))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	(run2 (gensym))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	(result (gensym)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    `(let ((,run1 (get-internal-run-time))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	   (,result (progn ,@forms))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	   (,run2 (get-internal-run-time)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       `(duration ,(- ,run2 ,run1) msec... result ,,result))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
For now, &lt;code class=&#34;verbatim&#34;&gt;result&lt;/code&gt; is simply the number of eight-fold time clusters
occuring within 1000 units of time. The execution time was roughly a
second for the first few times I ran this:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#39;(DURATION 1045 MSEC... RESULT 235)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#39;(DURATION 1554 MSEC... RESULT 201)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#39;(DURATION 827 MSEC... RESULT 164)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This already processed events at 1 MHz, roughly 4x faster than the
Clojure speed of 250kHz.&lt;/p&gt;
&lt;p&gt;
Later, however, when I revisited the code, I noticed it ran significantly
faster:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#39;(DURATION 435 MSEC... RESULT 193)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#39;(DURATION 279 MSEC... RESULT 189)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#39;(DURATION 205 MSEC... RESULT 177)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#39;(DURATION 601 MSEC... RESULT 180)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This is 2.6 Mhz, &lt;strong&gt;10x the Clojure code speed&lt;/strong&gt;.  It took me a while to
figure out that I had changed the SBCL heap size in order to handle
larger arrays for testing (this is one area where laziness would
help!). The larger heap size was making the code run faster.&lt;/p&gt;
&lt;p&gt;
It should be said at this point that I made no attempt in my original
blog post to optimize the Clojure code for performance. Nevertheless,
I think it&amp;#39;s interesting that my first attempt to write the same
algorithm in Common Lisp, using roughly the same idioms, performed so
much faster.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-3&#34;&gt;
Interlude
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Looking back over my career, it seems I have been moving gradually
from fast, lower-level languages to slower, more expressive,
high-level languages: &lt;code class=&#34;verbatim&#34;&gt;FORTRAN&lt;/code&gt; and C, to Perl and Python, then to
Clojure (which is faster than Python for most long-running programs,
while being arguably more expressive&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-1&#34; href=&#34;#footnote-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;). I&amp;#39;ve enjoyed this
trajectory, because higher level languages let you implement so much, so
quickly.&lt;/p&gt;
&lt;p&gt;
My feelings on this are shifting, however. I wrote some code a decade
ago for &lt;a href=&#34;https://arxiv.org/abs/0810.4930&#34;&gt;a system&lt;/a&gt; that has been running constantly for a decade on
thousands of devices. My code is not particularly CPU efficient and,
therefore, not as energy-efficient as it could be. As the planet
warms, I think it&amp;#39;s important to try and find small efficiencies where
we can… not necessarily under the assumption that it will make a
massive difference, but because it&amp;#39;s just the right thing to do as
conscientious professionals. (The fact that the sins of my past are
executing on processors running on top of and within Antarctic ice
adds an extra bit of irony here).&lt;/p&gt;
&lt;p&gt;
Common Lisp is particularly interesting to me of late because, having
been designed largely for &lt;a href=&#34;https://en.wikipedia.org/wiki/Symbolic_artificial_intelligence&#34;&gt;Good Old-Fashioned AI&lt;/a&gt;, it allows you to work
at a very high level (you can, for example, add Prolog-like
functionality to a Lisp in a few hundred lines of code &lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-2&#34; href=&#34;#footnote-2&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; – but, you can generate very fast (i.e.,
more energy efficient) code as well, as we shall see shortly.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-4&#34;&gt;
Improvements
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
The next thing I tried was to separate the event generation from the trigger calculation and to use a vector for the input times, instead of a list:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defun time-sequence-vec (n)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (make-array `(,n)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              :initial-contents
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              (loop repeat n
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                 for y = 0 then (+ y (random 1000))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                 collect y)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defparameter array-size (* 100 1000 1000))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defparameter *s* (time-sequence-vec array-size))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
I also make the test sample much larger to improve the run durations and statistics.&lt;/p&gt;
&lt;p&gt;
Both Graham&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-3&#34; href=&#34;#footnote-3&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; and Norvig&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-4&#34; href=&#34;#footnote-4&#34;&gt;4&lt;/a&gt;&lt;/sup&gt; emphasize tuning your algorithm first before turning
to other optimizations. In our case the problem is O(&lt;em&gt;n&lt;/em&gt;), which is
the best time complexity we can hope for, but our use of function
composition, while elegant, could be turned into something more
efficient. To improve the algorithm proper, I perform the entire
computation in a single &lt;code class=&#34;verbatim&#34;&gt;loop&lt;/code&gt; statement. I also change the output
slightly to show the index for matching 8-fold events, start and end
time, and event duration:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defun second-try ()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (loop for x below (- array-size 8)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     if (&amp;lt; (- (elt *s* (+ x 8))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              (elt *s* x))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           1000)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     collect `(index ,x
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                     startval ,(elt *s* x)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                     endval   ,(elt *s* (+ x 8))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                     diff     ,(- (elt *s* (+ x 8))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                  (elt *s* x)))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(take 4 (second-try))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;((INDEX 69087 STARTVAL 34504666 ENDVAL 34505615 DIFF 949)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (INDEX 153990 STARTVAL 76991815 ENDVAL 76992630 DIFF 815)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (INDEX 237070 STARTVAL 118617491 ENDVAL 118618358 DIFF 867)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (INDEX 294951 STARTVAL 147513479 ENDVAL 147514346 DIFF 867))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; Time it, a few times:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(timing (length (second-try)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(DURATION 2158 MSEC... RESULT 2427)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(DURATION 2167 MSEC... RESULT 2427)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(DURATION 2162 MSEC... RESULT 2427)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Note that the starting and ending time values increase monotonically,
and the reported time differences (&lt;code class=&#34;verbatim&#34;&gt;DIFF&lt;/code&gt;) are under 1000, as desired&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-5&#34; href=&#34;#footnote-5&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;
The new trigger function improves the processing rate to 46.2 MHz. At
this point I&amp;#39;m starting to wonder what the assembly language looks
like:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(disassemble &amp;#39;second-try)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; disassembly for SECOND-TRY
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; Size: 1061 bytes. Origin: #x228FE0B0                        ; SECOND-TRY
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 0B0:       498B7510         MOV RSI, [R13+16]               ; thread.binding-stack-pointer
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 0B4:       488975F8         MOV [RBP-8], RSI
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 0B8:       488B3591FFFFFF   MOV RSI, [RIP-111]              ; &amp;#39;ARRAY-SIZE
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 0BF:       8B56F5           MOV EDX, [RSI-11]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 0C2:       4A8B142A         MOV RDX, [RDX+R13]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 0C6:       83FA61           CMP EDX, 97
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 0C9:       480F4456F9       CMOVEQ RDX, [RSI-7]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 0CE:       83FA51           CMP EDX, 81
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 0D1:       0F84BF030000     JEQ L17
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 0D7:       BF10000000       MOV EDI, 16
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 0DC:       FF1425B000B021   CALL QWORD PTR [#x21B000B0]     ; GENERIC--
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; .................. many lines omitted ................
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 4B6: L24:  CC18             BREAK 24                        ; UNBOUND-SYMBOL-ERROR
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 4B8:       27               BYTE #X27                       ; &amp;#39;*S*
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 4B9: L25:  6880000000       PUSH 128
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 4BE:       FF14252800B021   CALL QWORD PTR [#x21B00028]     ; ALLOC-TRAMP-R11
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 4C5:       E9FFFEFFFF       JMP L12
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 4CA: L26:  6A10             PUSH 16
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 4CC:       FF14252800B021   CALL QWORD PTR [#x21B00028]     ; ALLOC-TRAMP-R11
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;; 4D3:       EB94             JMP L14&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
(258 lines in total.)&lt;/p&gt;
&lt;p&gt;
My assembler-fu is not strong, but I notice the &lt;code class=&#34;verbatim&#34;&gt;GENERIC--&lt;/code&gt; and we do
not need generic functions: there are many opportunities here to
introduce type declarations.&lt;/p&gt;
&lt;p&gt;
After declaring to the compiler we want more speed and less
type-checking (&lt;code class=&#34;verbatim&#34;&gt;(declaim (optimize (speed 3) (debug 0) (safety 0)))&lt;/code&gt;),
let&amp;#39;s declare our array to be type &lt;code class=&#34;verbatim&#34;&gt;fixnum&lt;/code&gt; (which on SBCL is an
integer from -4611686018427387904 to 4611686018427387903).&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defparameter *s* (make-array array-size
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                              :element-type &amp;#39;fixnum))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; Initialize array:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(loop
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   for y = 0 then (+ y (random 1000))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   for i below array-size
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   do (setf (elt *s* i) y))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(timing
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (length
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   (loop for x below (- array-size 8)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      if (&amp;lt; (- (elt *s* (+ x 8))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               (elt *s* x))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            1000)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      collect `(index ,x
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      startval ,(elt *s* x)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      endval   ,(elt *s* (+ x 8))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      diff     ,(- (elt *s* (+ x 8))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                   (elt *s* x))))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(DURATION 1964 MSEC... RESULT 2435)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(DURATION 1939 MSEC... RESULT 2435)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(DURATION 2010 MSEC... RESULT 2435)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
… maybe a slight improvement. Let&amp;#39;s now type-hint where we can throughout the tight loop:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(timing
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (length
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   (loop for x below (- array-size 8)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      if (&amp;lt; (- (the fixnum (elt *s* (the fixnum (+ x 8))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               (the fixnum (elt *s* (the fixnum x))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            1000)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      collect `(index ,x
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      startval ,(elt *s* x)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      endval   ,(elt *s* (+ x 8))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      diff     ,(- (elt *s* (+ x 8))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                   (elt *s* x))))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(DURATION 1740 MSEC... RESULT 2435)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(DURATION 1738 MSEC... RESULT 2435)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(DURATION 1753 MSEC... RESULT 2435)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
A 10% or so improvement… not too bad.&lt;/p&gt;
&lt;p&gt;
At this point I&amp;#39;m tempted to look at the macroexpansion of my &lt;code class=&#34;verbatim&#34;&gt;loop&lt;/code&gt;
expression and see what it&amp;#39;s doing. For simplicity, I &lt;code class=&#34;verbatim&#34;&gt;collect&lt;/code&gt; just
the starting time index for times satisfying the trigger:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(macroexpand-1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#39;(loop for x below (- array-size 8)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     if (&amp;lt; (- (the fixnum (elt *s* (the fixnum (+ x 8))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            (the fixnum (elt *s* (the fixnum x))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         1000)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     collect x))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(block nil
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let ((#:loop-limit-711 (- array-size 8)) (x 0))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (declare (type (and number real) x)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             (type (and number real) #:loop-limit-711))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (sb-loop::with-loop-list-collection-head (#:loop-list-head-712
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                              #:loop-list-tail-713)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (tagbody
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       sb-loop::next-loop
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (when (&amp;gt;= x #:loop-limit-711) (go sb-loop::end-loop))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (if (&amp;lt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              (- (the fixnum (elt *s* (the fixnum (+ x 8))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                 (the fixnum (elt *s* (the fixnum x))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              1000)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             (sb-loop::loop-collect-rplacd
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              (#:loop-list-head-712 #:loop-list-tail-713) (list x)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (sb-loop::loop-desetq x (1+ x))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (go sb-loop::next-loop)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       sb-loop::end-loop
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (return-from nil
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           (sb-loop::loop-collect-answer #:loop-list-head-712))))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
I notice that &lt;code class=&#34;verbatim&#34;&gt;x&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;:loop-limit-711&lt;/code&gt; have an overly-general type declaration. I&amp;#39;m not sure how to type-hint &lt;code class=&#34;verbatim&#34;&gt;x&lt;/code&gt;, but I can type-hint the upper bound:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(timing
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (length
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   (loop for x below (- (the fixnum array-size) 8)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      if (&amp;lt; (- (the fixnum (elt *s* (+ (the fixnum x) 8)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               (the fixnum (elt *s* (the fixnum x))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            1000)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      collect `(index ,x
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      startval ,(elt *s* x)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      endval   ,(elt *s* (+ x 8))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      diff     ,(- (elt *s* (+ x 8))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                   (elt *s* x))))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(DURATION 1460 MSEC... RESULT 2513)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(DURATION 1455 MSEC... RESULT 2513)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(DURATION 1486 MSEC... RESULT 2513)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Another modest but significant improvement.&lt;/p&gt;
&lt;p&gt;
At this point I reached for the SBCL profiler to see what I could
learn from it. Most of the processing time is spent in array
lookups, which I don&amp;#39;t think we can avoid.&lt;/p&gt;
&lt;p&gt;
Let&amp;#39;s look at the assembler again. Since our trigger matches are rare,
most of our time is going to be spent in finding the events, rather
than in collecting the detailed results for the matches. If we switch
back to using &lt;code class=&#34;verbatim&#34;&gt;collect x&lt;/code&gt; to avoid the extra assembly associated with
building &lt;code class=&#34;verbatim&#34;&gt;`(index ,x startval ...)&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defun trigger ()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(loop for x below (- (the fixnum array-size) 8)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     if (&amp;lt; (- (the fixnum (elt *s* (+ (the fixnum x) 8)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              (the fixnum (elt *s* (the fixnum x))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           1000)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     collect x))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(disassemble &amp;#39;trigger)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; disassembly for TRIGGER
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; Size: 448 bytes. Origin: #x22610EA0                         ; TRIGGER
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EA0:       498B4510         MOV RAX, [R13+16]              ; thread.binding-stack-pointer
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EA4:       488945F8         MOV [RBP-8], RAX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EA8:       488B05B1FFFFFF   MOV RAX, [RIP-79]              ; &amp;#39;ARRAY-SIZE
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EAF:       8B70F5           MOV ESI, [RAX-11]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EB2:       4A8B342E         MOV RSI, [RSI+R13]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EB6:       83FE61           CMP ESI, 97
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EB9:       480F4470F9       CMOVEQ RSI, [RAX-7]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EBE:       83FE51           CMP ESI, 81
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EC1:       0F8477010000     JEQ L11
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EC7:       40F6C601         TEST SIL, 1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0ECB:       0F8568010000     JNE L10
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0ED1:       48D1FE           SAR RSI, 1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0ED4:       4883EE08         SUB RSI, 8
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0ED8:       488975F0         MOV [RBP-16], RSI
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EDC:       31F6             XOR ESI, ESI
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EDE:       49896D28         MOV [R13+40], RBP              ; thread.pseudo-atomic-bits
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EE2:       4D8B5D68         MOV R11, [R13+104]             ; thread.alloc-region
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EE6:       498D4310         LEA RAX, [R11+16]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EEA:       493B4570         CMP RAX, [R13+112]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EEE:       0F874D010000     JNBE L12
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EF4:       49894568         MOV [R13+104], RAX             ; thread.alloc-region
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EF8: L0:   498D4307         LEA RAX, [R11+7]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0EFC:       49316D28         XOR [R13+40], RBP              ; thread.pseudo-atomic-bits
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F00:       7402             JEQ L1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F02:       CC09             BREAK 9                        ; pending interrupt trap
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F04: L1:   C740F917001020   MOV DWORD PTR [RAX-7], #x20100017  ; NIL
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F0B:       C7400117001020   MOV DWORD PTR [RAX+1], #x20100017  ; NIL
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F12:       488945E8         MOV [RBP-24], RAX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F16:       488945E0         MOV [RBP-32], RAX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F1A:       E9BB000000       JMP L4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F1F:       90               NOP
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F20: L2:   8B142524144A20   MOV EDX, [#x204A1424]          ; tls_index: *S*
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F27:       4A8B142A         MOV RDX, [RDX+R13]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F2B:       83FA61           CMP EDX, 97
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F2E:       480F44142528144A20 CMOVEQ RDX, [#x204A1428]     ; *S*
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F37:       83FA51           CMP EDX, 81
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F3A:       0F840F010000     JEQ L13
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F40:       488D7E10         LEA RDI, [RSI+16]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F44:       4883EC10         SUB RSP, 16
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F48:       488975D8         MOV [RBP-40], RSI
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F4C:       B904000000       MOV ECX, 4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F51:       48892C24         MOV [RSP], RBP
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F55:       488BEC           MOV RBP, RSP
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F58:       B862934F22       MOV EAX, #x224F9362            ; #&amp;lt;FDEFN ELT&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F5D:       FFD0             CALL RAX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F5F:       488B75D8         MOV RSI, [RBP-40]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F63:       F6C201           TEST DL, 1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F66:       0F85CA000000     JNE L9
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F6C:       4C8BC2           MOV R8, RDX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F6F:       49D1F8           SAR R8, 1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F72:       4C8945D0         MOV [RBP-48], R8
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F76:       8B142524144A20   MOV EDX, [#x204A1424]          ; tls_index: *S*
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F7D:       4A8B142A         MOV RDX, [RDX+R13]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F81:       83FA61           CMP EDX, 97
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F84:       480F44142528144A20 CMOVEQ RDX, [#x204A1428]     ; *S*
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F8D:       83FA51           CMP EDX, 81
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F90:       0F84BC000000     JEQ L14
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F96:       488BFE           MOV RDI, RSI
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F99:       4883EC10         SUB RSP, 16
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0F9D:       488975D8         MOV [RBP-40], RSI
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FA1:       B904000000       MOV ECX, 4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FA6:       48892C24         MOV [RSP], RBP
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FAA:       488BEC           MOV RBP, RSP
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FAD:       B862934F22       MOV EAX, #x224F9362            ; #&amp;lt;FDEFN ELT&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FB2:       FFD0             CALL RAX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FB4:       4C8B45D0         MOV R8, [RBP-48]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FB8:       488B75D8         MOV RSI, [RBP-40]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FBC:       F6C201           TEST DL, 1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FBF:       7572             JNE L8
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FC1:       488BC2           MOV RAX, RDX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FC4:       48D1F8           SAR RAX, 1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FC7:       498BD0           MOV RDX, R8
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FCA:       4829C2           SUB RDX, RAX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FCD:       4881FAE8030000   CMP RDX, 1000
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FD4:       7C22             JL L5
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FD6: L3:   4883C602         ADD RSI, 2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FDA: L4:   488BC6           MOV RAX, RSI
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FDD:       48D1F8           SAR RAX, 1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FE0:       483B45F0         CMP RAX, [RBP-16]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FE4:       0F8C36FFFFFF     JL L2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FEA:       488B45E8         MOV RAX, [RBP-24]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FEE:       488B5001         MOV RDX, [RAX+1]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FF2:       488BE5           MOV RSP, RBP
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FF5:       F8               CLC
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FF6:       5D               POP RBP
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FF7:       C3               RET
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FF8: L5:   4C8B45E0         MOV R8, [RBP-32]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 0FFC:       49896D28         MOV [R13+40], RBP              ; thread.pseudo-atomic-bits
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1000:       4D8B5D68         MOV R11, [R13+104]             ; thread.alloc-region
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1004:       498D4310         LEA RAX, [R11+16]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1008:       493B4570         CMP RAX, [R13+112]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 100C:       7747             JNBE L15
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 100E:       49894568         MOV [R13+104], RAX             ; thread.alloc-region
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1012: L6:   498D4307         LEA RAX, [R11+7]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1016:       49316D28         XOR [R13+40], RBP              ; thread.pseudo-atomic-bits
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 101A:       7402             JEQ L7
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 101C:       CC09             BREAK 9                        ; pending interrupt trap
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 101E: L7:   488970F9         MOV [RAX-7], RSI
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1022:       C7400117001020   MOV DWORD PTR [RAX+1], #x20100017  ; NIL
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1029:       488945E0         MOV [RBP-32], RAX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 102D:       49894001         MOV [R8+1], RAX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1031:       EBA3             JMP L3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1033: L8:   CC48             BREAK 72                       ; OBJECT-NOT-FIXNUM-ERROR
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1035:       08               BYTE #X08                      ; RDX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1036: L9:   CC48             BREAK 72                       ; OBJECT-NOT-FIXNUM-ERROR
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1038:       08               BYTE #X08                      ; RDX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1039: L10:  CC48             BREAK 72                       ; OBJECT-NOT-FIXNUM-ERROR
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 103B:       18               BYTE #X18                      ; RSI
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 103C:       CC10             BREAK 16                       ; Invalid argument count trap
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 103E: L11:  CC18             BREAK 24                       ; UNBOUND-SYMBOL-ERROR
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1040:       00               BYTE #X00                      ; RAX
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1041: L12:  6A10             PUSH 16
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1043:       FF14252800B021   CALL QWORD PTR [#x21B00028]    ; ALLOC-TRAMP-R11
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 104A:       E9A9FEFFFF       JMP L0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 104F: L13:  CC18             BREAK 24                       ; UNBOUND-SYMBOL-ERROR
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1051:       27               BYTE #X27                      ; &amp;#39;*S*
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1052: L14:  CC18             BREAK 24                       ; UNBOUND-SYMBOL-ERROR
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1054:       27               BYTE #X27                      ; &amp;#39;*S*
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1055: L15:  6A10             PUSH 16
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 1057:       FF14252800B021   CALL QWORD PTR [#x21B00028]    ; ALLOC-TRAMP-R11
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; 105E:       EBB2             JMP L6&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
… this is almost a manageable amount of assembler, though I don&amp;#39;t
claim to understand all of it. If I needed more speed, though, I could
dig into the assembler as a way to try and ferret out even more
efficiency.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-5&#34;&gt;
Summary
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
We went from our initial POC in very functional-looking Clojure,
running at 250 kHz, to optimized Common Lisp running at 100,000,000 /
1467 msec = 68.2 MHz, which is nearly 300x faster.&lt;/p&gt;
&lt;p&gt;
Checking our intuition about how fast this really is: my processor is
2.7 GHz, and our processing rate is 68.2 MHz, meaning we&amp;#39;re spending
about 40 clock ticks per event, which doesn&amp;#39;t strike me as too bad.&lt;/p&gt;
&lt;p&gt;
In the end, we made the following changes to our initial attempt:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Separated out the initial event time-sequence generation as a
separate step;&lt;/li&gt;
&lt;li&gt;Rewrote the algorithm as a single loop;&lt;/li&gt;
&lt;li&gt;&lt;code class=&#34;verbatim&#34;&gt;declaim&lt;/code&gt;&amp;#39;ed optimizations to the compiler;&lt;/li&gt;
&lt;li&gt;Type-hinted the input array, the variables used in the time
difference calculation, and the loop upper bound.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We also touched on profiling (which didn&amp;#39;t provide much benefit this
time, but can be very useful generally), and showed how to inspect the
generated assembler code.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-6&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-6&#34;&gt;
Conclusion
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-6&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Common Lisp can be made pretty fast!  I should write a C-language
version of this toy problem to compare.  The final code is not nearly
as beautiful as the original, but without too much effort we got much
faster code.  I&amp;#39;ll conclude with this line from ANSI Common Lisp:
&amp;#34;Lisp is really two languages: a language for writing fast programs
and a language for writing programs fast.&amp;#34; It seems quite powerful to
me to have both of these on hand.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr class=&#34;footnotes-separatator&#34;&gt;
&lt;div class=&#34;footnote-definitions&#34;&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-1&#34;&gt;&lt;a href=&#34;#footnote-reference-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;Reasonable people can disagree on the relative expressiveness of languages; for me, Lisps win on expressiveness because I can bend the language to my will using macros in a way that I cannot with non-Lisps.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-2&#34;&gt;&lt;a href=&#34;#footnote-reference-2&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;See Paul Graham, &lt;em&gt;On Lisp&lt;/em&gt; p. vii&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-3&#34;&gt;&lt;a href=&#34;#footnote-reference-3&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;Paul Graham, ANSI Common Lisp&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-4&#34;&gt;&lt;a href=&#34;#footnote-reference-4&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;Peter Norvig, Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-5&#34;&gt;&lt;a href=&#34;#footnote-reference-5&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;The original Clojure code reported the entire sequence of eight times for each triggered event, but we omit that level of detail for clarity. Since the triggered clusters are rare, this doesn&amp;#39;t significantly impact the timing measurements.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Common Lisp How-Tos</title>
      <link>http://johnj.com/posts/lisp-projects/</link>
      <pubDate>Sun, 15 Sep 2019 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/lisp-projects/</guid>
      <description>
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Intro
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/lisp-sticks.jpeg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/lisp-sticks_hu_118f89e1fb0202d5.jpeg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;I&amp;#39;ve been writing this post as I go, and you may still see changes if you check back from time to time.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
This post is for writing about things I&amp;#39;m figuring out, and for
keeping notes on what I want to figure out next, as I get ramped up on
Common Lisp. When I&amp;#39;m done there will hopefully be stuff here other
people can use.&lt;/p&gt;
&lt;p&gt;
There&amp;#39;s a lot to love and admire about Common Lisp, but the language
has some pointy bits that can at times make Clojure look friendly.
With so many things to sort out I&amp;#39;m going to try to keep a few notes
going forward just to keep it all organized.  Caveat emptor, YMMV, USE
AT YOUR OWN RISK, etc., etc.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
Lessons Learned So Far
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-3&#34;&gt;
How Do I Set Up Common Lisp on a Mac?
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/eigenhombre/mac-sbcl-quicklisp-install&#34;&gt;I made a repo&lt;/a&gt; to automate how I set up a fresh SBCL install on a Mac,
including Quicklisp. This gets me from zero to a working Emacs REPL
system fairly quickly.&lt;/p&gt;
&lt;p&gt;
Note that I also set a &lt;code class=&#34;verbatim&#34;&gt;LISP_HOME&lt;/code&gt; environment variable in my
&lt;code class=&#34;verbatim&#34;&gt;.bash_profile&lt;/code&gt; which I use in the examples which follow.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-4&#34;&gt;
How Do I Get Environment Variables from Lisp?
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
From the &lt;a href=&#34;https://lispcookbook.github.io/cl-cookbook/os.html&#34;&gt;Common Lisp Cookbook&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(uiop:getenv &amp;#34;HOME&amp;#34;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-5&#34;&gt;
How Do I Quickly Create a New Project?
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
(There is &lt;a href=&#34;https://lispmethods.com/libraries.html&#34;&gt;a nice writeup&lt;/a&gt; on how Lisp projects are organized.)&lt;/p&gt;
&lt;p&gt;
First, it seems it&amp;#39;s best to pick a standard place to put your Lisp
projects. I have a deep directory tree on my filesystem so would
prefer to set that path as an environment variable; this makes the
setup easy to port to another computer.&lt;/p&gt;
&lt;p&gt;
I made this &lt;code class=&#34;verbatim&#34;&gt;bash&lt;/code&gt; script, &lt;code class=&#34;verbatim&#34;&gt;lisplib&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;projname=${1?}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sbcl --non-interactive  \
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     --disable-debugger \
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     --eval &amp;#39;(ql:quickload &amp;#34;cl-project&amp;#34;)&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     --eval &amp;#39;(ql:quickload &amp;#34;cl-utilities&amp;#34;)&amp;#39; \
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     --eval &amp;#39;(let* ((projname &amp;#34;&amp;#39;$projname&amp;#39;&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    (home (sb-unix::posix-getenv &amp;#34;LISP_HOME&amp;#34;))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    (projpath (concatenate &amp;#39;&amp;#34;&amp;#39;&amp;#34;&amp;#39;string home &amp;#34;/&amp;#34; projname)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               (cl-project:make-project (pathname projpath)))&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;open -a /Applications/Emacs.app $LISP_HOME/$projname/src/main.lisp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;(Omit the newlines inside the last single-quoted expression.)&lt;/p&gt;
&lt;p&gt;
When I, say, &lt;code class=&#34;verbatim&#34;&gt;lisplib foo&lt;/code&gt;, it creates the project using &lt;code class=&#34;verbatim&#34;&gt;make-project&lt;/code&gt;
and opens the editor on the main source file.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-6&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-6&#34;&gt;
How Do I Add Dependencies to One Of My Projects?
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-6&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;Add it to the &lt;code class=&#34;verbatim&#34;&gt;.asd&lt;/code&gt; file in the &lt;code class=&#34;verbatim&#34;&gt;:depends-on&lt;/code&gt; list.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-7&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-7&#34;&gt;
How Do I Get My Local Projects Loadable By Other Projects?
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-7&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;I did this once:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ cd ~/quicklisp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ mv local-projects /tmp  # Mine was basically empty...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ln -s $LISP_HOME local-projects&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-8&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-8&#34;&gt;
How Do I Get Dependencies Loaded
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-8&#34; class=&#34;outline-text-3&#34;&gt;
&lt;ol&gt;
&lt;li&gt;put your project in the directory symlinked above;&lt;/li&gt;
&lt;li&gt;jack into your REPL;&lt;/li&gt;
&lt;li&gt;update &lt;code class=&#34;verbatim&#34;&gt;depends-on&lt;/code&gt; in the project&amp;#39;s &lt;code class=&#34;verbatim&#34;&gt;.asd&lt;/code&gt; file as you add dependencies;&lt;/li&gt;
&lt;li&gt;&lt;code class=&#34;verbatim&#34;&gt;(ql:quickload &amp;lt;current-package&amp;gt;)&lt;/code&gt; to pick up its dependencies.&lt;/li&gt;
&lt;li&gt;Optionally, to get the correct namespacing for the package you&amp;#39;re
working on, use &lt;code class=&#34;verbatim&#34;&gt;slime-repl-set-package&lt;/code&gt; (&lt;code class=&#34;verbatim&#34;&gt;C-c M-p&lt;/code&gt;) to set the
default package to the one you&amp;#39;re working on (not 100% sure what
effect this has yet)&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-9&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-9&#34;&gt;
How Do I Build Binaries?
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-9&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;I use to Xach Beane&amp;#39;s &lt;a href=&#34;https://www.xach.com/lisp/buildapp/&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;buildapp&lt;/code&gt;&lt;/a&gt;, built like so:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone git@github.com:xach/buildapp.git
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cd buildapp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;make install&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;A small working build script using &lt;code class=&#34;verbatim&#34;&gt;buildapp&lt;/code&gt; can be found &lt;a href=&#34;https://github.com/eigenhombre/loam/blob/master/build.sh&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-10&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-10&#34;&gt;
How Do I Get My Project Into &lt;a href=&#34;https://www.quicklisp.org/beta/&#34;&gt;Quicklisp&lt;/a&gt;?
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-10&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;Make a pull request with Xach Beane &lt;a href=&#34;https://github.com/quicklisp/quicklisp-projects/issues&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-11&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-11&#34;&gt;
How Do I Use &lt;code class=&#34;verbatim&#34;&gt;Curses&lt;/code&gt; (or equivalent)?
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-11&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;After some research I decided to follow in &lt;a href=&#34;http://stevelosh.com/blog/2016/08/lisp-jam-postmortem/&#34;&gt;Steve Losh&amp;#39;s footsteps&lt;/a&gt; and
use &lt;code class=&#34;verbatim&#34;&gt;cl-charms&lt;/code&gt; (tutorial &lt;a href=&#34;http://turtleware.eu/posts/cl-charms-crash-course.html&#34;&gt;here&lt;/a&gt;). This &lt;a href=&#34;https://stackoverflow.com/questions/57906498/package-lock-error-while-installing-sbcl-cffi-package-on-mac-via-quicklisp&#34;&gt;cost me multiple days&lt;/a&gt; due to some outdated
Homebrew packages, but worked out in the end after updating those and
reinstalling my Lisp setup.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-12&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-12&#34;&gt;
How Do I Get Help?
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-12&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;Aside from Stack Overflow, &lt;a href=&#34;https://www.irccloud.com/irc/freenode/channel/lisp&#34;&gt;the &lt;code class=&#34;verbatim&#34;&gt;#lisp&lt;/code&gt; channel on IRC&lt;/a&gt; was helpful to
me for the above issue.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-13&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-13&#34;&gt;
Future Projects
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-13&#34; class=&#34;outline-text-2&#34;&gt;
&lt;ul&gt;
&lt;li&gt;Finish &lt;a href=&#34;https://github.com/eigenhombre/weeds&#34;&gt;Weeds&lt;/a&gt; (redo of my blog software in CL)&lt;/li&gt;
&lt;li&gt;Port &lt;a href=&#34;https://github.com/eigenhombre/namejen&#34;&gt;namejen&lt;/a&gt; to CL&lt;/li&gt;
&lt;li&gt;Write a Roguelike&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>A Daily Journal in Org Mode</title>
      <link>http://johnj.com/posts/journaling-procedure/</link>
      <pubDate>Mon, 02 Sep 2019 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/journaling-procedure/</guid>
      <description>
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/jackson-park-road.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/jackson-park-road_hu_60311bd308cac8c2.jpg&#34; style=&#34;width:300px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
In &lt;a href=&#34;https://news.ycombinator.com/item?id=20856236&#34;&gt;a comment&lt;/a&gt; on yesterday&amp;#39;s &lt;a href=&#34;https://news.ycombinator.com/item?id=20849148&#34;&gt;Hacker News thread&lt;/a&gt; about journaling, I
sketched out my daily journaling practice of late. This post contains
the full details on this procedure for those who are interested in
using Org Mode for daily journaling.&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
The Basics
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Every day gets its own &lt;a href=&#34;https://orgmode.org&#34;&gt;Org Mode&lt;/a&gt; file. What goes in is not specified, but things I&amp;#39;ve included so far include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;To do lists&lt;/li&gt;
&lt;li&gt;Things I probably won&amp;#39;t do but would like to&lt;/li&gt;
&lt;li&gt;Previous night&amp;#39;s dreams&lt;/li&gt;
&lt;li&gt;Free-form journaling&lt;/li&gt;
&lt;li&gt;Notes on projects in progress&lt;/li&gt;
&lt;li&gt;Small snippets of beautiful code I&amp;#39;ve written or seen that day&lt;/li&gt;
&lt;li&gt;Summary of the day&amp;#39;s events&lt;/li&gt;
&lt;li&gt;Quotes or poems&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main thing is to write something every day and keep some kind of
record about what&amp;#39;s happening in my life.&lt;/p&gt;
&lt;p&gt;
So far I&amp;#39;ve kept each day to a single page. At the end of the day,
this page gets exported as a two-column PDF (via Org&amp;#39;s LaTeX export),
printed out and kept in a binder on my desk. I review the binder
occasionally to get a feel for how the days have been going.&lt;/p&gt;
&lt;p&gt;
If I continue on this path for a few more months, I&amp;#39;ll have a hundred
or so entries; after a year, of course, hundreds.  At that point I&amp;#39;ll
probably concatentate the PDFs into a single PDF and turn it into a
bound book, perhaps via &lt;a href=&#34;http://lulu.com/&#34;&gt;Lulu&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
Explanation
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-3&#34;&gt;
Org Mode
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;For programming and writing, I use a 40+ year old text editor called
Emacs, which is matchless in its programmability. If you&amp;#39;re a
programmer (or want to be one) and you want complete control over your
editing experience, Emacs might be for you. Org Mode is a set of
functionality that has been added to Emacs which allows for easy
outlining, table creation and editing, export into a variety of
formats (e.g. HTML and PDF), and a variety of other features for
making pretty documents that are also readable as plain text. If
you&amp;#39;re familiar with the Markdown text format, Org Mode is like
Markdown, but on steroids. (Every post on this site is generated from
an Org Mode file.)&lt;/p&gt;
&lt;p&gt;
Org Mode files can have header information at the top of the file to
define how the file looks when it&amp;#39;s exported. Since I&amp;#39;m picky about
how the printout looks, I&amp;#39;ve tweaked this to my liking as follows:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#+TITLE: [...today&amp;#39;s date...]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#+OPTIONS: toc:nil num:nil author:nil date:nil
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#+STARTUP: align
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#+HTML_HEAD: &amp;lt;link rel=&amp;#34;stylesheet&amp;#34; type=&amp;#34;text/css href=&amp;#34;styles.css&amp;#34; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#+LaTeX_CLASS: article
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#+LaTeX_CLASS_OPTIONS: [9pt,twocolumn,portrait]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#+LATEX_HEADER: \usepackage[margin=0.5in]{geometry}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#+LATEX_HEADER: \usepackage{enumitem}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;code class=&#34;verbatim&#34;&gt;styles.css&lt;/code&gt; is a style sheet I have which overrides the default
styles for Org Mode-generated HTML, in case I want to view the file in
a Web browser, which runs faster than the LaTeX/PDF export. The
LaTeX-related items specify the multi-column layout, along with
smaller text and narrower margins than the default.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-4&#34;&gt;
Automating It
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;At first, I created and edited the files manually, copying and pasting
the above snippet into a new file each morning, and setting the title
in the header using &lt;code class=&#34;verbatim&#34;&gt;org-time-stamp-inactive&lt;/code&gt; (&lt;code class=&#34;verbatim&#34;&gt;C-c !&lt;/code&gt;).  Eventually I
automated all that using the following Emacs Lisp (added to
&lt;code class=&#34;verbatim&#34;&gt;$HOME/.emacs.d/init.el&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defun open-journal-file ()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let* ((today (format-time-string &amp;#34;%Y-%m-%d&amp;#34;))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (path (concat (getenv &amp;#34;HOME&amp;#34;) &amp;#34;/path/to/my/journal/&amp;#34; today &amp;#34;.org&amp;#34;))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (hdr-list (list (concat &amp;#34;#+TITLE: [&amp;#34; today &amp;#34;]&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                         &amp;#34;#+OPTIONS: toc:nil num:nil author:nil date:nil&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                         &amp;#34;#+STARTUP: align&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                         &amp;#34;#+HTML_HEAD: &amp;lt;link rel=\&amp;#34;stylesheet\&amp;#34; type=\&amp;#34;text/css\&amp;#34; href=\&amp;#34;styles.css\&amp;#34; /&amp;gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                         &amp;#34;#+LaTeX_CLASS: article&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                         &amp;#34;#+LaTeX_CLASS_OPTIONS: [9pt,twocolumn,portrait]&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                         &amp;#34;#+LATEX_HEADER: \\usepackage[margin=0.5in]{geometry}&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                         &amp;#34;#+LATEX_HEADER: \\usepackage{enumitem}&amp;#34;))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (hdr (apply &amp;#39;concat
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                     (mapcar (lambda (s) (concat s &amp;#34;\n&amp;#34;))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                             hdr-list)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (has-hdr (lambda ()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    (save-excursion
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      (goto-char (point-min))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      (search-forward &amp;#34;#+TITLE&amp;#34; nil t)))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (message (concat &amp;#34;opening &amp;#34; path &amp;#34; ...&amp;#34;))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (find-file path)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (unless (funcall has-hdr)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (save-excursion
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        (goto-char (point-min))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        (insert hdr)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (message &amp;#34;Enjoy your journaling!&amp;#34;)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Then, to bind it to the key combination &lt;code class=&#34;verbatim&#34;&gt;Control-o 1&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(global-set-key &amp;#34;\C-o1&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                (lambda ()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                  (interactive)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                  (open-journal-file)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Now that this is set up, with just a keystroke or two I have the day&amp;#39;s
journal entry formatted exactly the way I want (because of the
&lt;code class=&#34;verbatim&#34;&gt;HTML_HEAD&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;LATEX_*&lt;/code&gt; options). If the file was already created,
the shortcut puts me back in the file to make updates.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-5&#34;&gt;
To Do Lists
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;The way I organize my tasks for the day (&amp;#34;organize&amp;#34; is too heavyweight
a word - it&amp;#39;s a very light touch) goes something like this:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| pt exercises          |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| coffee                |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| work on =smallscheme= |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| breakfast             | &amp;lt;-- stuff I did
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;|                       |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| train to work         | &amp;lt;-- stuff I&amp;#39;m doing now
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| work on blog post     |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;|                       |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| demo prep             | &amp;lt;-- stuff I think I&amp;#39;ll do
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| pairing               |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| meeting about xyz     |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| demo/standup/retro    |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| bike home             |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| dinner                |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| dishes                |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| meditate              |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| bed                   |&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The Org Mode table editing shortcuts let me reorder, add or eliminate
items quickly. Anything I don&amp;#39;t get to by the end of the day either
gets a &lt;del&gt;strikethrough&lt;/del&gt; so I can remember that I didn&amp;#39;t get to it, or
just removed. The point of the todo table is not simply to make sure I
do certain things, but to record the trajectory of the day.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-6&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-6&#34;&gt;
Why This Approach?
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-6&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;For many years I&amp;#39;ve been keeping to-do lists and writing journals
using various strategies, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the Things app on laptop and phone;&lt;/li&gt;
&lt;li&gt;a single, massive Org Mode file; and&lt;/li&gt;
&lt;li&gt;a pen and a bound paper journal.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I love the physicality of a paper journal, but I find handwritten
journals harder to read than a typed manuscript. (The handwritten
journals also have a way of &lt;a href=&#34;https://github.com/eigenhombre/sborg&#34;&gt;turning into sketchbooks&lt;/a&gt;.)  The printed
journal gives me a bit more physicality and much better readability.&lt;/p&gt;
&lt;p&gt;
I like many things about Org Mode, but find the &lt;a href=&#34;https://orgmode.org/manual/Tracking-TODO-state-changes.html&#34;&gt;TODO states&lt;/a&gt; too ugly
and heavyweight for a day&amp;#39;s tasks. Generally, if I can&amp;#39;t finish
something in a single day, I don&amp;#39;t want to be pestered about it (and I
know what I care about longer-term). I really do need to be reminded
of it I&amp;#39;ll set a reminder in my calendar or my phone. (Most of the
things I have to worry about at my day job are in our JIRA ticketing
system or explicitly on my calendar.)  Finally, something about the
single, massive Org file gets to be a little oppressive. A separate
file for every day has a certain cleanness to it.&lt;/p&gt;
&lt;p&gt;
I&amp;#39;ve enjoyed going back and rereading the entries. Whereas meditation
builds awareness of the present moment, journaling and reading the
journals gives a sense of the wider arc of time, inviting
contemplation about how I&amp;#39;m spending my days, and shedding light on
themes and feelings that persist over time.&lt;/p&gt;
&lt;p&gt;
The other comments in the &lt;a href=&#34;https://news.ycombinator.com/item?id=20849148&#34;&gt;Hacker News thread&lt;/a&gt; are worth a read if
you&amp;#39;re into this sort of thing.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Implementing Scheme in Python</title>
      <link>http://johnj.com/posts/scheme-in-python/</link>
      <pubDate>Wed, 28 Aug 2019 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/scheme-in-python/</guid>
      <description>
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/oewy.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/oewy_hu_ab424748ab8b3940.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Background
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Lately I&amp;#39;ve been a bit of a Lisp kick again, reading &lt;em&gt;&lt;a href=&#34;http://www.paulgraham.com/onlisp.html&#34;&gt;On Lisp&lt;/a&gt;&lt;/em&gt; and
&lt;em&gt;&lt;a href=&#34;http://www.gigamonkeys.com/book/&#34;&gt;Practical Common Lisp&lt;/a&gt;&lt;/em&gt;, working &lt;a href=&#34;https://github.com/eigenhombre/99lisp/&#34;&gt;problems&lt;/a&gt; and &lt;a href=&#34;https://github.com/eigenhombre/weeds&#34;&gt;re-casting&lt;/a&gt; my
&lt;a href=&#34;https://github.com/eigenhombre/organa&#34;&gt;Clojure-based blog software&lt;/a&gt; into Common Lisp to see how that goes. The
urge to do these things caught me somewhat by surprise: in the past
few years I haven&amp;#39;t done much programming outside of my day job
because I&amp;#39;ve been focused more on painting and drawing. It seems,
though, that these things are cyclical and right now I&amp;#39;m in the grips
of Lisp mania again.&lt;/p&gt;
&lt;p&gt;
This cycle goes back to the mid-1980s when I was a college student
studying physics and learning how to program. It&amp;#39;s hard to say how I
got the Lisp bug initially. I remember reading &lt;a href=&#34;https://en.wikipedia.org/wiki/Metamagical_Themas&#34;&gt;Douglas Hofstadter&lt;/a&gt;&amp;#39;s
explanation of recursive Lisp functions; hanging out near the AI
workstations in the basement of the Madison Academic Computing Center
where I worked (the sans-serif Lisp program printouts looked way
better than anybody else&amp;#39;s output); and reading about AI and Lisp on
Usenet.  At any rate, I managed to pick up a copy of PC-Lisp, a port
of &lt;a href=&#34;https://en.wikipedia.org/wiki/Franz_Lisp&#34;&gt;Franz Lisp&lt;/a&gt; to IBM PCs which apparently &lt;a href=&#34;https://github.com/blakemcbride/PC-LISP&#34;&gt;is still a thing&lt;/a&gt; after all
these years. Somewhat astonishingly, the interpreter ran on my
underpowered &lt;a href=&#34;https://en.wikipedia.org/wiki/IBM_PCjr&#34;&gt;IBM PCjr&lt;/a&gt;, loading from floppy disk in half a minute or
so. I remember how even fairly small programs would pause for several
seconds while the garbage collector did its thing. This interpreter,
along with a Lisp textbook I picked up somewhere, was enough to get me
started learning about atoms, lists, &lt;code class=&#34;verbatim&#34;&gt;quote&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;car&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;cdr&lt;/code&gt;,
symbolic computing, and simple recursive algorithms.&lt;/p&gt;
&lt;p&gt;
I also wrote a small s-expression parser in &lt;a href=&#34;https://en.wikipedia.org/wiki/Turbo_Pascal&#34;&gt;Turbo Pascal&lt;/a&gt; on the same
PCjr as a way of graphing arbitrary math functions of two variables. I
had no compiler class but my roommate taught me enough about finite
state machines, lexers, parsers, etc. to be dangerous… enough
knowledge to get my grapher up and running. (I wish I still had some
of these old programs, but they vanished when I &amp;#34;lent&amp;#34; the computer
and all my diskettes to a friend; they are probably landfill
somewhere.)&lt;/p&gt;
&lt;p&gt;
This all subsided for several years while I got sucked into physics,
then painting, then capoeira, then physics, then painting, then
software engineering in C, Perl, and Python. In the early aughts I got
interested in Paul Graham&amp;#39;s &lt;a href=&#34;http://www.paulgraham.com/articles.html&#34;&gt;writing&lt;/a&gt;, which led to a few skirmishes
with Common Lisp every couple of years, and ultimately to me getting
totally hooked on Clojure starting in 2011.&lt;/p&gt;
&lt;p&gt;
I intend to write more about what makes Lisps in general compelling
for me&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-1&#34; href=&#34;#footnote-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; and why I&amp;#39;ve returned to it over and over throughout my
career. In the mean time….&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
Scheming in Python
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Happily, my Lisp mania has crested coincidentally with Chicago Python
teacher David Beazley announcing another &lt;a href=&#34;https://www.dabeaz.com/sicp.html&#34;&gt;class&lt;/a&gt; on &lt;a href=&#34;https://en.wikipedia.org/wiki/Structure_and_Interpretation_of_Computer_Programs&#34;&gt;The Structure and
Interpretation of Computer Programs&lt;/a&gt;, a classic MIT computing text
based on a dialect of Lisp called Scheme, and I managed to get on the
list before it filled up. Since it&amp;#39;s been awhile since I&amp;#39;ve written
much Python, I thought I&amp;#39;d warm up for the class by trying to write &lt;a href=&#34;https://github.com/eigenhombre/smallscheme&#34;&gt;a
small Scheme implementation&lt;/a&gt; in Python. My hope was to refresh my
memory of the basics of Scheme, improve my slightly-dusty Python, and
have fun.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-3&#34;&gt;
Prior Art
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Researching this post (after most of the code was done), I noticed
that there are a &lt;a href=&#34;https://www.biostat.wisc.edu/~annis/creations/PyLisp/&#34;&gt;ton&lt;/a&gt; &lt;a href=&#34;https://github.com/fogus/lithp&#34;&gt;of&lt;/a&gt; &lt;a href=&#34;http://petraszd-smallscheme.appspot.com/&#34;&gt;small&lt;/a&gt; &lt;a href=&#34;https://github.com/juliusf/schemePy&#34;&gt;Lisps&lt;/a&gt; &lt;a href=&#34;https://github.com/xielingwang/pyScheme&#34;&gt;written&lt;/a&gt; in Python (&lt;a href=&#34;https://github.com/eigenhombre/PyClojure&#34;&gt;including&lt;/a&gt; &lt;a href=&#34;https://github.com/drewr/clojure-py&#34;&gt;two&lt;/a&gt; I
worked on the better part of a decade ago). One that stuck out in my
memory was Peter Norvig&amp;#39;s hundred-odd-line &lt;a href=&#34;https://norvig.com/lispy.html&#34;&gt;Lispy&lt;/a&gt;, which is
particularly striking in its elegance (in style, it reminds me of the
Lisp programs in &lt;a href=&#34;https://github.com/norvig/paip-lisp&#34;&gt;PAIP&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-4&#34;&gt;
The Stages
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;My plan for writing the interpreter was to follow the actual REPL
stages: Read, Eval, and Print. &lt;em&gt;Read&lt;/em&gt; would involve parsing input
expressions and turning them into data structures to be evaluated;
&lt;em&gt;Eval&lt;/em&gt; would be a (presumably recursive) step whereby, for function
calls, arguments would be &lt;em&gt;Eval&lt;/em&gt;&amp;#39;ed first, with the results handed to
the appropriate code implementing the actual function, implemented
either in Python (for a few primitive functions) or, eventually,
through user-defined functions. An exception to the argument
evaluation rule would have to be made for a few &lt;em&gt;special forms&lt;/em&gt;, which
would have to be handled on a case-by-case basis.&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-5&#34;&gt;
Parsing
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;My first approach for the parser was to use &lt;a href=&#34;https://www.dabeaz.com/ply/&#34;&gt;PLY&lt;/a&gt;, which I&amp;#39;ve used
before. Having been spoiled by the excellent &lt;a href=&#34;https://github.com/Engelberg/instaparse&#34;&gt;Instaparse&lt;/a&gt; library for
Clojure, upon returning to PLY I found the library&amp;#39;s interface
relatively clumsy and abstruse.&lt;/p&gt;
&lt;p&gt;
Then I thought I&amp;#39;d try a regex to parse everything, since Scheme&amp;#39;s
base syntax and grammar are so simple. The following regex actually
worked well for awhile:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pat = &amp;#34;&amp;#34;&amp;#34;^\s*\((?P&amp;lt;list&amp;gt;.*)\)$   # Something beginning/ending with parens, or
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (?P&amp;lt;bool&amp;gt;(\#t|\#f))\s*  # A boolean true/false value, or
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         |                       # An atom starting w/ a letter or arithmetic op:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (?P&amp;lt;atom&amp;gt;[a-zA-Z\+\-\*\/]+[a-zA-Z0-9\+\-\*\/]*)\s*
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (?P&amp;lt;num&amp;gt;[0-9]+)\s*&amp;#34;&amp;#34;&amp;#34;   # Or, a positive natural number.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
(I had not gotten to negative or floating point numbers at this stage
of the project.)&lt;/p&gt;
&lt;p&gt;
Expressions of the form &lt;code class=&#34;verbatim&#34;&gt;(+ 1 2 (+ 1 1 1))&lt;/code&gt;, for example, parsed
correctly.  However, the regex didn&amp;#39;t handle lists that nested in
other than the last position, for example, &lt;code class=&#34;verbatim&#34;&gt;(+ (* 2 3) 4)&lt;/code&gt;. It might
be possible to do the whole problem with regular expressions, but at
this point I decided to look for a nice modern parser library that let
me write down the grammer in EBNF notation and simply returned a parse
tree when given a valid expression. I found &lt;a href=&#34;https://github.com/lark-parser/lark&#34;&gt;Lark&lt;/a&gt;, which is roughly as
featureful as Instaparse and worked well. Here&amp;#39;s the Lark grammar as
it currently stands:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;start  : _exprs
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;_exprs : _e* _e
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;_e     : ATOM
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       | _num
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       | BOOL
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       | list
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;TRUE   : &amp;#34;#t&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;FALSE  : &amp;#34;#f&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;BOOL   : TRUE | FALSE
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;list   : &amp;#34;(&amp;#34; _exprs? &amp;#34;)&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;INT    : /[-+]?[0-9]+/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ATOM   : /[a-zA-Z]+[a-zA-Z0-9\-\?]*/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       | /[\*\/\=\&amp;gt;\&amp;lt;]/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       | /[\-\+](?![0-9])/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;FLOAT  : /[-+]?[0-9]+\.[0-9]*/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;_num   : INT | FLOAT
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;%import common.WS
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;%ignore WS&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note that while libraries like Lark and Instaparse are a nice
way to turn out a powerful parser quickly, Norvig&amp;#39;s &lt;code class=&#34;verbatim&#34;&gt;lis.py&lt;/code&gt; just
splits the inputs on open/close parens and uses them to
increase/decrease nesting level as they appear. The approach to
parsing numbers is also elegant: try to parse it as an integer; if
that fails, as a float; otherwise, it&amp;#39;s a symbol (what my grammar
calls &lt;code class=&#34;verbatim&#34;&gt;ATOM&lt;/code&gt;). I suspect that using a &amp;#34;real&amp;#34; parser makes it easier to add more syntax to your language if needed, though.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-6&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-6&#34;&gt;
Data Model
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-6&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;Once Lark parses an expression, I convert to my own internal
representation before evaluation (function &lt;a href=&#34;https://github.com/eigenhombre/smallscheme/blob/master/smallscheme/scheme.py#L52&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;convert_ast&lt;/code&gt;&lt;/a&gt;). I did not
use objects to represent lists, atoms, etc., but just simple tuples
and lists:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Data Type&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Atom&lt;/td&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;(&amp;#39;atom&amp;#39;, &amp;#39;foo&amp;#39;)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Boolean&lt;/td&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;(&amp;#39;bool&amp;#39;, True)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Int&lt;/td&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;(&amp;#39;int&amp;#39;, 123)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Float&lt;/td&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;(&amp;#39;float&amp;#39;, 3.14)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;List&lt;/td&gt;
&lt;td&gt;&lt;code class=&#34;verbatim&#34;&gt;(&amp;#39;list&amp;#39;, [(&amp;#39;atom&amp;#39;, &amp;#39;define&amp;#39;), (&amp;#39;atom&amp;#39;, &amp;#39;x&amp;#39;), (&amp;#39;int&amp;#39;, 3)])&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;It might be more idiomatic Python to use objects, but I&amp;#39;m more used to
thinking in terms of nested structures of base data types (lists,
tuples, dictionaries), which have the advantage of being easily
printable while debugging.&lt;/p&gt;
&lt;p&gt;
Here&amp;#39;s an example expression, parsed with Lark and then converted into
my internal representation:&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-7&#34; class=&#34;outline-4&#34;&gt;
&lt;h4 id=&#34;headline-7&#34;&gt;
Scheme raw source
&lt;/h4&gt;
&lt;div id=&#34;outline-text-headline-7&#34; class=&#34;outline-text-4&#34;&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(define (abs x)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (if (&amp;lt; x 0)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (- x)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      x))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-8&#34; class=&#34;outline-4&#34;&gt;
&lt;h4 id=&#34;headline-8&#34;&gt;
Lark output
&lt;/h4&gt;
&lt;div id=&#34;outline-text-headline-8&#34; class=&#34;outline-text-4&#34;&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Tree(start,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     [Tree(list,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           [Token(ATOM, &amp;#39;define&amp;#39;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            Tree(list,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                 [Token(ATOM, &amp;#39;abs&amp;#39;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                  Token(ATOM, &amp;#39;x&amp;#39;)]),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            Tree(list, [Token(ATOM, &amp;#39;if&amp;#39;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        Tree(list,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                             [Token(ATOM, &amp;#39;&amp;lt;&amp;#39;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                              Token(ATOM, &amp;#39;x&amp;#39;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                              Token(INT, &amp;#39;0&amp;#39;)]),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        Tree(list,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                             [Token(ATOM, &amp;#39;-&amp;#39;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                              Token(ATOM, &amp;#39;x&amp;#39;)]),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        Token(ATOM, &amp;#39;x&amp;#39;)])])])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-9&#34; class=&#34;outline-4&#34;&gt;
&lt;h4 id=&#34;headline-9&#34;&gt;
Internal representation used in the interpreter
&lt;/h4&gt;
&lt;div id=&#34;outline-text-headline-9&#34; class=&#34;outline-text-4&#34;&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[(&amp;#39;list&amp;#39;, [(&amp;#39;atom&amp;#39;, &amp;#39;define&amp;#39;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           (&amp;#39;list&amp;#39;, [(&amp;#39;atom&amp;#39;, &amp;#39;abs&amp;#39;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                     (&amp;#39;atom&amp;#39;, &amp;#39;x&amp;#39;)]),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           (&amp;#39;list&amp;#39;, [(&amp;#39;atom&amp;#39;, &amp;#39;if&amp;#39;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                     (&amp;#39;list&amp;#39;, [(&amp;#39;atom&amp;#39;, &amp;#39;&amp;lt;&amp;#39;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                               (&amp;#39;atom&amp;#39;, &amp;#39;x&amp;#39;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                               (&amp;#39;int&amp;#39;, 0)]),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                     (&amp;#39;list&amp;#39;, [(&amp;#39;atom&amp;#39;, &amp;#39;-&amp;#39;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                               (&amp;#39;atom&amp;#39;, &amp;#39;x&amp;#39;)]),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                     (&amp;#39;atom&amp;#39;, &amp;#39;x&amp;#39;)])])]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-10&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-10&#34;&gt;
Evaluation
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-10&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/eigenhombre/smallscheme/blob/master/smallscheme/scheme.py#L299&#34;&gt;Evaluation&lt;/a&gt; turned out, not surprisingly, to be where most of the work is; specifically, the individual cases for special forms. These were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&#34;verbatim&#34;&gt;quote&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&#34;verbatim&#34;&gt;cond&lt;/code&gt; / &lt;code class=&#34;verbatim&#34;&gt;if&lt;/code&gt; (I implemented these separately but, had I implemented
macros, I might implement one in terms of the other)&lt;/li&gt;
&lt;li&gt;&lt;code class=&#34;verbatim&#34;&gt;define&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&#34;verbatim&#34;&gt;lambda&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&#34;verbatim&#34;&gt;or&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&#34;verbatim&#34;&gt;and&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Aside from these, there was code for normal function application rules, with a slight variance between internally-defined functions and functioned defined by the user with &lt;code class=&#34;verbatim&#34;&gt;define&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
I did not, &lt;a href=&#34;http://www.paulgraham.com/rootsoflisp.html&#34;&gt;as Paul Graham did&lt;/a&gt;, attempt to find the minimal subset of language elements needed to bootstrap a complete Lisp, though that is certainly an interesting exercise. My goal was to get my tests green in a straightforward way, as described below.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-11&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-11&#34;&gt;
Printing
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-11&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
The &lt;em&gt;Print&lt;/em&gt; stage needed to convert the internal representation of the
evaluated result to a string, both for a user running a REPL, and for
my unit tests. This turned out to be simple enough that I can put the
entire function here:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;def printable_value(ast):
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    k, v = ast
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    if k == &amp;#39;int&amp;#39; or k == &amp;#39;float&amp;#39;:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        return str(v)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    if k == &amp;#39;bool&amp;#39;:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        return {True: &amp;#34;#t&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                False: &amp;#34;#f&amp;#34;}.get(v)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    if k == &amp;#39;intproc&amp;#39;:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        return &amp;#34;Internal procedure &amp;#39;%s&amp;#39;&amp;#34; % v
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    if k == &amp;#39;atom&amp;#39;:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        return v
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    if k == &amp;#39;list&amp;#39;:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        return &amp;#39;(&amp;#39; + &amp;#39; &amp;#39;.join([printable_value(x)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                               for x in v]) + &amp;#39;)&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    if k == &amp;#39;nop&amp;#39;:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        return &amp;#39;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    if k == &amp;#39;fn&amp;#39;:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        (fn_name, _, _) = v
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        if fn_name == &amp;#39;lambda&amp;#39;:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            return &amp;#34;Anonymous-function&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        return &amp;#34;Function-&amp;#39;%s&amp;#39;&amp;#34; % str(fn_name)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    raise Exception(&amp;#39;Unprintable ast &amp;#34;%s&amp;#34;&amp;#39; % str(ast))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The primitive data types (&lt;code class=&#34;verbatim&#34;&gt;int&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;float&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;bool&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;atom&lt;/code&gt;) are
obvious enough; &lt;code class=&#34;verbatim&#34;&gt;intproc&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;fn&lt;/code&gt; are for internally-defined and
user-defined functions, respectively; finally, &lt;code class=&#34;verbatim&#34;&gt;nop&lt;/code&gt; is for when you
don&amp;#39;t want any value shown to the user (i.e., after one enters a
&lt;code class=&#34;verbatim&#34;&gt;define&lt;/code&gt; expression, there is no output printed before the next
prompt):&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;scheme&amp;gt; (define a 3)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;scheme&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-12&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-12&#34;&gt;
Testing Approach
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-12&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;I used a fairly strict test-driven development workflow for this
project: write just enough new test code to fail; write just enough
production code to get the test to pass; then refactor. This workflow
generally serves me well for harder problems where I&amp;#39;m unlikely to see
the best way to do things from the outset and I expect to make many
improvements: I know the tests will have my back when I make
changes. This turned out to be the right approach, since I had to
pivot several times.&lt;/p&gt;
&lt;p&gt;
I didn&amp;#39;t just use tests drive the code forward, but let SICP drive the
&lt;em&gt;tests&lt;/em&gt; forward as well. When I needed the next thing to work on, all
I had to do was turn forward a few pages in the book, and the page
count gave me a measure of my progress.&lt;/p&gt;
&lt;p&gt;
A few of the tests, with the corresponding page numbers:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    # Adapted from SICP p. 8:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    t(&amp;#34;(define pi 3.14159)&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    t(&amp;#34;(define radius 10)&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    t(&amp;#34;(* pi (* radius radius))&amp;#34;, &amp;#34;314.159&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    # p. 19:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    t(&amp;#34;(define x 7)&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    t(&amp;#34;(and (&amp;gt; x 5) (&amp;lt; x 10))&amp;#34;, &amp;#34;#t&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    # p. 37
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    t(&amp;#34;&amp;#34;&amp;#34;(define (fib n)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           (cond ((= n 0) 0)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                 ((= n 1) 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                 (else (+ (fib (- n 1))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                          (fib (- n 2))))))&amp;#34;&amp;#34;&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    t(&amp;#34;(fib 5)&amp;#34;, &amp;#34;5&amp;#34;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Here &lt;code class=&#34;verbatim&#34;&gt;t&lt;/code&gt; (a very short function name since it&amp;#39;s used so many times) is
a testing function which evaluates the code supplied in the first
argument, using the current &amp;#34;environment&amp;#34; (scope). If a second argument
(a string) is supplied, it also asserts that the code in the first
argument evaluates to the second.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-13&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-13&#34;&gt;
The Code Comes To Life
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-13&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;One of my favorite things about this project was when I started
writing nontrivial tests which &lt;em&gt;already passed&lt;/em&gt;, because enough of the
language had been implemented already. This happened more often as the
project progressed, and it made me feel like I&amp;#39;d implemented a &amp;#34;real&amp;#34;
language, an oddly compelling feeling.&lt;/p&gt;
&lt;p&gt;
The code, in its entirety, can be found &lt;a href=&#34;https://github.com/eigenhombre/smallscheme&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-14&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-14&#34;&gt;
Next Steps
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-14&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;Though I have already gone far past my goals for the project, there are a few directions which I could take this.&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-15&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-15&#34;&gt;
Implement more of Scheme
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-15&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;For example, I don&amp;#39;t have strings yet in my implementation!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-16&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-16&#34;&gt;
Extend it Further
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-16&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;Implement Python interop and shell features. This could be genuinely
fun and useful, but there&amp;#39;s already &lt;a href=&#34;https://github.com/hylang/hy&#34;&gt;a fairly full-featured Lisp skin
for Python called Hy&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-17&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-17&#34;&gt;
Go Low Level
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-17&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;Do it again, but in a faster, lower-level language. Python is
relatively slow compared to Clojure for long-running programs, and
slower than Common Lisp or C for program startup. I&amp;#39;ve been wanting to
dust off my C chops, and this would be an excuse to do so, though C is
a bit primitive compared to, say, Rust. (Go is not to my taste so I
wouldn&amp;#39;t pick it for a fun project like this one.) So, either an
excuse to learn Rust or to improve my C chops. Which leads me to the
final question: would I rather implement Lisps, or program in them? Up
until now it has been the latter, but after the past few weeks I can
definitely taste the appeal of the former.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-18&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-18&#34;&gt;
Thoughts Upon Revisiting Python
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-18&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;This was the biggest Python project I&amp;#39;ve done in five years, so it was
interesting to check my experience of the language after some time
away in Clojure-land. I was a big Python fan for many years but my
enthusiasm for the language has definitely cooled. This is partly due to the performance comparison I just mentioned, but the two other things I really missed were REPL integration and structural editing.&lt;/p&gt;
&lt;p&gt;
In Lisps such as Clojure and Common Lisp I can send expressions to the
REPL directly from Emacs and see the results instantly. It&amp;#39;s difficult
to describe how helpful this short feedback cycle is until you&amp;#39;ve
experienced it. Writing the interpreter, I got sort of close by using
&lt;a href=&#34;https://github.com/eigenhombre/continuous-testing-helper&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;conttest&lt;/code&gt;&lt;/a&gt; plus &lt;code class=&#34;verbatim&#34;&gt;nosetests&lt;/code&gt;: my unit tests ran every time I saved
a source file, and if I wanted to inspect some object I could add a
&lt;code class=&#34;verbatim&#34;&gt;print&lt;/code&gt; or two temporarily to the code I was working on. But this is
definitely more clumsy than a Lisp REPL directly integrated with my editor.&lt;/p&gt;
&lt;p&gt;
Structural editing (via &lt;a href=&#34;http://danmidwood.com/content/2014/11/21/animated-paredit.html&#34;&gt;Paredit&lt;/a&gt;) is another thing that is hard to
explain the utility of but which is hard to live without once you&amp;#39;re
used to it.  The basic idea is that you are no longer editing strings
of text, but the actual tree of nested lists comprising your code -
killing, splitting, joining, absorbing (&amp;#34;slurping&amp;#34;) into and expelling
(&amp;#34;barfing&amp;#34;) from those lists.  Working with the code at the tree level
is a powerful way to edit your code, and &lt;a href=&#34;https://www.youtube.com/watch?v=D6h5dFyyUX0&#34;&gt;watching this video might
help&lt;/a&gt; may give a hint of it. Once you&amp;#39;re used to the affordances of
Paredit or its cousins, it feels clunky and primitive to go back to
editing plain old text.&lt;/p&gt;
&lt;p&gt;
Other value propositions of Clojure, such as macros, immutable
data structures and concurrency, weren&amp;#39;t really an issue for this
project, though I would certainly miss them for bigger projects.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-19&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-19&#34;&gt;
Conclusion
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-19&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Implementing your own Lisp is surprisingly do-able (and fun!). Python
is certainly a fine tool for the job (though if you want to skip straight to programming in a modern Lisp for your day job, please &lt;a href=&#34;http://johnj.com/contact.html&#34;&gt;contact me&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-20&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-20&#34;&gt;
Postscript
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-20&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
While digging through my digital and mental archives for Lisp things I remembered something I hadn&amp;#39;t seen in a long time: the use of closing square brackets to terminate a deeply-nested collection of s-expressions (i.e. &lt;code class=&#34;verbatim&#34;&gt;]&lt;/code&gt; instead of &lt;code class=&#34;verbatim&#34;&gt;)))))))&lt;/code&gt;). Did I imagine it? While not necessarily a good idea, it&amp;#39;s an interesting one. Then, while reading through Gabriel and Steele&amp;#39;s &lt;a href=&#34;https://dl.acm.org/citation.cfm?id=155373&#34;&gt;Evolution of Lisp&lt;/a&gt; this morning, I came across the following snippet:&lt;/p&gt;
&lt;p&gt;
&amp;#34;One of the minor, but interesting, syntactic extensions that
Interlisp made was the introduction of the superparenthesis, or
superbracket. If a right square bracket &lt;code class=&#34;verbatim&#34;&gt;]&lt;/code&gt; is encountered during a
read operation, it balances all outstanding open left parentheses, or
back to the last outstanding left square bracket &lt;code class=&#34;verbatim&#34;&gt;[&lt;/code&gt;.&amp;#34;&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;DEFINEQ((FACTORIAL
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (LAMBDA (N)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   (COND [(ZEROP N) 1]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (T (TIMES N (FACTORIAL (SUB1 N]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Bingo! I wasn&amp;#39;t imagining it.  This suggests those workstations in the
basement of MACC at UW-Madison were probably running Interlisp.&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/for-the-trees.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/for-the-trees_hu_895555d88ddbe0d5.png&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr class=&#34;footnotes-separatator&#34;&gt;
&lt;div class=&#34;footnote-definitions&#34;&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-1&#34;&gt;&lt;a href=&#34;#footnote-reference-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;So compelling that I left &lt;a href=&#34;https://icecube.wisc.edu&#34;&gt;an exciting science project&lt;/a&gt;
partly in order to do Lisp (Clojure) programming full time.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Show at NUPOC</title>
      <link>http://johnj.com/posts/nupoc/</link>
      <pubDate>Wed, 10 Oct 2018 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/nupoc/</guid>
      <description>
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/nupoc-card.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/nupoc-card_hu_1c674a411a0403d5.png&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
I am pleased to announce:&lt;/p&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css?family=Titillium+Web:400,400i&#34; rel=&#34;stylesheet&#34;&gt;
&lt;h2 style=&#34;font-size: 2em; font-family: &#39;Titillium Web&#39;, sans-serif; font-style: Italic;&#34;&gt;Of the Flesh but not the World...&lt;/h2&gt;
&lt;p&gt;
A show of nine works in a small gallery space at the Feinberg
School of Medicine at the &lt;a href=&#34;https://www.nupoc.northwestern.edu/&#34;&gt;Northwestern University
Prosthetics-Orthotics Center&lt;/a&gt; (NUPOC).&lt;/p&gt;
&lt;p&gt;
The works include four paintings made from life at NUPOC over the
course of the last few months. There are also paintings and drawings
done from life at the &lt;a href=&#34;https://paletteandchisel.org/&#34;&gt;Palette and Chisel Academy of Fine Art&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/DSCN3455sm.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/DSCN3455sm_hu_6470429765726216.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Plagiocephaly Helmet Casts, oil on panel, 12&amp;#34; x 9&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-1&#34;&gt;
Location and Hours
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Feinberg School of Medicine&lt;br&gt;
Northwestern University Prosthetics-Orthotics Center (NUPOC)&lt;br&gt;
680 North Lake Shore Drive, Suite 1100&lt;br&gt;
Chicago, IL 60611&lt;br&gt;
312-503-5700&lt;/p&gt;
&lt;p&gt;
Dates: &lt;strong&gt;November 2 through the end of 2018.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
Hours: &lt;strong&gt;Monday-Friday, 9 AM - 4:30 PM&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
A quick Google will show a number of parking options nearby. The
building is about four blocks from Navy Pier; the closest El stop is
Chicago Ave., on the Red Line.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/johnportrait.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/johnportrait_hu_a174d49d3c3b1e43.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Portrait of J., oil on panel, 11.5&amp;#34; x5.5&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-2&#34;&gt;
Artist&amp;#39;s Statement
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-3&#34;&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#34;&lt;strong&gt;Of the flesh but not the world?&lt;/strong&gt; How peculiar. How can that be? It
sounds like maths, only more practical somehow.&amp;#34;
– Thomas Pynchon, &lt;em&gt;Against the Day&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
For the past six months I have had the privilege of painting from life
roughly once per week at the &lt;a href=&#34;https://www.nupoc.northwestern.edu/&#34;&gt;Northwestern University
Prosthetics-Orthotics Center&lt;/a&gt; (NUPOC).  NUPOC carries out research and
training in the design, manufacture, and application of orthotic and
prosthetic devices.  Aside from representing a fascinating synthesis
of engineering and medicine, it is a visually rich environment
hosting hundreds of artifacts, all of which relate in some way to
the human form.&lt;/p&gt;
&lt;p&gt;
These artifacts appeal to both the engineer and the artist in me.  The
anatomical models, common in both medical schools and art studios, are
not only helpful objects of study (a figurative artist ought to know
how the body is put together), but beautiful objects of contemplation
in their own right.  In addition, NUPOC&amp;#39;s collection of historical and
current prostheses and orthoses, ranging from the crude to the
intricate, is visually fascinating… any of these objects could
be the cornerstone of a striking still life painting.&lt;/p&gt;
&lt;p&gt;
In addition to the four paintings done at NUPOC, there are figurative
paintings and drawings based on live models. They represent a subset
of many studies carried out over the past few years at the &lt;a href=&#34;https://paletteandchisel.org/&#34;&gt;Palette and
Chisel Academy of Fine Arts&lt;/a&gt;, a century-old Chicago institution where
one can find people drawing and painting from life nearly every day of
the year.  Working from life and studying anatomy are centuries-old
strategies for turning paint into convincing illusions - to create
bodies that are &amp;#34;of the flesh, but not the world.&amp;#34;&lt;/p&gt;
&lt;p&gt;
From the standpoint of engineering, I find the devices at NUPOC
intriguing for their mix of high- and low-tech.  3D printers and
advanced polymers contrast with mechanical joints, hooks, levers and
cables.  Automated mass-production of some components exists in
conjunction with highly customized fittings of others, to adapt to
every individual&amp;#39;s unique morphology and requirements.  High-tech is
not necessarily better tech: advanced prostheses with multiple digits
controlled by nerve induction may be less appropriate than a more
straightforward, affordable device that can be maintained by its
wearer &amp;#34;in the field.&amp;#34;&lt;/p&gt;
&lt;p&gt;
More generally, the artifacts represent a literal meeting of the human
organism, with its animal origins, and the engineered world.  Limbs
lost, or never present, can be augmented in capability, at
times far past their &amp;#34;baseline&amp;#34; functionality.  What could be more
human than to build devices to mold or extend the function of our bodies
challenged by trauma, age, genetics, or other vicissitudes?  What are
the limits of our flesh, assisted or no?  These are interesting
questions for a figurative artist to ponder.&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Many thanks to the staff at NUPOC for their assistance and hospitality.&lt;/em&gt;&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/DSCN3473.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/DSCN3473_hu_549aa9f5dc96ac19.jpg&#34; style=&#34;width:150px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
NUPOC Leg Model (&amp;#34;Legcorché&amp;#34;), oil on linen, 7&amp;#34;x28&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/JacobsenGift-RJG_0183.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/JacobsenGift-RJG_0183_hu_a7251931fc1725c8.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Gift to NUPOC with RJ Garrick
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-3&#34;&gt;
For news and updates
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Say hi &lt;a href=&#34;http://johnj.com/contact&#34;&gt;on email&lt;/a&gt;, or check me &lt;a href=&#34;https://www.instagram.com/eigenhombre/&#34;&gt;on Instagram&lt;/a&gt; (&lt;code class=&#34;verbatim&#34;&gt;eigenhombre&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Color Notations</title>
      <link>http://johnj.com/posts/color-codes/</link>
      <pubDate>Wed, 19 Sep 2018 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/color-codes/</guid>
      <description>
&lt;p&gt;
I have been experimenting with notations for color mixtures, so I can
make notes about colors on the go without actually carrying a whole
set of oil paints everywhere.&lt;/p&gt;
&lt;p&gt;
Here&amp;#39;s an example from a very quick sketch during tonight&amp;#39;s commute home:





&lt;a href=&#34;http://johnj.com/IMG_20180919_0001.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20180919_0001_hu_215e041969ee6282.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Though it may &lt;em&gt;look&lt;/em&gt; black and white, there are a dozen colors
captured in this quick sketch.  In this post, I briefly describe the
notation.&lt;/p&gt;
&lt;p&gt;
The letters are based on my oil painting palette of late: usually,&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;provider&lt;/td&gt;
&lt;td&gt;pigment number&lt;/td&gt;
&lt;td&gt;code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cremnitz white&lt;/td&gt;
&lt;td&gt;RGH&lt;/td&gt;
&lt;td&gt;PW 1&lt;/td&gt;
&lt;td&gt;w&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nickel (titanium) yellow&lt;/td&gt;
&lt;td&gt;Williamsburg&lt;/td&gt;
&lt;td&gt;PY 53&lt;/td&gt;
&lt;td&gt;n&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;winsor (primary) yellow&lt;/td&gt;
&lt;td&gt;Holbein&lt;/td&gt;
&lt;td&gt;PY 74&lt;/td&gt;
&lt;td&gt;y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;raw sienna&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PBr 7&lt;/td&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;transparent earth yellow&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PY 42&lt;/td&gt;
&lt;td&gt;t&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;venetian red&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PR 101&lt;/td&gt;
&lt;td&gt;v&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cadmium red light&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PR 108&lt;/td&gt;
&lt;td&gt;c&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pyrrole red&lt;/td&gt;
&lt;td&gt;Holbein&lt;/td&gt;
&lt;td&gt;PR 254&lt;/td&gt;
&lt;td&gt;p&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;brown pink&lt;/td&gt;
&lt;td&gt;Williamsburg&lt;/td&gt;
&lt;td&gt;PR 101&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;spanish earth&lt;/td&gt;
&lt;td&gt;Williamsburg&lt;/td&gt;
&lt;td&gt;PR 102&lt;/td&gt;
&lt;td&gt;a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;quinacradone violet&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PV 19&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dioxazine purple&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PV 23&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cobalt blue&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PB 28&lt;/td&gt;
&lt;td&gt;o&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(real) manganese blue&lt;/td&gt;
&lt;td&gt;Vasari&lt;/td&gt;
&lt;td&gt;PB 33&lt;/td&gt;
&lt;td&gt;m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;prussian blue&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PB 27&lt;/td&gt;
&lt;td&gt;r&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ivory black&lt;/td&gt;
&lt;td&gt;Williamsburg&lt;/td&gt;
&lt;td&gt;PBk 9&lt;/td&gt;
&lt;td&gt;b&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;viridian&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PG 18&lt;/td&gt;
&lt;td&gt;i&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;terre verte&lt;/td&gt;
&lt;td&gt;Gamblin&lt;/td&gt;
&lt;td&gt;PY 43, PG 18, PBk 9&lt;/td&gt;
&lt;td&gt;e&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;raw umber&lt;/td&gt;
&lt;td&gt;Williamsburg&lt;/td&gt;
&lt;td&gt;PBr 7&lt;/td&gt;
&lt;td&gt;u&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
Since there are fewer than two dozen colors, a single letter can be
assigned to each pigment (the rightmost column shows my assignations as
of this morning).  I&amp;#39;d like to whittle the number of colors down even
further, but I&amp;#39;m hooked on the various properties of each of these.
Almost all of them are pure pigments… the only mixture is terre
verte, which I love for its transparency, mass tone and utility in
mixing cool midtones.&lt;/p&gt;
&lt;p&gt;
Occasionally I&amp;#39;ll throw in another pigment for special occasions, or
start out with just a few for underpaintings, but usually I lay most
of these out for any given painting session.&lt;/p&gt;
&lt;p&gt;
The notation, then, is very similar to that used for writing chemical
compositions, which you might remember from high school chemistry:
$\mathrm{H_2O}$ is water, and $\mathrm{C_{18}H_{32}O_2}$
is linoleic acid, one of the components of linseed oil.&lt;/p&gt;
&lt;p&gt;
For paint mixtures, we apply a similar rule: one letter per &amp;#34;element&amp;#34;
(paint color/pigment), with an optional numerical suffix to indicate a
correspondingly higher proportion (for simplicity we eliminate the
subscripting of the numbers).&lt;/p&gt;
&lt;p&gt;
For example, king&amp;#39;s blue, which is typically white plus cobalt blue,
is, in my system,&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;w2o&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
… i.e., roughly two parts Cremnitz (lead) white per part of cobalt
blue.&lt;/p&gt;
&lt;p&gt;
Not every color I might use is assigned a letter.  In this case, just
write the pigment code in parentheses.  For example, for an exact
match for commercial king&amp;#39;s blue, I would use titanium white (PW-6)
instead of the more transparent lead white; in this case, king&amp;#39;s blue is&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;(PW6)2o&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
Now let&amp;#39;s talk through the sketch at the top, location by
location. The head is mostly backlit (&lt;em&gt;contre-jour&lt;/em&gt;) with light from
the window and some interior light inside the train.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hair on top of head, &lt;strong&gt;b4uw&lt;/strong&gt;: four parts black, plus raw
umber and white.&lt;/li&gt;
&lt;li&gt;Fairly flat area of color on forehead, &lt;strong&gt;eta&lt;/strong&gt;: terre verte
plus transparent earth yellow plus Spanish earth.&lt;/li&gt;
&lt;li&gt;Left upper highlight, &lt;strong&gt;w4(PV19)&lt;/strong&gt; - mostly white with a bit of
quinacradone violet.&lt;/li&gt;
&lt;li&gt;Forward/top plane of nose, &lt;strong&gt;w(PV19)s&lt;/strong&gt;: white, quinacradone violet,
raw sienna.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the ear, we use a variant of the notation which has light, mid
tone, and dark values, stacked (in parentheses):&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;vw&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;pn&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;w(PV19)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
… which means,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Light: venetian red + white&lt;/li&gt;
&lt;li&gt;Mid tone: pyrrole red + nickel titanium yellow&lt;/li&gt;
&lt;li&gt;Dark: quinacradone violet + white&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the lips I could see, roughly, light and dark values:&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;w2(PV19)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;w1a1(PV19)1&lt;/strong&gt; [the &lt;strong&gt;1&lt;/strong&gt;&amp;#39;s are superfluous]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
i.e., two portions white per quinacradone violet for light, and white, Spanish
earth and quinacradone violet for the dark.&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-1&#34;&gt;
Are you serious about all this?
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
This may seem like a lot of work, or hard to remember.  The notation
is highly personal, though – your palette and your notation will be
different, and you will remember yours better than mine.  I do find it
interesting that in just a few minutes I was able to make a study
recording a dozen color decisions with just paper and pencil.  One
could work up a simple portrait on this basis alone
(especially if the sketch were a little more complete).&lt;/p&gt;
&lt;p&gt;
This will be hard to do unless you&amp;#39;ve painted enough with your palette
to have some knowledge about how your colors behave when mixed with
each other.  It is a good way to practice thinking about color when
out in the world and away from the easel.  Like preparing for &lt;a href=&#34;./daily-composition-lessons-learned.html&#34;&gt;drawing from memory&lt;/a&gt;, it&amp;#39;s something you can do just about anywhere.&lt;/p&gt;
&lt;p&gt;
This is a work in progress: since I used quinacradone violet multiple
times in my sketch, I am hereby officially dedicating the letter &lt;strong&gt;q&lt;/strong&gt;
to that pigment.  Maybe Williamsburg brown pink can be &lt;strong&gt;k&lt;/strong&gt; (originally
reserved for my chalk putty medium, which maybe I don&amp;#39;t need a letter
for). Dioxazine purple can be &lt;strong&gt;d&lt;/strong&gt;. As my palette evolves (as they tend
to), I expect to swap around my letter assignations … and will have
to remember to write down a key now and then so I can still &amp;#34;decode&amp;#34;
my notations in years to come.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Code and Data</title>
      <link>http://johnj.com/posts/code-and-data/</link>
      <pubDate>Mon, 04 Jun 2018 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/code-and-data/</guid>
      <description>
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/thin-ice.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/thin-ice_hu_2c5da9487f484be.png&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Introduction
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
&lt;em&gt;This article was adapted from discussions we had at the weekly
Clojure study group at OpinionLab, in June, 2018.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
Clojure is a Lisp.  Code is data in Lisp, and data can also be
code. Lisp code consists of lists of symbols (or atoms, as they are
called in other Lisps), other data primitives such as numbers and
keywords, or (nested) lists of the same.&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-1&#34; href=&#34;#footnote-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;
The first item in an expression (list) is the name of an operation,
usually a function; the rest of the items are the arguments. When
lists are nested, the inner expressions are evaluated first: in &lt;code class=&#34;verbatim&#34;&gt;(+ 1
(* 2 3))&lt;/code&gt;, the multiplication happens before the addition.&lt;/p&gt;
&lt;p&gt;
Somewhat less commonly, instead of function names, the first item in
the list may be the name of a macro or so-called &amp;#34;special form.&amp;#34;  In
these cases, the exact method of evaluation depends on the
implementation of the macro or form. For example, in &lt;code class=&#34;verbatim&#34;&gt;(dotimes [_ 10]
(println &amp;#39;hi))&lt;/code&gt;, the &lt;code class=&#34;verbatim&#34;&gt;println&lt;/code&gt; is evaluated 10 times; if &lt;code class=&#34;verbatim&#34;&gt;dotimes&lt;/code&gt;
were a function, &lt;code class=&#34;verbatim&#34;&gt;println&lt;/code&gt; would be evaluated exactly once.&lt;/p&gt;
&lt;p&gt;
To prevent evaluation of an expression, one can &lt;code class=&#34;verbatim&#34;&gt;quote&lt;/code&gt; it:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(quote (+ 1 (* 2 3)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(+ 1 (* 2 3))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The single quote (&amp;#39;) character is an abbreviation for &lt;code class=&#34;verbatim&#34;&gt;quote&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(+ 1 (* 2 3))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(+ 1 (* 2 3))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The REPL will evaluate expressions unless you quote them; if you
decide later you want to evaluate an expression, you can use &lt;code class=&#34;verbatim&#34;&gt;eval&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(def expr &amp;#39;(+ 1 (* 2 3)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(eval expr)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Quoting and evaluation are inverse operations:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(eval (eval (eval (eval &amp;#39;&amp;#39;&amp;#39;&amp;#39;(+ 1 (* 2 3))))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Here are some examples you should try at the REPL, to help build an
understanding of these two operations:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(+ 1 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;+
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;+
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#39;(+ 1 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(cons &amp;#39;+ &amp;#39;(1 1))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(eval (cons &amp;#39;+ &amp;#39;(1 1)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(first &amp;#39;(+ - * /))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(cons (first &amp;#39;(+ - * /)) &amp;#39;(1 1))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(eval (cons (first &amp;#39;(+ - * /)) (rest &amp;#39;(not-a-number 1 1))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(-&amp;gt;&amp;gt; &amp;#39;(not-a-number 1 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     rest
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (cons (first &amp;#39;(+ - * /)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     eval)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Try to understand each of these as best you can, and try some
variations.  The last expression is the same as the one prior to it,
just rewritten using the thread-last (&lt;code class=&#34;verbatim&#34;&gt;-&amp;gt;&amp;gt;&lt;/code&gt;) macro.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
Arithmetic of the Fittest
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
The close relationship of code and data suggests making new code on
the fly to solve problems, which is a concept used in
&lt;a href=&#34;https://en.wikipedia.org/wiki/Genetic_algorithm&#34;&gt;genetic algorithms&lt;/a&gt;.  Here is an example inspired by GAs.  Let&amp;#39;s write
a function which &lt;em&gt;finds expressions involving the four arithmetic
operators that return the number 2.&lt;/em&gt; Examples:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(+ 1 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(- 4 2)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(* 1 2)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(/ 2 1)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
First, let&amp;#39;s make our expression generator (type or copy-paste into your REPL):&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn oper [] (rand-nth &amp;#39;(* / - +)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn digit [] (rand-int 10))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn numlist []
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let [numnums (rand-int 10)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (repeatedly numnums digit)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn expr-fn []
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (cons (oper) (numlist)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Trying these out:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(oper)    ;;=&amp;gt; *
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(oper)    ;;=&amp;gt; /
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(numlist) ;;=&amp;gt; (6)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(numlist) ;;=&amp;gt; (6 9 3 4 4 2 4 3 2)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(expr-fn) ;;=&amp;gt; (/ 6 1 3 7 0 3 0 9)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(expr-fn) ;;=&amp;gt; (- 5 7 2)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Our expression generator selects an arithmetic operator at random, and
tacks it on to the beginning of a random list of 0-9 digits.&lt;/p&gt;
&lt;p&gt;
Evaluating some example functions:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(eval (expr-fn)) ;;=&amp;gt; 0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(eval (expr-fn)) ;;=&amp;gt; 41
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(eval (expr-fn)) ;;=&amp;gt; 7/1152
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(eval (expr-fn)) ;;=&amp;gt; java.lang.ArithmeticException stacktrace!?!?!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This last one shows a problem: some of our expressions will not be
valid mathematically (for example, &lt;code class=&#34;verbatim&#34;&gt;(/ 1 0)&lt;/code&gt;). Let&amp;#39;s catch any exceptions:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn eval-with-catch-exception [expr]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (try
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (eval expr)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (catch Throwable t
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (-&amp;gt; t .getClass .getSimpleName symbol))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This function attempts to evaluate &lt;code class=&#34;verbatim&#34;&gt;expr&lt;/code&gt; and, if the code throws an
exception, simply returns the exception name as a symbol.&lt;/p&gt;
&lt;p&gt;
We are now in a position to try our code generator out:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(dotimes [_ 10]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let [e (expr-fn)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (println e (eval-with-catch-exception e))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
which gives&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(/ 9 8 7 0 0 7 2 2 6) ArithmeticException
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(+ 1 3 3 0 7 7 6) 27
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(+ 4 2) 6
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(- 4 1 2 1 0 0 0) 0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(/ 5 7 0 7) ArithmeticException
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(* 0 4 6) 0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(* 8 6 7 2 4 1) 2688
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(* 7 4 6 9 8 6) 72576
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(*) 1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(- 7) -7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
(&lt;code class=&#34;verbatim&#34;&gt;*&lt;/code&gt; called with no arguments returns 1; &lt;code class=&#34;verbatim&#34;&gt;+&lt;/code&gt; with no arguments returns 0. This may or
may not make intuitive sense to you, depending on how much math you&amp;#39;ve had in
school.)&lt;/p&gt;
&lt;p&gt;
Let&amp;#39;s generate some that return the desired result, 2:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(distinct
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (for [_ (range 1000)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       :let [f (expr-fn)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             result (eval-with-catch-exception f)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             fitness-fn #(= result 2)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       :when (fitness-fn)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   f))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;((+ 2)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (- 9 1 1 1 4)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (- 2 0)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (/ 4 2)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (/ 2 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (* 2))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
(Note that &lt;code class=&#34;verbatim&#34;&gt;(+ n)&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;(* n)&lt;/code&gt; both just return &lt;code class=&#34;verbatim&#34;&gt;n&lt;/code&gt;.)&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-3&#34;&gt;
Macros
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Macros are an advanced topic, but they are relevant because they allow
(among other things) selective evaluation of arguments. Arguments to a
macro can be evaluated zero, one, or many times; this makes macros
especially helpful for implementing control flow: &lt;code class=&#34;verbatim&#34;&gt;loop&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;for&lt;/code&gt;,
&lt;code class=&#34;verbatim&#34;&gt;while&lt;/code&gt; etc. are all macros.&lt;/p&gt;
&lt;p&gt;
Macros rely on code-as-data: they essentially functions which generate
code, which is then evaluated. Most or all modern Lisps have macros,
the equivalent of which are very rare in non-Lisps. These macros play
a large role in making Lisp so expressive.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-4&#34;&gt;
Exercises
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
&lt;strong&gt;Exercise 1&lt;/strong&gt;: Creating and evaluating code on the fly in this manner
is not unique to Lisp, but Lisp provides a very natural way to do
so. Consider how to do the above examples in JavaScript, Ruby, or
other mainstream languages. What, if any, are the differences between
Clojure/Lisp and those languages?&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Exercise 2&lt;/strong&gt;: Set a different arithmetic goal (other than &lt;code class=&#34;verbatim&#34;&gt;2&lt;/code&gt;) and
generate expressions which satisfy it.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Exercise 3&lt;/strong&gt;: Adapt your code generator to include nested expressions,
so that some of the numbers are generated expressions in their own
right.  Example: &lt;code class=&#34;verbatim&#34;&gt;(+ 1 4) -&amp;gt; (+ 1 (* 2 2))&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Exercise 4&lt;/strong&gt;: Instead of generating expressions, adapt &lt;code class=&#34;verbatim&#34;&gt;expr-fn&lt;/code&gt; to
return &lt;em&gt;functions&lt;/em&gt; of no arguments, and adapt the rest of the code to
call and evaluate those functions.  I.e., &lt;code class=&#34;verbatim&#34;&gt;(+ 1 2 3)&lt;/code&gt; becomes &lt;code class=&#34;verbatim&#34;&gt;(fn []
(+ 1 2 3))&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Exercise 5 (advanced)&lt;/strong&gt;: Both the generated functions and the &amp;#34;fitness function&amp;#34;
&lt;code class=&#34;verbatim&#34;&gt;fitness-fn&lt;/code&gt; can be made more complex; for example, in addition to the
operators &lt;code class=&#34;verbatim&#34;&gt;+ - * /&lt;/code&gt; and the numbers 0-9, you could add an &amp;#34;argument&amp;#34;
variable &lt;code class=&#34;verbatim&#34;&gt;x&lt;/code&gt; and change the fitness function to expect expressions
that return the square of &lt;code class=&#34;verbatim&#34;&gt;x&lt;/code&gt;; some acceptable outputs would
then be &lt;code class=&#34;verbatim&#34;&gt;(* x x)&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;(* 1 x x 1)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
Change your expression generator and fitness functions to implement
the squaring function.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Exercise 6 (advanced)&lt;/strong&gt;: try adding other Clojure core functions and
data types to the list of possible operators and arguments; try other
fitness functions as well.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Exercise 7 (more advanced)&lt;/strong&gt;: develop a way of combining expressions
and evaluating the fitness of the resulting expression. To build on
our previous example, if you have the two lists &lt;code class=&#34;verbatim&#34;&gt;(+ 1 1)&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;(* 2
3)&lt;/code&gt;, you could choose terms at random from each list, e.g. &lt;code class=&#34;verbatim&#34;&gt;(* 1 3)&lt;/code&gt;;
you must decide how to handle lists with different lengths.  The
fitness function could just be &lt;code class=&#34;verbatim&#34;&gt;fitness-fn&lt;/code&gt; from our example, or a
more ambitious one&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-2&#34; href=&#34;#footnote-2&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;. If you want to include nested
expressions, then you have to decide how to combine those.&lt;/p&gt;
&lt;p&gt;
Rather than success or failure, the fitness function could return a
number which reflects how well or poorly the expression performed. A
strategy from genetic algorithms is to generate many expressions,
evaluate these, take the best performers, and then generate new
expressions by combining these. Implement this.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-5&#34;&gt;
See Also
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-3&#34;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?reload%3D9&amp;amp;v%3Der_lLvkklsk&#34;&gt;This freaking amazing
talk&lt;/a&gt;&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-3&#34; href=&#34;#footnote-3&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; given
by William Byrd and Greg Rosenblatt on program synthesis, given at
Clojure/conj 2016.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Genetic_algorithm&#34;&gt;Genetic Algorithms&lt;/a&gt; on Wikipedia&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-4&#34; href=&#34;#footnote-4&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
&lt;li&gt;Colin Jones&amp;#39;s excellent &lt;a href=&#34;https://pragprog.com/book/cjclojure/mastering-clojure-macros&#34;&gt;book on macros&lt;/a&gt;&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-5&#34; href=&#34;#footnote-5&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr class=&#34;footnotes-separatator&#34;&gt;
&lt;div class=&#34;footnote-definitions&#34;&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-1&#34;&gt;&lt;a href=&#34;#footnote-reference-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;Other collection types in Clojure are ignored in this post.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-2&#34;&gt;&lt;a href=&#34;#footnote-reference-2&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;like, say, returning a list of the first million or so prime numbers&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-3&#34;&gt;&lt;a href=&#34;#footnote-reference-3&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://www.youtube.com/watch?reload=9&amp;amp;v=er_lLvkklsk&#34;&gt;https://www.youtube.com/watch?reload=9&amp;amp;v=er_lLvkklsk&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-4&#34;&gt;&lt;a href=&#34;#footnote-reference-4&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Genetic_algorithm&#34;&gt;https://en.wikipedia.org/wiki/Genetic_algorithm&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-5&#34;&gt;&lt;a href=&#34;#footnote-reference-5&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://pragprog.com/book/cjclojure/mastering-clojure-macros&#34;&gt;https://pragprog.com/book/cjclojure/mastering-clojure-macros&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>(oodles of delicious atoms)</title>
      <link>http://johnj.com/posts/oodles/</link>
      <pubDate>Wed, 30 May 2018 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/oodles/</guid>
      <description>
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
A Recursive Feast
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
In 1983, Douglas R. Hofstadter, author of &amp;#34;Gödel, Escher, Bach: An
Eternal Golden Braid&amp;#34; wrote a series of articles on Lisp in Scientific
American (later republished in the book &lt;a href=&#34;https://en.wikipedia.org/wiki/Metamagical_Themas&#34;&gt;Metamagical Themas&lt;/a&gt;, which is
where I encountered them for the first time).  While much of the
writing focused on the nature of recursion in programming, the third
and last article in the series provided an entertaining example of
blurring the line between code and data, which is typical for Lisp
(though somewhat less common in Clojure, except for the occasional
macro).&lt;/p&gt;
&lt;p&gt;
In the example, a set of acronyms are presented; each acronym can be
&amp;#34;expanded&amp;#34; into a phrase which itself may contain other acronyms.
The program generates random expansions of these acronyms, &amp;#34;bottoming
out&amp;#34; (hitting the base case) at random, though with increasing
probability of termination for more deeply-nested expressions.&lt;/p&gt;
&lt;p&gt;
What follows is my translation of the Lisp code in his articles into
Clojure, with a few extra details and explanations.  A few interesting
edge cases have to be accounted for to accommodate the differences
between the languages.&lt;/p&gt;
&lt;p&gt;
If you&amp;#39;re interested in running the code, it&amp;#39;s &lt;a href=&#34;https://github.com/eigenhombre/oodles&#34;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
Cooking It Up
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
First, a small macro helps us keep things tidy: &lt;code class=&#34;verbatim&#34;&gt;defpasta&lt;/code&gt; makes a
function that simply returns the list supplied as its argument,
avoiding the need for the argument vector or the quote.  Note that
just one small macro provides enough &amp;#34;syntactic sugar&amp;#34; to make the
examples more readable.  We also attach metadata for convenience in
testing (see below).&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defmacro defpasta [name_ &amp;amp; expr]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  `(defn ~(with-meta name_ {:pasta true}) []
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     &amp;#39;~@expr))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Next are the actual acronym definitions. These are the definitions
Hofstadter uses, with commas treated differently.  The commas are
important in his output, but commas are whitespace in Clojure… so
where the symbols are used with commas in compound statements, we
append &lt;code class=&#34;verbatim&#34;&gt;_CO&lt;/code&gt; to tell the program to supply a comma in the output.
(Example: &lt;code class=&#34;verbatim&#34;&gt;SAUCE,&lt;/code&gt; becomes &lt;code class=&#34;verbatim&#34;&gt;SAUCE_CO&lt;/code&gt;.)&lt;/p&gt;
&lt;p&gt;
We cannot, unfortunately, add commas after lists in this way, but
his example is inconsistent in this regard (three examples have
commas after lists, but the example expansion later in the article
does not).&lt;/p&gt;
&lt;p&gt;
Hostadter presents the acronyms in capital letters, though
Common Lisp atoms (analogous to Clojure symbols) are
case-insensitive; we follow that convention here and use it to
indicate terms which may be expanded… that is to say, the
&lt;code class=&#34;verbatim&#34;&gt;COFFEE&lt;/code&gt; in the expansion of &lt;code class=&#34;verbatim&#34;&gt;SAUCE&lt;/code&gt; can itself be expanded to a
phrase which includes &lt;code class=&#34;verbatim&#34;&gt;ESPRESSO&lt;/code&gt;, and so on.&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta TOMATOES (TOMATOES on MACARONI (and TOMATOES only)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                             exquisitely SPICED))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta MACARONI (MACARONI and CHEESE (a REPAST of Naples_CO Italy)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta REPAST (rather extraordinary PASTA and SAUCE_CO typical))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta CHEESE (cheddar_CO havarti_CO, emmentaler
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                (especially SHARP emmenthaler)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta SHARP (strong_CO hearty_CO and rather pungent))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta SPICED (sweetly pickled in CHEESE ENDIVE dressing))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta ENDIVE (egg NOODLES_CO dipped in vinegar eggnog))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta NOODLES (NOODLES (oodles of delicious LINGUINI) elegantly served))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta LINGUINI (LAMBCHOPS (including NOODLES)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                  gotten usually in Northern Italy))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta PASTA (PASTA and SAUCE (that&amp;#39;s ALL!)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta ALL! (a lucious lunch))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta SAUCE (SHAD and unusual COFFEE (excellente!)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta SHAD (SPAGHETTI_CO heated al dente))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta SPAGHETTI (standard PASTA_CO always good_CO hot particularly
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                              (twist_CO then ingest)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta COFFEE (choice of fine flavors, particularly ESPRESSO))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta ESPRESSO (excellent_CO strong_CO powerful_CO rich ESPRESSO_CO
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                 suppressing sleep outrageously))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta BASTA! (belly all stuffed (tummy ache!)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta LAMBCHOPS (LASAGNE and meatballs_CO casually heaped onto PASTA SAUCE))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta LASAGNE (LINGUINI and SAUCE and GARLIC (NOODLES everywhere!)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta RHUBARB (RAVIOLI_CO heated under butter and RHUBARB (BASTA!)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta RAVIOLI (RIGATONI and vongole in oil_CO lavishly introduced))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta RIGATONI (rich Italian GNOCCHI and TOMATOES (or NOODLES instead)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta GNOCCHI (GARLIC NOODLES over crisp CHEESE_CO heated immediately))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defpasta GARLIC (green and red LASAGNE in CHEESE))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Hofstadter leaves the implementation of &lt;code class=&#34;verbatim&#34;&gt;acronym?&lt;/code&gt; undefined,
since it is so implementation-specific.  In our case, something is
an acronym if it&amp;#39;s a symbol and its name is equal to an
upper case version of itself.&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn acronym? [x]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (and (symbol? x)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (= (name x) (.toUpperCase (name x)))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
We also want to be able to remove commas from a symbol and evaluate
the result as a function. This is also very implementation-specific;
in our case, it relies on Clojure&amp;#39;s machinery for converting symbols
to strings and vice-versa, and on the subtle differences between
symbols, vars, and functions:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn strip-comma-and-eval [sym]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let [base-symbol-name (-&amp;gt; sym
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                             name
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                             (clojure.string/replace #&amp;#34;_CO$&amp;#34; &amp;#34;&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                             symbol)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ((-&amp;gt; *ns*
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          ns-map
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          (get (symbol base-symbol-name))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          var-get))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(strip-comma-and-eval &amp;#39;RHUBARB)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(RAVIOLI_CO heated under butter and RHUBARB (BASTA!))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;code class=&#34;verbatim&#34;&gt;lower&lt;/code&gt; reduces the probability by some amount to encourage our
recursion to bottom out (and thereby avoid stack overflows).
Hofstadter multiplies probabilities by 0.8, but I simply square the
probability so that higher probabilities decrease more slowly than
lower ones as the recursion progresses:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn lower [x] (* x x))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
A significant portion of Hofstadter&amp;#39;s article relates to the
recursive &lt;code class=&#34;verbatim&#34;&gt;expand&lt;/code&gt; function, so I won&amp;#39;t go into details here.  This
version is similar to his; it adds a bottoming-out clause to
accommodate the base case of an empty phrase (since &lt;code class=&#34;verbatim&#34;&gt;()&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;nil&lt;/code&gt;
are not the same in Clojure, as they are in Common Lisp).  Also we
use &lt;code class=&#34;verbatim&#34;&gt;strip-comma-and-eval&lt;/code&gt; instead of plain &lt;code class=&#34;verbatim&#34;&gt;eval&lt;/code&gt; to handle the
comma-ed symbols.&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn expand [phrase probability]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (cond
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (symbol? phrase) phrase
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (empty? phrase) phrase
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (acronym? (first phrase))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (if (&amp;lt; (rand) probability)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (concat
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (expand (strip-comma-and-eval (first phrase)) (lower probability))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (expand (rest phrase) probability))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (cons (first phrase) (expand (rest phrase) probability)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    :else (cons (expand (first phrase) (lower probability))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                (expand (rest phrase) (lower probability)))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Ultimately we want to make the output similar to what Hofstadter shows in
the book.  The &lt;code class=&#34;verbatim&#34;&gt;normalize&lt;/code&gt; function does this, relying on two helper
functions, whose names are self-explanatory:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn lower-case-symbol [x]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (if-not (symbol? x)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    x
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (-&amp;gt; x name .toLowerCase symbol)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn get-commas-back [x]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (if-not (symbol? x)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    x
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (-&amp;gt; x
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        name
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        (clojure.string/replace #&amp;#34;_CO$&amp;#34; &amp;#34;,&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        symbol)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
When we&amp;#39;re done expanding our lists of food (and our bellies), we
prepare our data for output to the user: turn &lt;code class=&#34;verbatim&#34;&gt;_CO&lt;/code&gt; suffixes into
actual commas (using the fact that &lt;code class=&#34;verbatim&#34;&gt;(symbol &amp;#34;x,&amp;#34;)&lt;/code&gt; yields a valid
symbol, if one that would be hard to read back at the REPL); and,
lower-case all symbols to adhere to the style of the output shown in
&lt;em&gt;Metamagical Themas:&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn normalize [expr]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (-&amp;gt;&amp;gt; expr
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (clojure.walk/postwalk get-commas-back)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (clojure.walk/postwalk lower-case-symbol)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-3&#34;&gt;
Dinner Is Served
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Now for the actual function we&amp;#39;ll use to generate our expansions.
Setting a large probability will ensure longer examples:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn dinner [expr]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (normalize (expand expr 0.9999)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
We should test our code to make sure it doesn&amp;#39;t bomb out on any of our
acronyms.  Here we find all the acronyms based on the metadata added
by the &lt;code class=&#34;verbatim&#34;&gt;defpasta&lt;/code&gt; macro, ensuring each runs to completion:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(let [nsm (ns-map *ns*)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (doseq [[k v] nsm :when (:pasta (meta v))]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (dotimes [_ 10]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (dinner (list k)))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
If, like me, you use Emacs and CIDER and want long REPL examples,
you have to set `*print-length*` to something bigger than its
default:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(set! *print-length* 1000)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Now to run it!  Are you hungry yet?&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(dinner &amp;#39;(LINGUINI))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(lasagne and meatballs, casually heaped onto pasta sauce (including
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;noodles) gotten usually in northern italy and standard pasta, always
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;good, hot particularly (twist, then ingest) heated al dente and
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;unusual coffee (excellente!) and green and red lasagne in cheese
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(noodles (oodles of delicious linguini) elegantly served (oodles of
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;delicious linguini) elegantly served everywhere!) and meatballs,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;casually heaped onto pasta shad and unusual coffee (excellente!)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(including noodles (oodles of delicious linguini) elegantly served
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(oodles of delicious linguini) elegantly served (oodles of delicious
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;linguini) elegantly served (oodles of delicious linguini) elegantly
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;served (oodles of delicious lasagne and meatballs, casually heaped
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;onto pasta sauce (including noodles) gotten usually in northern italy)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;elegantly served) gotten usually in northern italy and standard pasta
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;and shad and unusual coffee (excellente!) (that&amp;#39;s all!) and shad and
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;unusual coffee (excellente!) (that&amp;#39;s all!) always good, hot
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;particularly (twist, then ingest) heated al dente and unusual choice
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;of fine flavors particularly espresso (excellente!) and green and red
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;lasagne in cheese (noodles (oodles of delicious linguini) elegantly
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;served (oodles of delicious linguini) elegantly served (oodles of
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;delicious linguini) elegantly served (oodles of delicious linguini)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;elegantly served everywhere!) and meatballs, casually heaped onto
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pasta and sauce (that&amp;#39;s all!) and sauce (that&amp;#39;s all!) and shad and
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;unusual coffee (excellente!) (that&amp;#39;s all!) sauce (including noodles
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(oodles of delicious linguini) elegantly served (oodles of delicious
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;lambchops (including noodles) gotten usually in northern italy)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;elegantly served (oodles of delicious lambchops (including noodles)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gotten usually in northern italy) elegantly served) gotten usually in
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;northern italy and standard pasta and shad and unusual coffee
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(excellente!) (that&amp;#39;s all!) and standard pasta, always good, hot
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;particularly (twist, then ingest) heated al dente and unusual coffee
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(excellente!) (that&amp;#39;s all!) and spaghetti, heated al dente and unusual
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;coffee (excellente!) (that&amp;#39;s a lucious lunch) and standard pasta,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;always good, hot particularly (twist, then ingest) heated al dente and
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;unusual coffee (excellente!) (that&amp;#39;s a lucious lunch) always good, hot
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;particularly (twist, then ingest) heated al dente and unusual choice
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;of fine flavors particularly espresso (excellente!) and green and red
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;linguini and sauce and garlic (noodles everywhere!) and meatballs,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;casually heaped onto pasta sauce (including noodles) gotten usually in
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;northern italy and spaghetti, heated al dente and unusual coffee
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(excellente!) and green and red lasagne in cheese (noodles (oodles of
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;delicious linguini) elegantly served everywhere!) in cheese (noodles
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(oodles of delicious linguini) elegantly served (oodles of delicious
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;linguini) elegantly served (oodles of delicious linguini) elegantly
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;served (oodles of delicious linguini) elegantly served (oodles of
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;delicious linguini) elegantly served (oodles of delicious lambchops
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(including noodles) gotten usually in northern italy) elegantly served
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(oodles of delicious linguini) elegantly served (oodles of delicious
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;linguini) elegantly served everywhere!) and meatballs, casually heaped
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;onto pasta and shad and unusual coffee (excellente!) (that&amp;#39;s a lucious
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;lunch) and sauce (that&amp;#39;s all!) and spaghetti, heated al dente and
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;unusual coffee (excellente!) (that&amp;#39;s a lucious lunch) and standard
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pasta and sauce (that&amp;#39;s all!) always good, hot particularly (twist,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;then ingest) heated al dente and unusual coffee (excellente!) (that&amp;#39;s
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;a lucious lunch) shad and unusual choice of fine flavors particularly
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;espresso (excellente!) (including noodles (oodles of delicious
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;linguini) elegantly served (oodles of delicious linguini) elegantly
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;served (oodles of delicious linguini) elegantly served (oodles of
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;delicious linguini) elegantly served (oodles of delicious lasagne and
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;meatballs, casually heaped onto pasta sauce (including noodles) gotten
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;usually in northern italy) elegantly served (oodles of delicious
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;lambchops (including noodles) gotten usually in northern italy)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;elegantly served (oodles of delicious linguini and sauce and garlic
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(noodles everywhere!) and meatballs, casually heaped onto pasta sauce
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(including noodles (oodles of delicious linguini) elegantly served)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gotten usually in northern italy) elegantly served (oodles of
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;delicious lambchops (including noodles (oodles of delicious linguini)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;elegantly served) gotten usually in northern italy) elegantly served
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(oodles of delicious lasagne and meatballs, casually heaped onto pasta
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sauce (including noodles) gotten usually in northern italy and shad
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;and unusual coffee (excellente!) and garlic (noodles everywhere!) and
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;meatballs, casually heaped onto pasta sauce (including noodles (oodles
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;of delicious linguini) elegantly served (oodles of delicious linguini)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;elegantly served) gotten usually in northern italy) elegantly served
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(oodles of delicious linguini and sauce and garlic (noodles
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;everywhere!) and meatballs, casually heaped onto pasta sauce
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(including noodles) gotten usually in northern italy and spaghetti,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;heated al dente and unusual coffee (excellente!) and garlic (noodles
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(oodles of delicious linguini) elegantly served everywhere!) and
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;meatballs, casually heaped onto pasta sauce (including noodles (oodles
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;of delicious linguini) elegantly served (oodles of delicious linguini)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;elegantly served) gotten usually in northern italy) elegantly served)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;gotten usually in northern italy)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Man, I&amp;#39;m stuffed!&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;A talk based on this code was given as in instructional&lt;/em&gt;
/
&lt;em&gt;fun exercise at Clojurepalooza at OpinionLab in May of 2018.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Painting and Time</title>
      <link>http://johnj.com/posts/painting-time/</link>
      <pubDate>Tue, 29 May 2018 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/painting-time/</guid>
      <description>&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_4756.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_4756_hu_2e8a4cf7dfc139b4.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
&lt;em&gt;Painting is quite old and hard to fool.&lt;/em&gt; –Tad Spurgeon
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
In &lt;a href=&#34;https://www.tadspurgeon.com/the_book.php?page%3Dthe%2Bbook&#34;&gt;&lt;em&gt;Living Craft&lt;/em&gt;&lt;/a&gt;, Spurgeon calls out &lt;em&gt;time&lt;/em&gt; as the first &amp;#34;material&amp;#34;
used to make paintings. He speaks of &amp;#34;extra-logical,&amp;#34; emotional
time, time experienced by the mind of the painter, rather than purely
physical time measured by clocks. His remarks frame an invitation to
contemplate how one experiences time in the studio and what time means
to painters (and, by extension, viewers).&lt;/p&gt;
&lt;p&gt;
There is no question that paintings take time to make, sometimes &lt;em&gt;a
lot&lt;/em&gt; of time… from minutes to hundreds or thousands of
hours.&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-1&#34; href=&#34;#footnote-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;  Much contemporary activity seems to be oriented
around saving time, but a single painting can take the kind of time
jobs take, or marriages, or
kids&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-2&#34; href=&#34;#footnote-2&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.
To me, this slowness is part of painting&amp;#39;s appeal,
one of the reasons that it remains relevant today (as an antidote, at
least). Becoming a painter has meant, for me, learning how (and why)
to spend that kind of time at the easel… on many paintings at once,
switching them as drying times and inspiration require, or on just one
at a time.&lt;/p&gt;
&lt;p&gt;
Paintings connect the present moment of painting (or viewing) with
various points in the past and future. &lt;em&gt;This&lt;/em&gt; moment, &lt;em&gt;this&lt;/em&gt; tip of
&lt;em&gt;this&lt;/em&gt; brush containing &lt;em&gt;this&lt;/em&gt; much of &lt;em&gt;this&lt;/em&gt; color and &lt;em&gt;this&lt;/em&gt;
consistency of paint with &lt;em&gt;this&lt;/em&gt; precise location on &lt;em&gt;this&lt;/em&gt; surface,
and &lt;em&gt;this&lt;/em&gt; breath, &lt;em&gt;this&lt;/em&gt; experience of the image reaching the eye and
brain, all relate to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[ $-$ (0-8) &lt;em&gt;hours&lt;/em&gt; ] the moments just prior to this one; the wet paint just
put down, to be blended into, left alone, rubbed out, scraped off.&lt;/li&gt;
&lt;li&gt;[ + (0-8) &lt;em&gt;hours&lt;/em&gt; ] the moments about to come, in this
session; future marks that will be blended into this one; other
manipulations about to come, including removal if the current
experiment is judged a failure.&lt;/li&gt;
&lt;li&gt;[ $-$ &lt;em&gt;(days, months, years)&lt;/em&gt; ] previous paint layers. Ground,
underpainting, impasto… existing layers are like sedimentary rocks
whose geology tells the story of what the mind and hand were doing
during earlier sessions, recording course corrections, adjustment of
values and edges, and the evolution of emotion, content and
intent. The strata laid down previously are always in the process
of being covered or exposed by the current brush strokes, knife
application, scraping, sanding. These layers also show things
(generally, but not always, mistakes) that you couldn&amp;#39;t see previously, but
that suddenly become, sometimes painfully, clear.&lt;/li&gt;
&lt;li&gt;[ &lt;em&gt;+ (days, months, years)&lt;/em&gt; ] the painting as it slowly dries, and
paint layers to come. Thoughts of translucency and opacity, of
optical mixing, of glazing and scumbling.  Where the painting might
go. Anticipation of coming successes and failures.&lt;/li&gt;
&lt;li&gt;[ $-$ &lt;em&gt;(days, months, years)&lt;/em&gt; ] past drawings or other studies you made for
this painting. Other sketches or paintings you made which led you
down your current path.&lt;/li&gt;
&lt;li&gt;[ &lt;em&gt;+ years&lt;/em&gt; ] future paintings you will (hopefully) make. The
evolution of your thinking, themes, urges, longings; mistakes you
will no longer make; new territories that will open up, that you
can&amp;#39;t even see yet.&lt;/li&gt;
&lt;li&gt;[ $-$ &lt;em&gt;(years, decades)&lt;/em&gt; ] teachings you&amp;#39;ve received from teachers and mentors.&lt;/li&gt;
&lt;li&gt;[ &lt;em&gt;+ (years, decades)&lt;/em&gt; ] paintings to be made by students you taught / may
teach or people you&amp;#39;ve inspired / may inspire.&lt;/li&gt;
&lt;li&gt;[ $-$ &lt;em&gt;(years, centuries)&lt;/em&gt; ] paintings made in the past that you&amp;#39;ve seen /
liked / hated. All the Great Masters; others, in your personal pantheon of
artists. The first artworks you ever saw, or made.&lt;/li&gt;
&lt;li&gt;[ $-$ &lt;em&gt;millennia&lt;/em&gt; ] the earliest paintings made. Cave paintings, paintings
from ancient civilization.&lt;/li&gt;
&lt;li&gt;[ $-$ &lt;em&gt;($10^0$ - $10^2$) years&lt;/em&gt; ] the production, storage,
transportation and cultural context of the raw materials that find
their way into your paintings: panels, stretcher bars, linen,
linseed oil, pigment, brush fibers, bugs, hair, etc. I have panels
prepared by my grandfather and recovered from his woodpile after he
died; a handmade cherry-wood palette I got off Instagram that I
cherish; and a few kilos of powdered manganese blue (PB-33) that I
stockpiled because nobody is producing the pigment or paint anymore.&lt;/li&gt;
&lt;li&gt;[ $-$ &lt;em&gt;($10^9$ - $10^{10}$) years&lt;/em&gt; ] the history of the substances
(atoms/molecules) composing those materials: the annual growth and
harvest of flax from fields in Europe; slow reactions involving iron
in the earth&amp;#39;s crust; the early history of the planet&amp;#39;s formation;
formation of heavy elements such as cadmium, cobalt, and lead in
&lt;a href=&#34;https://en.wikipedia.org/wiki/Supernova_nucleosynthesis&#34;&gt;supernova nucleosynthesis&lt;/a&gt;; the creation of lighter elements occurring the
early universe after the Big Bang.&lt;/li&gt;
&lt;li&gt;[ &lt;em&gt;+ (days, years, centuries)&lt;/em&gt; ] the fate of your work on the walls
of someone&amp;#39;s house / palace / fortress / vault / museum / bomb
shelter (that is, if anyone keeps it around).  Happenstance viewings
in various circumstances by future generations.&lt;/li&gt;
&lt;li&gt;[ &lt;em&gt;+ ($10^{??}$ years)&lt;/em&gt; ] the atoms from your paintings, after they
are burned / rotted / crushed / vaporized /….&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Every moment of painting is in dialogue with all these other moments
and time scales. This conversation of material and mind is far greater
than any one person, but it is available while you work, or look,
&lt;em&gt;right now.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;:Ὁ βίος βραχύς,&lt;/p&gt;
&lt;p&gt;
ἡ δὲ τέχνη μακρή,&lt;/p&gt;
&lt;p&gt;
ὁ δὲ καιρὸς ὀξύς,&lt;/p&gt;
&lt;p&gt;
ἡ δὲ πεῖρα σφαλερή,&lt;/p&gt;
&lt;p&gt;
ἡ δὲ κρίσις χαλεπή.&lt;/p&gt;
&lt;p&gt;
Vita brevis,
ars longa,
occasio praeceps,
experimentum periculosum,
iudicium difficile.&lt;/p&gt;
&lt;p&gt;
(Life is short, and art long, opportunity fleeting, experimentation
perilous, and judgment difficult.&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-3&#34; href=&#34;#footnote-3&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr class=&#34;footnotes-separatator&#34;&gt;
&lt;div class=&#34;footnote-definitions&#34;&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-1&#34;&gt;&lt;a href=&#34;#footnote-reference-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;They also take time to get to, and to digest once you get a chance to see them.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-2&#34;&gt;&lt;a href=&#34;#footnote-reference-2&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;For an example, see Ivan Albright&amp;#39;s painting, &lt;em&gt;That Which I Should Have Done I Did Not Do (The Door)&lt;/em&gt;, which took ten years to complete.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-3&#34;&gt;&lt;a href=&#34;#footnote-reference-3&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Ars_longa,_vita_brevis&#34;&gt;https://en.wikipedia.org/wiki/Ars_longa,_vita_brevis&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Contact Me</title>
      <link>http://johnj.com/contact/</link>
      <pubDate>Sat, 10 Mar 2018 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/contact/</guid>
      <description>
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/homecushion.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/homecushion_hu_8c28c72084561514.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Physical
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;John Jacobsen
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;NPX Designs, LLC.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;5341 S. Cornell Ave #3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Chicago, IL 60615&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
Logical
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;&lt;a href=&#34;mailto:john@johnj.com&#34;&gt;john@johnj.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
Instagram: &lt;a href=&#34;https://www.instagram.com/eigenhombre/&#34;&gt;@eigenhombre&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
Mastodon: &lt;a href=&#34;https://mastodon.art/@eigenhombre&#34;&gt;@eigenhombre@mastodon.art&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
GitHub: &lt;a href=&#34;https://github.com/eigenhombre&#34;&gt;eigenhombre&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-3&#34;&gt;
Numeric
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-2&#34;&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;+1 312 436 1522 (office/mobile/home)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Learning Muscular Anatomy</title>
      <link>http://johnj.com/posts/learning-muscular-anatomy/</link>
      <pubDate>Thu, 22 Feb 2018 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/learning-muscular-anatomy/</guid>
      <description>
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/muscle-overlay.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/muscle-overlay_hu_64b74dab7055c860.png&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Skeleton and muscle overlay study (underlying photo by &lt;a href=&#34;https://www.flickr.com/photos/pixiduc/&#34;&gt;Pixiduc&lt;/a&gt;)
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
A knowledge of the human form is vital for figurative artists. A
detailed understanding of anatomy is especially helpful when working
from life or constructing the figure from imagination.&lt;/p&gt;
&lt;p&gt;
Various approaches have been taken to learning artistic anatomy.
While I&amp;#39;d rather not rob graveyards and &lt;a href=&#34;https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3361109/&#34;&gt;do my own dissections&lt;/a&gt;, there
are, fortunately, excellent anatomy books[1] available for the artist.&lt;/p&gt;
&lt;p&gt;
I have found the muscles harder to learn than the skeleton, so I
developed the method outlined here, which involves reading, data
entry, and memorization.  Other methods include drawing muscles on
tracing paper over figure drawings or photographs, or sculpting
muscles atop a pre-formed skeleton.  This practice supplements, but
does not replace, those other methods.&lt;/p&gt;
&lt;p&gt;
A few key facts can be helpful to learn, for each of the important
muscles (&amp;lt; 100 of them, roughly):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Muscle name&lt;/li&gt;
&lt;li&gt;Origin of muscle (attachment point, stationary during contraction)&lt;/li&gt;
&lt;li&gt;Insertion of muscle (attachment point, moves during contraction)&lt;/li&gt;
&lt;li&gt;Function: what the muscle does&lt;/li&gt;
&lt;li&gt;What the muscle overlaps&lt;/li&gt;
&lt;li&gt;What the muscle is overlapped by.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These last two points can be helpful in constructing a mental
model of the muscular forms and of the entire form they help to
create.&lt;/p&gt;
&lt;p&gt;
I use the &lt;a href=&#34;https://apps.ankiweb.net/&#34;&gt;Anki&lt;/a&gt; flash card system as a tool for memorization.  Anki
uses a carefully designed model to set the timing of when you see
individual cards, showing you ones you got wrong sooner, and gradually
showing them less and less often as you learn.&lt;/p&gt;
&lt;p&gt;
For all the muscles you want to study, you can enter these key facts
into a table, and then export the table into flashcards. The original
Org file can be kept in Git under source control and shared with
others, and presents a convenient overview of the entire corpus of
data.  Merely entering the data in the first place starts the
memorization, and then each table field can be paired with the muscle
name both &amp;#34;forwards&amp;#34; and &amp;#34;backwards&amp;#34; (fact-&amp;gt;muscle and muscle-&amp;gt;fact)
as separate flashcards.  Thus, for, say, 100 muscle names and the
associated five facts per muscle, one has 100 x 5 x 2 = 1,000
flashcards.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/anatomy-table-example.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/anatomy-table-example_hu_d18d509fdf34fd34.png&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Example table in Org Mode
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
There are Anki decks for muscular anatomy already available, but they
tend to be large in size and have a medical rather than artistic
context; also, finding and summarizing the information required to
create the cards helps me learn.&lt;/p&gt;
&lt;p&gt;
I wrote &lt;a href=&#34;https://github.com/eigenhombre/anatomy/blob/master/src/anatomy/core.clj&#34;&gt;a tiny Clojure program&lt;/a&gt; (&lt;a href=&#34;https://github.com/eigenhombre/anatomy/blob/master/src/anatomy/core.clj&#34;&gt;GitHub repository here&lt;/a&gt;) to facilitate exporting the Org
data into Anki, which accepts tab-separated lines.  I run it whenever
I add new muscles into my table.&lt;/p&gt;
&lt;p&gt;
Since Anki synchronizes with my phone, I can review whenever I have a
short break.  If I enter a few muscles a week, the data entry should
roughly keep up with my memorization practice, and will then have all
the relevant muscles memorized in well under a year with minimal daily
effort… perhaps five minutes per day.&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-1&#34;&gt;
Sample program output
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-3&#34;&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ lein run
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Function of Sartorius	flexes, weakly abducts, rotates upper leg; flexes and medially \
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rotates lower leg
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Muscle w/ function flexes, weakly abducts, rotates upper leg; flexes and medially \
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rotates lower leg	Sartorius
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Origin of Sartorius	Just below tip of ASIS
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Muscle with origin &amp;#39;Just below tip of ASIS&amp;#39;	Sartorius
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Insertion of Sartorius	Pes anserinus, on tibia
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Muscle with insertion &amp;#39;Pes anserinus, on tibia&amp;#39;	Sartorius
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Sartorius overlaps...	Gracilis, Rectus Femoris, Vastus Medialis, Adductor Longus
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Gracilis, Rectus Femoris, Vastus Medialis, Adductor Longus are overlapped by...	Sartorius
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Function of Deltoid	flex arm forward, abducts outward, pulls backward
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Muscle w/ function flex arm forward, abducts outward, pulls backward	Deltoid
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Origin of Deltoid	lateral 1/3 of clavicle, acromion process, spine of scapula
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
… and a sample flash card (top portion only is shown initially, with the
answer below shown after a tap or keypress):&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/anki-example.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/anki-example_hu_9da427f3d62a872e.png&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Example Anki flash card
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-2&#34;&gt;
Workflow
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-3&#34;&gt;
&lt;ol&gt;
&lt;li&gt;Clone &lt;a href=&#34;https://github.com/eigenhombre/anatomy/blob/master/src/anatomy/core.clj&#34;&gt;the GitHub repository&lt;/a&gt; and &lt;code class=&#34;verbatim&#34;&gt;cd&lt;/code&gt; to the new directory;&lt;/li&gt;
&lt;li&gt;Edit &lt;code class=&#34;verbatim&#34;&gt;resources/muscle-structure.org&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Export Org file to CSV (&lt;code class=&#34;verbatim&#34;&gt;org-table-export&lt;/code&gt;) in the same directory;&lt;/li&gt;
&lt;li&gt;Run the program and save the output: &lt;code class=&#34;verbatim&#34;&gt;lein run &amp;gt; cards.txt&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Import &lt;code class=&#34;verbatim&#34;&gt;cards.txt&lt;/code&gt; (removing any previously-imported entries first) into Anki;&lt;/li&gt;
&lt;li&gt;Memorize away!&lt;/li&gt;
&lt;li&gt;Repeat as new muscles are added.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-3&#34;&gt;
Conclusion
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
After a few weeks of minimal effort (a lot less than &lt;a href=&#34;./daily-composition-lessons-learned.html&#34;&gt;my previous
year-long project&lt;/a&gt;), I&amp;#39;ve added half a dozen or so muscles so far and
have them pretty well down.  Since the overlapping forms are included,
one starts to flesh out one&amp;#39;s three-dimensional understanding of the
figure from the outset.  (I recommend starting with the largest
muscles first if you&amp;#39;re not as familiar with them – e.g. pectoralis,
gluteus maximum, rectus abdominis, etc.). This method is a bit
personal, Emacs, Org Mode, Clojure, etc. not being standard artists&amp;#39;
tools, but could be adapted to e.g. Excel or CSV files, or other
programming languages, with minimal effort.&lt;/p&gt;
&lt;p&gt;
[1] See, for example, &lt;em&gt;Human Anatomy for Artists: The Elements of Form&lt;/em&gt; by Elliot Goldfinger.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Bio</title>
      <link>http://johnj.com/bio/</link>
      <pubDate>Fri, 24 Nov 2017 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/bio/</guid>
      <description>&lt;p&gt;
I grew up&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-1&#34; href=&#34;#footnote-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;[some old pictures of me]]] in
Madison, Wisconsin and studied art and physics at the University of
Wisconsin — Madison, receiving my doctorate in physics there in 1996
under &lt;a href=&#34;https://wipac.wisc.edu/people/faculty/francis-halzen&#34;&gt;Prof. Francis Halzen&lt;/a&gt;.  I also worked for a year at CERN in
Geneva, Switzerland, under &lt;a href=&#34;https://en.wikipedia.org/wiki/Sau_Lan_Wu&#34;&gt;Prof. Sau Lan Wu&lt;/a&gt; on the &lt;a href=&#34;https://en.wikipedia.org/wiki/ALEPH_experiment&#34;&gt;ALEPH&lt;/a&gt; experiment.&lt;/p&gt;
&lt;p&gt;
My doctoral work and postdoc focused on &lt;a href=&#34;https://en.wikipedia.org/wiki/Antarctic_Muon_And_Neutrino_Detector_Array&#34;&gt;the AMANDA neutrino detector&lt;/a&gt;
constructed at the Geographic South Pole, and the subsequent, much
larger &lt;a href=&#34;https://en.wikipedia.org/wiki/IceCube_Neutrino_Observatory&#34;&gt;IceCube Neutrino Observatory&lt;/a&gt;.  My physics career is described
in more depth in &lt;a href=&#34;./vita.html&#34;&gt;my Curriculum Vitae&lt;/a&gt;; the IceCube project is described
quite engagingly and at length by &lt;a href=&#34;https://en.wikipedia.org/wiki/Mark_Bowen_(writer)&#34;&gt;Mark Bowen&lt;/a&gt; in his book, &lt;a href=&#34;https://www.amazon.com/Telescope-Ice-Inventing-Astronomy-South/dp/1137280085&#34;&gt;The
Telescope in the Ice: Inventing a New Astronomy at the South Pole&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
While in graduate school I also studied painting, drawing and
printmaking in the UW-Madison graduate art program, mostly with &lt;a href=&#34;https://www.juxtapoz.com/news/printmaking-and-beyond-with-jack-damer/&#34;&gt;Jack
Damer&lt;/a&gt;, Richard Long and &lt;a href=&#34;https://www.youtube.com/watch?v=-EXq1dEUP4s&#34;&gt;David H. Becker&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
In the 21st century I have been a &lt;a href=&#34;./tech.html&#34;&gt;software engineer&lt;/a&gt; and painter. I
travelled to the Geographic South Pole ten times for AMANDA and
IceCube, going at first as a physicist, and then as a software
consultant (&lt;a href=&#34;./southpole-blog.html&#34;&gt;blog posts here&lt;/a&gt;).  Some of my early paintings were
described in William Fox&amp;#39;s book, &lt;a href=&#34;https://www.amazon.com/Terra-Antarctica-Looking-Emptiest-Continent/dp/1593761481&#34;&gt;Terra Antarctica: Looking Into the
Emptiest Continent&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Since 2015 I have maintained a regular studio practice focusing on
figurative art based on observation and imagination.  This effort has
involved some re-training, mostly in the form of workshops at the
Palette and Chisel Academy of Fine Art with &lt;a href=&#34;http://cargocollective.com/andrewsconklin&#34;&gt;Andrew S. Conklin&lt;/a&gt;, &lt;a href=&#34;http://steven-assael-mr8x.squarespace.com/work&#34;&gt;Stephen
Assael&lt;/a&gt;, and Larry Paulsen.  My exhibition history is &lt;a href=&#34;./exhibitions.html&#34;&gt;here&lt;/a&gt;, while
recent work and work in progress are shown on &lt;a href=&#34;https://www.instagram.com/eigenhombre/&#34;&gt;my Instagram&lt;/a&gt; and &lt;a href=&#34;https://toomanysketchbooks.tumblr.com/&#34;&gt;Tumblr&lt;/a&gt;
feeds.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr class=&#34;footnotes-separatator&#34;&gt;
&lt;div class=&#34;footnote-definitions&#34;&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-1&#34;&gt;&lt;a href=&#34;#footnote-reference-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;Just for fun, here are [[./more-pix-of-me.html&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Reflections on a Year of Daily Memory Drawings</title>
      <link>http://johnj.com/posts/daily-composition-lessons-learned/</link>
      <pubDate>Mon, 18 Sep 2017 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/daily-composition-lessons-learned/</guid>
      <description>
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
365 Drawings
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
The sketchbooks shown below are the result of doing one drawing from
memory every day for a year, a project I finished this month.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2934.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2934_hu_d7079272117865da.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
A year&amp;#39;s worth of Daily Compositions
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
This drawing practice was based on the Daily Composition, which, as I
&lt;a href=&#34;./daily-memory-drawing.html&#34;&gt;explained&lt;/a&gt; last January, is an exercise from &lt;em&gt;The Natural Way to Draw&lt;/em&gt;,
by &lt;a href=&#34;https://en.wikipedia.org/wiki/Kimon_Nicola%25C3%25AFdes&#34;&gt;Kimon Nicolaïdes&lt;/a&gt; (published posthumously in 1941).  The
requirements for this exercise are as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;em&gt;See&lt;/em&gt; things and events that interest you throughout the day;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Remember&lt;/em&gt; them, and&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Capture&lt;/em&gt; them on paper, in the form of a single image …&lt;/li&gt;
&lt;li&gt;… &lt;em&gt;Once per day&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Each of these is challenging in its own way, and each reinforces the
other.  Maintaining the practice over a full year taught me a number
of lessons.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0014-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0014-online_hu_e72bc2f803ffd4bb.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Example drawing: 54th and Cornell
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-2&#34;&gt;
Lesson 1: The limits of visual memory
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
I’d struggled with this exercise now and again over the years, and in
taking it up again I was immediately reminded just how little I
remember of what I see throughout the day.&lt;/p&gt;
&lt;p&gt;
The mind is able to recognize, and, to a greater or lesser extent, to
respond mentally and emotionally to a stunning variety of objects and
occurrences in the world around us. This happens automatically and
without effort. But this sort of ordinary seeing is not the same as
being able to &lt;em&gt;recall&lt;/em&gt; and to visually &lt;em&gt;reproduce&lt;/em&gt; the things we
&amp;#34;see.&amp;#34;&lt;/p&gt;
&lt;p&gt;
To demonstrate this to yourself, try to draw your spouse&amp;#39;s face, or a
friend&amp;#39;s, from memory. This is a person you would have no trouble
recognizing, even at some distance, yet you don&amp;#39;t really have access
to how your brain stores that information. Now try to draw your car,
or bicycle, or the front of your building. These are things you know
well, yet you probably cannot describe them visually in much detail.&lt;/p&gt;
&lt;p&gt;
Doing this exercise faithfully made this fact painfully obvious.  Each
day, out of the millions of details that passed in front of my eyes, I
was left grasping only a handful of facts to work with at day&amp;#39;s end.
(The number of memories was small, but I was surprised that it was
never zero.)&lt;/p&gt;
&lt;p&gt;
Contrast this with the capabilities of a camera: it faithfully records
the details it is exposed to, millions of bits of data per shot. But
the camera, a mere machine, cannot recognize or react emotionally to
those details&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-1&#34; href=&#34;#footnote-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0004-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0004-online_hu_7013ec1e85de63d6.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Adams St. Bridge
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-3&#34;&gt;
Lesson 2: Trying to remember amplifies seeing
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
It would be easy to think of the Daily Composition exercise as a way
of learning how to do a camera&amp;#39;s job: you are exposed to scenes, and
later you record them on paper.  I did find myself, in fact, taking
mental &amp;#34;pictures&amp;#34; most days, of a person or group doing something, in
some specific place.  I would see a person getting into a cab, or
construction workers huddled over a hole, or (one day) a unicycle
rider cresting a small hill, and I would think, &amp;#34;that&amp;#39;s it!&amp;#34; and try
to remember, for that evening&amp;#39;s drawing, everything I could about the
moment I&amp;#39;d just seen.&lt;/p&gt;
&lt;p&gt;
During the course of the year, I didn&amp;#39;t actually get that much better
in terms of the sheer number of details I could recall.  A half dozen
&amp;#34;facts&amp;#34; (the size and shape of a doorway; the size and number of
windows in a storefront; the particular shape of a woman&amp;#39;s boots),
along with a rough gesture for and/or placement of the key figures,
were about as I could expect for any given day&amp;#39;s drawing.&lt;/p&gt;
&lt;p&gt;
A much bigger change occurred in my ability to &lt;em&gt;notice&lt;/em&gt; things, and my
emotional response to them was amplified. Knowing that I needed
material for a drawing at the end of the day simply opened my eyes
more. It was like going on vacation somewhere totally new. I saw
things in my neighborhood, and on my commute, that I had passed by
without noticing for years: the shapes and placement of signs, light
poles, fire hydrants; the construction and weathering of steel
supports for elevated trains; the multitudes of ornamental details on
buildings. The endless variety of people&amp;#39;s faces… commuters,
shopkeepers, construction workers, homeless men and women; the smiles,
grim stares (especially at commute times) or lines of care they bore;
their postures and gestures (all too often, in relationship to their
phones); the cut and fit of their clothing, coats, boots or shoes.
The endless repetitive movements of pigeons, and the surprising
variety of other birds (sparrows, hawks, cranes, herons, geese, ducks,
swallows, and several migratory bird species I couldn&amp;#39;t identify).
The printed word, in steel or brass relief, to be seen everywhere in
streets and sidewalks, indicating lines of survey, or the origin or
builders of utility covers or nearby buildings. All the endless
varieties of trees, contours of trunks, branching patterns, leaves,
and all the grasses, flowers and weeds of the city… these things
came to my notice, were revealed fresh as though I had previously had
some sort of screen over my vision that had fallen away.&lt;/p&gt;
&lt;p&gt;
Part of &lt;em&gt;seeing&lt;/em&gt; these things became &lt;em&gt;caring&lt;/em&gt; about them.  In that regard I
became less, not more, like a camera.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0015-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0015-online_hu_a086311c63874f96.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Promontory Point
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-4&#34;&gt;
Lesson 3: Emotion aids recall
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
If I saw something I reacted to emotionally, it was usually a lot
easier to recall later. This seems obvious, but to live the connection
between emotion and memory as part of one&amp;#39;s daily routine for a year
had a cumulative effect.  This is what I meant when I said in my &lt;a href=&#34;./daily-memory-drawing.html&#34;&gt;last
post&lt;/a&gt; that I felt a stronger connection to Chicago and my surroundings.
I suspect that building these sorts of connections to daily life is
one of the main reason Nicolaïdes recommends the exercise as a daily
practice.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0020-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0020-online_hu_eadcd6ef322bd9c1.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
South Loop Mural and Smoker
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-5&#34;&gt;
Lesson 4: Other tricks for remembering
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Aside from focusing on things that give an emotional charge, here are
some more tricks I used to remember things I saw:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Practice drawing or painting something while you look at it.&lt;/strong&gt; This
includes making movements in the air as if you were drawing,
building a little actual muscle memory (and inviting curious
glances from passersby).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Re-remember things&lt;/strong&gt;. If I saw something I wanted to &amp;#34;save up&amp;#34; for
the evening&amp;#39;s drawing, then whenever I saw something &lt;em&gt;else&lt;/em&gt; that
looked interesting, I would look carefully at it, but then I would
use the whole noticing-something-noteworthy experience as a
reminder to remember the &lt;em&gt;other&lt;/em&gt; thing I was trying to remember
also.  In other words, every new thing I noticed became a reminder
to remember the other thing.  Occasionally, I would build a list of
things to remember and would then go through the list items
one-by-one whenever this occurred.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;De-distract and focus.&lt;/strong&gt; Of course, sometimes the above tricks got
to be too much; at those times, I&amp;#39;d try to minimize my visual input
by looking down at the sidewalk if safe to do so (allowing my
peripheral vision or looking up when needed, in order to keep from
getting hit by buses, etc.), just making the effort to hold the
memories in my mind while I walked or ran.&lt;/li&gt;
&lt;/ol&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0030-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0030-online_hu_f4e978740993e80.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Weed whacking on the Lakefront
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-6&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-6&#34;&gt;
Lesson 5: Invention and knowledge help fill in details
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-6&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Given a relative paucity of remembered facts, how do you complete your
drawing? Just as our mind fills in details about what we see without
our being consciously aware of it, one can invent the elements of a
scene that elude our grasp when we try to recall them.  For this, a
knowledge of perspective, of human anatomy and clothing, of the
construction of builings and plants and trees, and especially of light
and shadow are indispensible for adding extra life and believability to
a composition, no matter how quickly executed.  For example, I would
rarely remember a &lt;em&gt;specific&lt;/em&gt; shadow, but if I knew where I was and
what time it was, I could place the shadows based on where the sun
would have been at the time. Used skillfully, invention can also &lt;em&gt;amplify&lt;/em&gt;
whatever emotional response led one to record the scene in one&amp;#39;s mind
to begin with.&lt;/p&gt;
&lt;p&gt;
I think I got slightly better at &amp;#34;filling in the gaps&amp;#34; this way over
the year.  The exercise does seem to strengthen the connection
between memory, knowledge, and imagination.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0032-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0032-online_hu_96a505f7e1a7873.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Dearborn subway entrance
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-7&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-7&#34;&gt;
Lesson 6: Drawing can distort memory; revisiting a place helps
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-7&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
I often noticed that, after drawing something that occurred in a
specific place, my memory would be strongly affected by whatever
inventions (or mistakes) I came up with to compensate for my ignorance
of the drawing&amp;#39;s setting.  For this reason, I sometimes disliked
looking at the drawings after the fact because they were so clearly
wrong and they interfered with my &amp;#34;real&amp;#34; memory of where the event
occurred.  An easy remedy for this was just to go back to the place in
question and look around. One sees many more details the second time
around, and it&amp;#39;s always amusing and humbling to realize how wrong you
got it the first time.&lt;/p&gt;
&lt;p&gt;
On a related note, I find that taking and reviewing photographs
shapes my memory as well. I remember things differently, and more
emotionally, having drawn them, either from life or from memory, than
I do when I&amp;#39;ve photographed them.  I sometimes limit my photography
when I travel for this reason (although I still take a ton of
pictures).&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0006-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0006-online_hu_5d22614547dbcf83.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
North Avenue Apple Store
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-8&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-8&#34;&gt;
Lesson 7: Don&amp;#39;t make it a big deal
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-8&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
To do the exercise three hundred and sixty five days in a row did
require commitment, since I have a busy schedule and was generally
doing it at the end of the day when my &lt;a href=&#34;http://www.webmd.com/diet/features/willpower-facts#1&#34;&gt;willpower budget&lt;/a&gt; and my ability
to focus were all but spent.&lt;/p&gt;
&lt;p&gt;
Nicolaïdes makes a point of not making a big deal of these drawings,
setting a fifteen minute time limit for each.  I broke this rule many
times, especially at the beginning when I would try to recall as much
as possible.  Eventually, however, I settled for just jotting down a
few things I remembered seeing (sometimes starting with just
remembering where I was and what I did, which could be hard enough),
and turning the most compelling memory into a small composition.  Even
on days when I was the most busy and distracted I could typically
remember at least one thing to put down on paper.  And I found there
was only a loose correlation between how much effort I put into
remembering things throughout any given day, and how much I liked the
drawing at the end of that day.  Some days I was excited about the
results, and some days I was just happy to put the drawing away
afterward.  Part of what&amp;#39;s good about doing something like this is you
can fail over and over again, and your daily commitment to the
practice means that any specific failure is no big deal.&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-2&#34; href=&#34;#footnote-2&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0027-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0027-online_hu_e88cb84ccf7e83e9.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Cyclists kissing at The Point
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-9&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-9&#34;&gt;
Lesson 8: More can be better
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-9&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
At least half the drawings are so bad, I find them pretty painful to
look at now.  Many of them show an interesting tidbit or idea worth
developing further.  And a small fraction, less than 10%, I enjoy
looking at and find appealing on their own terms. Some of these are
shown here.&lt;/p&gt;
&lt;p&gt;
The few successes illustrate an important rule that I still struggle
with: with art making, sometimes quantity wins.  I prefer to work for
a long time on paintings, but it is nice to complete something every
day and, occasionally, to have it succeed.  No matter who you are, I
suspect if you make a drawing a day for a whole year, at least a few
of them will suprise and please you.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0017-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0017-online_hu_6a67fe54854d52ad.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Randolph and Wabash
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-10&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-10&#34;&gt;
Lesson 9: It&amp;#39;s about composition
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-10&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Composition is about choosing what goes in a picture and arranging
those things in a pleasing design which communicates one&amp;#39;s ideas or
intentions.  One reason I took up this practice is that I find
inventing compositions (e.g., in the studio) more challenging than
finding them directly in front of me.  Ultimately, memory and
rendering are only part of the practice… the rest (perhaps the
biggest part) is design. Nearly four hundred drawings later I still
find it challenging, but solving a specific design problem every night
has made the whole problem of composition seem tractable in a way it
didn&amp;#39;t before.  This, I imagine, was another reason Nicolaïdes
emphasized this exercise.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0008-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0008-online_hu_d2cd5cc5683976fe.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Planting Bulbs
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-11&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-11&#34;&gt;
Moving forward
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-11&#34; class=&#34;outline-text-2&#34;&gt;
&lt;blockquote&gt;
&lt;p&gt;It will be helpful if you keep this up for a year, and it will be
twice as helpful if you keep it up for two years. The really serious
student will make a quick composition every day for the rest of his
life despite everything else he has to do. –Nicolaïdes&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
In later chapters of &lt;em&gt;The Natural Way to Draw&lt;/em&gt;, variations on the
Daily Composition are introduced, including a greater amount of
invention, and revisiting the same scene over several days in an
extended composition.  For myself, I wanted the challenge of working
primarily from memory for a year, but have increasingly been craving
more time for both invention and for working from life. I intend to
continue regular compositional practice, but more as a natural and
playful part of my creative rhythm, rather than as a tightly-defined
daily practice.  I don&amp;#39;t know where it will lead, but look forward to
finding out.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-12&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-12&#34;&gt;
More Drawings
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-12&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Here are a few more drawings from the year.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0018-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0018-online_hu_5c4add0eef962d8f.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Shambhala Center
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0002-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0002-online_hu_f85477a99ad051fd.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
54th and Cornell
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0011-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0011-online_hu_8ed9fd9e57d36147.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Van Buren
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0031-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0031-online_hu_ffd710c0494b12f7.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Truck, alley off Van Buren
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0022-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0022-online_hu_d79eb53bf5edcee0.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
March for Science, Columbus Drive
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0023-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0023-online_hu_bc084553557c5484.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Hipster cyclist crossing Metra tracks
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0025-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0025-online_hu_e2afde0e47eca187.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Stephen Assael class demo
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0034-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0034-online_hu_a827cc3d1d789f2.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Printers&amp;#39; Row Book Fair
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0012-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0012-online_hu_eb9ccacbc943203d.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
55th St.
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0013-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0013-online_hu_d8b7230ab2f8673a.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Cement mixer, Lake Shore Drive under McCormick Place
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0016-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0016-online_hu_c441dacfdf1c5834.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
63rd St. Beach
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20170917_0033-online.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20170917_0033-online_hu_e20285879b56f3c9.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Checking phone, near Oak St.
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr class=&#34;footnotes-separatator&#34;&gt;
&lt;div class=&#34;footnote-definitions&#34;&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-1&#34;&gt;&lt;a href=&#34;#footnote-reference-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;Some machine learning systems have gotten pretty good at recognizing specific objects in a digital image; thankfully, none of these has emotions yet.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-2&#34;&gt;&lt;a href=&#34;#footnote-reference-2&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;The ability to fail and to start anew, over and over again, is the most important creative skill that I know of.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Repainting</title>
      <link>http://johnj.com/posts/repainting/</link>
      <pubDate>Sun, 14 May 2017 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/repainting/</guid>
      <description>&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_6813.JPG&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_6813_hu_17460ef1ae2e9787.JPG&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Painting in Progress - from imagination
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
As I return to the painting on my easel, reworking both the major
figures and probably everything else as well, I am put to mind of a
lesson by a former teacher, &lt;a href=&#34;http://www.carolpylant.com/HOME.html&#34;&gt;Carol Pylant&lt;/a&gt;.  She told me to be paint
over the edges of my foreground figures when working on backgrounds,
so the backgrounds don’t get too “stiff.” Of course, this applies not
just to edges.  “If you painted it once, you can paint it again,” she
said.&lt;/p&gt;
&lt;p&gt;
There are some variants to this last phrase which come to mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you painted it once, and are afraid you won’t be able to paint it
as well or better, you probably need more practice.&lt;/li&gt;
&lt;li&gt;If you painted it once, and had fun doing so, you can have fun doing
it again.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think a major source of strength in a drawing or a painting (or a
computer program, for that matter) is the ability of letting go of
work completed so that better work can emerge.&lt;/p&gt;
&lt;p&gt;
This was vividly reinforced for me when I watched &lt;a href=&#34;http://steven-assael-mr8x.squarespace.com/work&#34;&gt;Steven Assael&lt;/a&gt; paint
for two days in February.  He built up beautiful passages again and
again and destroyed them… mostly.  Traces remained, in the layers of
marks and paint and texture.  Same thing, last month, watching him
draw the figure, and encouraging students to make radical changes even
in the last few minutes of a pose… destroying what was there to open
a path for something much better to emerge.  As time goes on I can see
that opening that path over and over again is absolutely critical for
successful work. Destruction is often a prerequisite for successful
creation.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Daily Memory Drawings</title>
      <link>http://johnj.com/posts/daily-memory-drawing/</link>
      <pubDate>Tue, 03 Jan 2017 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/daily-memory-drawing/</guid>
      <description>&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/dc-12-20-2016-wide.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/dc-12-20-2016-wide_hu_c28d731e7f694d0.png&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Riverside Plaza Memory Sketch
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Every day for the past three months I have drawn some
scene or event that I saw that day, purely from memory.&lt;/p&gt;
&lt;p&gt;
Usually this is something I saw on the way to work, or, if I&amp;#39;m home
that day, something I saw when out for a run or a walk somewhere in
the neighborhood.&lt;/p&gt;
&lt;p&gt;
Since I usually make the drawing at the end of the day, several hours
will have passed by the time I get around to recording what I saw. To
keep this purely about memory (with bits of invention as needed), I
don&amp;#39;t allow myself any notes or photo references.  As a result, while
going about my day, I need to work extra hard to have a chance to
remember the things I see. Sometimes I&amp;#39;ll stop on the street and spend
extra time looking at something, perhaps making little drawing
gestures in the air to build a little muscle memory about the shapes, and
no doubt drawing a stare or two from passersby. Other times if I&amp;#39;ve
seen something transitory while walking I&amp;#39;ll look down at the sidewalk
and go over the scene in my mind with minimal distraction from new
visual inputs.&lt;/p&gt;
&lt;p&gt;
Throughout the day, if I think of it, I&amp;#39;ll try to recall one or two
things I&amp;#39;ve seen to increase the chance of recall later.&lt;/p&gt;
&lt;p&gt;
When I sit down to draw, I first make a list of all the things I can
remember seeing, sometimes accompanied by small thumbnail
sketches.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20161224_0012_copy.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20161224_0012_copy_hu_782455d2b032b556.png&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Details remembered from Walk in Hyde Park
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Then I choose one thing as the subject of a larger, 15- to 20-minute drawing, usually 6&amp;#34;x8&amp;#34;.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/barber-9-26-2016sm.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/barber-9-26-2016sm_hu_16764434e5d42496.png&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Van Buren Barber Shop
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20161224_0013_copy.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20161224_0013_copy_hu_9b9c9f76eba2f33a.png&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
A Capella Band at Metra Entrance
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
While the drawings are usually not particularly good (and definitely
not &amp;#34;finished&amp;#34; by my usual standards), doing this exercise religiously
for awhile has had a few noticeable effects:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The exercise forces me to get out of the house at least once per
day, no matter my schedule or the weather.&lt;/li&gt;
&lt;li&gt;The drawings seem to be getting a little better, and a little more
complex, on average.&lt;/li&gt;
&lt;li&gt;I can remember more at the end of the day, often enough to fill two
pages of notes and drawings.&lt;/li&gt;
&lt;li&gt;Things I see throughout the day are more vivid and can pack more
emotional punch.  I feel a stronger connection to my surroundings,
the city of Chicago in particular.&lt;/li&gt;
&lt;li&gt;Imagining or inventing things, coming up with ideas for drawings or
compositions, seems easier.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I have been appreciating the last two items especially.&lt;/p&gt;
&lt;p&gt;
I don&amp;#39;t have a great memory, so this exercise sometimes feels
impossible, and involves a fair amount of staring off into space.
Like writing down dreams, however, once I get going, I tend to
remember more than I thought I would.&lt;/p&gt;
&lt;p&gt;
This activity is, with a minor variation or two, the &amp;#34;Daily
Composition&amp;#34; exercise proposed by Kimon Nicolaïdes in &lt;em&gt;The Natural Way
to Draw&lt;/em&gt;.  Without giving much explanation, he asserts,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;No other exercise in the book is more important than this one. These
compositions do not have to be right. They can be &lt;em&gt;all wrong&lt;/em&gt;. The
important thing is to do them — three hundred and sixty-five of them
between today and this date next year. It will be helpful if you keep
this up for a year, and it will be twice as helpful if you keep it up
for two years. The really serious student will make a quick
composition every day for the rest of his life despite everything else
he has to do.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
I first read about this exercise in the 1980s. How I wish I had
followed that advice consistently since then! Nevertheless, when I go
back and look at old sketchbooks and discover my occasional Daily
Compositions, no matter how bad the drawings, I do feel the strings of
memory vibrating strongly.&lt;/p&gt;
&lt;p&gt;
I think this exercise is hard to do consistently because, at first,
there isn&amp;#39;t much to work with… nothing to &lt;em&gt;copy from&lt;/em&gt;.  A newcomer
to the exercise will struggle when all he or she has to work with is a
few wispy clouds of memory and spotty knowledge of lighting, anatomy,
weather, architecture, costume, etc. But working on one&amp;#39;s weak spots
is a great way to improve.  In particular, when I go back to a spot
I&amp;#39;ve tried to draw, I notice many things I missed the first time. It&amp;#39;s
fun to re-draw those things, armed with the extra knowledge.&lt;/p&gt;
&lt;p&gt;
It&amp;#39;s also nice to have a fairly clear idea of &lt;em&gt;what to draw&lt;/em&gt; at least
once per day, without worrying about making it anything complicated or
clever. (Generally one of the day&amp;#39;s memories stands out clearly as the
best subject for a drawing.)&lt;/p&gt;
&lt;p&gt;
All art considerations aside, this exercises exposes the vast extent
of my ignorance of the simplest things I encounter every day. The
process of learning to notice my environment more feels like a healthy
(albeit upstream) direction to take in a world where constant
distraction by one&amp;#39;s smartphone has become the norm.&lt;/p&gt;
&lt;p&gt;
Since starting this exercise I&amp;#39;ve looked around for other references
to working from memory. It seems that the practice was more common in
the 19th Century.  Degas, in particular, and Whistler used memory
extensively in their work. More on this, perhaps, in later posts. In
any case, it seems to me that the practice is not given its due in
contemporary teaching and discourse (I don&amp;#39;t remember any discussion
of it in art school).&lt;/p&gt;
&lt;p&gt;
What things that you see every day are worthy of your repeated
attention and study… or even memorization?&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20161224_0008_copy.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20161224_0008_copy_hu_351571036dadd194.png&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Van Buren Memory Sketch
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Questions to Ask</title>
      <link>http://johnj.com/posts/questions-to-ask/</link>
      <pubDate>Thu, 25 Feb 2016 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/questions-to-ask/</guid>
      <description>
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Questions to Ask
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;&lt;em&gt;… of a painting in progress, with strategies for recovery.&lt;/em&gt;&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/pole-plein-air.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/pole-plein-air_hu_23b52070db133117.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Diagrammatic landscape sketch made &amp;#34;en plein air&amp;#34; at the Geographic South Pole
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
I’ve been learning a lot lately by studying books, blogs, and doing
studies from life. It’s made me reflect upon my past strategies (or
lack thereof) for making artworks.&lt;/p&gt;
&lt;p&gt;
These are roughly in order of importance, in that if the answer to a
previous question is, “no,” it’s probably not worth spending too much
time on the current question.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Is the concept, content or intent clear in your mind, and is it what you want?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
If not, go back to the drawing board:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;make studies from life;&lt;/li&gt;
&lt;li&gt;generate ideas in sketchbooks;&lt;/li&gt;
&lt;li&gt;look to other artists’ work for inspiration;&lt;/li&gt;
&lt;li&gt;look to previous successes and failures to see what the next step
is.&lt;/li&gt;
&lt;li&gt;Consider destruction, deferral, or radical transformation of the
current piece.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Does the overall design make sense?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Large Shapes and Edges&lt;/li&gt;
&lt;li&gt;Composition&lt;/li&gt;
&lt;li&gt;Perspective&lt;/li&gt;
&lt;li&gt;Arrangement of objects in the illusionistic space of the piece&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If not, fix at the level of drawing (shapes/outlines/values).  Also
ask, Is there anything that could be removed to make the work
stronger?&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Do the values communicate the right forms well?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
If not, fix at the level of drawing (values). Check:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Light sources and the nature of any reflections (specular vs. diffuse)&lt;/li&gt;
&lt;li&gt;Accuracy / illusion of form&lt;/li&gt;
&lt;li&gt;Level of detail&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Do the colors work in harmony with each other and with the other concerns in the painting?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
If not, repaint one or more areas, maintaining value but shifting hue.&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Do the marks and surface quality relate to the intent/energy/mood?  Are they interesting?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
No matter how “objective” the intent, at some level all paintings and
drawings are abstract. They should be beautiful at any distance or
level of “magnification.”&lt;/p&gt;
&lt;p&gt;
If not, re-work those areas, using strategies of sanding, scraping,
erasure, or starting over.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Macro-writing Macros</title>
      <link>http://johnj.com/posts/macro-writing-macros/</link>
      <pubDate>Wed, 25 Nov 2015 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/macro-writing-macros/</guid>
      <description>&lt;p&gt;
&lt;em&gt;… in which we explore the power of macros, and macro-writing
macros, to DRY out repetitive code.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/macro-sketch.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/macro-sketch_hu_40622335ed8bd4db.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
I’ve been writing Clojure code full time for nearly two years now. I
have a pretty good feel for the language, its virtues and its
faults. Mostly, I appreciate its virtues (though I still wish the REPL
started faster).&lt;/p&gt;
&lt;p&gt;
For me one of the language’s attractions has always been that it’s a
Lisp — a “homoiconic” language, i.e., one defined in terms of its own
data structures. Homoiconicity has one primary virtue, which is that
it makes metaprogramming more powerful and straightforward than it is
in non-homoiconic languages (arguably at some cost to readability).&lt;/p&gt;
&lt;p&gt;
In Lisp, this metaprogramming is accomplished with &lt;em&gt;macros&lt;/em&gt;, which are
functions that transform your code during a separate stage of
compilation. In other words, you write little programs to change your
programs before they execute. In effect, you extend the compiler
itself.&lt;/p&gt;
&lt;p&gt;
I run a Clojure study group at work and find that it can be hard to
explain the utility (or appeal) of this to newcomers to Lisp. This is
partly because macros do things you can’t easily do in other
languages, and because the things you want to do tend to relate to
abstractions latent in a particular codebase.&lt;/p&gt;
&lt;p&gt;
While &lt;a href=&#34;https://github.com/eigenhombre/moarquil&#34;&gt;playing around with 3d rendering&lt;/a&gt; in &lt;a href=&#34;http://quil.info/&#34;&gt;Quil&lt;/a&gt;, I recently came across
a use case that reminded me of the following quote by Paul Graham:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The shape of a program should reflect only the problem it needs to
solve. Any other regularity in the code is a sign, to me at least,
that I’m using abstractions that aren’t powerful enough— often that
I’m generating by hand the expansions of some macro that I need to
write&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-1&#34; href=&#34;#footnote-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
In Quil, there are multiple situations in which one needs to create a
temporary context to carry out a series of operations, restoring the
original state afterwards:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Save current style with &lt;code class=&#34;verbatim&#34;&gt;push-style&lt;/code&gt;; change style and draw stuff;
restore previous style with &lt;code class=&#34;verbatim&#34;&gt;pop-style&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Start shape with &lt;code class=&#34;verbatim&#34;&gt;begin-shape&lt;/code&gt;; draw vertices; &lt;code class=&#34;verbatim&#34;&gt;end-shape&lt;/code&gt; to end.&lt;/li&gt;
&lt;li&gt;Save current position/rotation with &lt;code class=&#34;verbatim&#34;&gt;push-matrix&lt;/code&gt;; translate / rotate
and draw stuff; restore old position/rotation with &lt;code class=&#34;verbatim&#34;&gt;pop-matrix&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here’s an example:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(push-matrix)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(try
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (push-style)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (try
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (fill 255)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (no-stroke)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (translate [10 10 10])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (begin-shape)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (try
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (vertex x1 y1 0)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (vertex x2 y2 0)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (vertex x2 y2 h)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (vertex x1 y1 h)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (vertex x1 y1 0)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (finally
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        (end-shape)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (finally
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (pop-style)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (finally
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (pop-matrix)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The &lt;code class=&#34;verbatim&#34;&gt;(try ... (finally ...))&lt;/code&gt; constructions may not be strictly needed
for a Quil drawing, but it’s a good habit to guarantee that stateful
context changes are undone, even if problems occur.&lt;/p&gt;
&lt;p&gt;
In a complex Quil drawing the idioms for saving style, translation
state, and denoting shapes appear often enough that one hungers for a
more compact way of representing each. Here’s one way to do it:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defmacro with-style [&amp;amp; body]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  `(do
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (push-style)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (try
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ~@body
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (finally
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (pop-style)))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defmacro with-matrix [&amp;amp; body]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  `(do
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (push-matrix)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (try
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ~@body
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (finally
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (pop-matrix)))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defmacro with-shape [&amp;amp; body]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  `(do
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (begin-shape)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (try
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ~@body
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (finally
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (end-shape)))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The original code then becomes more compact and easier to read:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(with-matrix
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (with-style
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (fill 255)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (no-stroke)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (translate [10 10 10])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (with-shape
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (vertex x1 y1 0)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (vertex x2 y2 0)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (vertex x2 y2 h)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (vertex x1 y1 h)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (vertex x1 y1 0))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
In &lt;a href=&#34;https://github.com/eigenhombre/moarquil/blob/master/src/moarquil/render.clj&#34;&gt;this example code&lt;/a&gt;, the contexts &lt;code class=&#34;verbatim&#34;&gt;with-matrix&lt;/code&gt;, etc. appear so often
that the resulting savings in lines of code and mental overhead for
the reader is substantial.&lt;/p&gt;
&lt;p&gt;
However, the astute reader will realize that the macro definitions
themselves are pretty repetitive—in fact, they look almost identical
except for the setup and teardown details (this kind of “context
manager” pattern is common enough that Python has &lt;code class=&#34;verbatim&#34;&gt;its own language
construct&lt;/code&gt; for it).&lt;/p&gt;
&lt;p&gt;
I generally reach for macros when I have a pattern that occurs with
obvious repetition that’s not easy to abstract out using just pure
functions. Control abstractions such as loops or exception handling
are common examples. (I find this situation occurs especially
frequently when writing test code).&lt;/p&gt;
&lt;p&gt;
In any case, the solution for our repetitive macros could be something
like:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defmacro defcontext
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  [nom setup teardown]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  `(defmacro ~(symbol (str “with-” nom))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     [~&amp;#39;&amp;amp; body#]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     `(do
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ~&amp;#39;~setup
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        (try
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          ~@body#
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          (finally
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            ~&amp;#39;~teardown)))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Yikes! I have to admit I had to write a lot of macros, and also refer
to &lt;a href=&#34;http://hubpages.com/technology/Clojure-macro-writing-macros&#34;&gt;this helpful page&lt;/a&gt; for reference, before I could write (and grok)
this macro.&lt;/p&gt;
&lt;p&gt;
With &lt;code class=&#34;verbatim&#34;&gt;defcontext&lt;/code&gt; in hand, our repetitive macro code just becomes:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defcontext style (push-style) (pop-style))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defcontext shape (begin-shape) (end-shape))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defcontext matrix (push-matrix) (pop-matrix))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
These are exactly equivalent to the three context macros &lt;code class=&#34;verbatim&#34;&gt;(with-*)&lt;/code&gt;
defined above.&lt;/p&gt;
&lt;p&gt;
With a little effort, it’s actually not too hard to construct such a
nested macro. It’s largely a matter of writing out the code you want
to generate, and then writing the code that generates it, testing with
&lt;code class=&#34;verbatim&#34;&gt;macroexpand-1&lt;/code&gt; at the REPL as you go. &lt;a href=&#34;http://hubpages.com/technology/Clojure-macro-writing-macros&#34;&gt;This page by A. Malloy&lt;/a&gt; has a lot
of helpful remarks, including this cautionary note: “Think twice
before trying to nest macros: it’s usually the wrong answer.” In this
case, I actually think it’s the right answer, because the pattern of a
context with setup and teardown is so common that I know I’ll reuse
this macro for many other things—we have effectively added one of my
favorite Python features to Clojure in just a few lines of code[fn::To
be even more like Python’s context managers, &lt;code class=&#34;verbatim&#34;&gt;defcontext&lt;/code&gt; would want
to enable the user to bind some local state resulting from the setup
phase of execution (“ &lt;code class=&#34;verbatim&#34;&gt;with x() as y:&lt;/code&gt; ” idiom); examples include file
descriptors or database connections. This is left as an exercise for
the reader.]&lt;/p&gt;
&lt;p&gt;
There’s a saying in the Clojure community: &lt;code class=&#34;verbatim&#34;&gt;data &amp;gt; functions &amp;gt; macros&lt;/code&gt;.
I’m a big believer in this. Clojure’s powerful built-in
abstractions for wrangling data in all its forms make it the language
I prefer above all others these days. But occasionally that means
wrangling the data that is the code itself, thereby reaping the
benefits in power, brevity and expressiveness.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/moarquil.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/moarquil_hu_4431473f278ad49.png&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Image generated by &lt;a href=&#34;https://github.com/eigenhombre/moarquil/blob/master/src/moarquil/util.clj#L5&#34;&gt;the Quil code&lt;/a&gt; used for this example.
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr class=&#34;footnotes-separatator&#34;&gt;
&lt;div class=&#34;footnote-definitions&#34;&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-1&#34;&gt;&lt;a href=&#34;#footnote-reference-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;Paul Graham, &amp;#34;Revenge of the Nerds&amp;#34;: &lt;a href=&#34;http://www.paulgraham.com/icad.html&#34;&gt;http://www.paulgraham.com/icad.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Time Limits</title>
      <link>http://johnj.com/posts/time-limits/</link>
      <pubDate>Sat, 25 Apr 2015 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/time-limits/</guid>
      <description>&lt;p&gt;
Picking up the art blogging again after a long hiatus.&lt;/p&gt;
&lt;p&gt;
Recently I’ve been thinking about constraints a lot, and finding out
how helpful they are. I think they are especially helpful for artists.&lt;/p&gt;
&lt;p&gt;
For example, since I started my new job last year, I am in the habit
of taking photos on the way to or from work. I use the following
constraints:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use only the iPhone with no extra lenses (digital
filters/manipulation OK, but only on the iPhone itself).&lt;/li&gt;
&lt;li&gt;Picture must be taken on the way to or from work, or near the office.&lt;/li&gt;
&lt;li&gt;Post the ones I like on Facebook, to &lt;a href=&#34;http://bit.ly/viewsfromthecommute&#34;&gt;this album&lt;/a&gt; (&amp;#34;Views from the Commute&amp;#34;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The pictures are not always awesome, but the practice itself is most
satisfying. It’s a way to stay creative and visually-focused despite
the demands of a “real” job. And I find the instant feedback I get
from friends and family on Facebook more satisfying than many a
gallery show has been.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/workingwounded.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/workingwounded_hu_4fcb0aa3c071c31c.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Image from &amp;#34;Views from the Commute&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Another way I’ve been exploring constraints in the last few years is
by &lt;a href=&#34;./plein-air.html&#34;&gt;painting outside&lt;/a&gt;. This practice has a number of constraints more or
less built in: you can’t carry too much stuff around; it’s only light
out for so long; and you typically paint the stuff you find in front
of you (rather than stuff you make up).&lt;/p&gt;
&lt;p&gt;
Lately I’ve been redoing my Web sites and thinking about some old art
projects as I sift through blog posts. I really enjoyed working with
SketchUp awhile back and have been itching to return to that. So I’ve
been wondering what sort of constraints might be helpful, similar to
the ones I get “for free” by painting outside.&lt;/p&gt;
&lt;p&gt;
I decided on the following formula:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Four hour limit per painting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hour one: make an image using SketchUp&lt;/li&gt;
&lt;li&gt;Hour two: transfer to panel and work on the drawing&lt;/li&gt;
&lt;li&gt;Third hour: underpainting&lt;/li&gt;
&lt;li&gt;Fourth hour: top layers / final painting.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Fifteen minute break in between hours&lt;/li&gt;
&lt;li&gt;Use &lt;a href=&#34;https://github.com/eigenhombre/ptg&#34;&gt;a Clojure program&lt;/a&gt; I wrote to help with the gridding of the drawing.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/holebubble-grid.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/holebubble-grid_hu_77be11eeae5da411.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
First stage, after one hour: exported from SketchUp and gridded
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_9543.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_9543_hu_c48b3c1edf3934b8.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
After second hour: drawing
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_9544.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_9544_hu_cc6aa5714c567387.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
After third hour: underpainting
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_9546v2.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_9546v2_hu_6a92297b7e7ffd17.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Final image
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_9549.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_9549_hu_53d23c36d51e7723.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Detail 1
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_9551.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_9551_hu_b0768c799b1020e7.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Detail 2
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Lessons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Constraints help. I ordinarily have trouble finishing
paintings. Though there were a few points when I thought things were
totally off the rails and the work was going to be a disaster,
overall I had a lot more focus (and fun!) than I often do while
painting.&lt;/li&gt;
&lt;li&gt;I originally planned hour three (underpainting) to be in acrylics;
but I found I wanted to just jump in with oils, and it worked fairly
well. Being flexible about the plan in this regard was good.&lt;/li&gt;
&lt;li&gt;Having painting supports ready in advance was helpful; NOT having a
concept or content queued up (for the SketchUp part) was also good,
I think, though I might experiment with brainstorming content as a
(timed) stage in the process.&lt;/li&gt;
&lt;li&gt;SketchUp is a total rabbit hole. I could have burned the entire time
just fooling around in SketchUp alone. Warning: dragons dwell there!&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Lazy Physics</title>
      <link>http://johnj.com/posts/lazy-physics/</link>
      <pubDate>Thu, 12 Feb 2015 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/lazy-physics/</guid>
      <description>&lt;p&gt;
&lt;em&gt;… in which we explore lazy sequences and common functional idioms in Clojure via the example of looking for (nearly) coincident clusters of times in a series.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
A fundamental technical problem in experimental particle physics is
how to distinguish the signatures of particles from instrumental
noise.&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/birds-on-wires.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/birds-on-wires_hu_16a165dde04a8c41.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Imagine a tree full of hundreds of sparrows, each nesting on a branch,
each chirping away occasionally. Suddenly, for a brief moment, they
all start chirping vigorously (maybe a hawk flew past). A clustering
of chirps in time is the signal that &lt;em&gt;something has happened!&lt;/em&gt; The
analogous situation occurs in instruments consisting of many similar
detector elements, each generating some amount of random noise that,
on its own, is indistinguishable from any evidence left by particles,
but which, taken together, signals that, again, &lt;em&gt;something has happened&lt;/em&gt;
—a muon, an electron, a neutrino has left a sudden spume of
electronic evidence in your instrument, waiting to be read out and
distinguished from the endless noise.&lt;/p&gt;
&lt;p&gt;
This process of separating the noise from the signal is known in
physics as &lt;em&gt;triggering&lt;/em&gt; and is typically done through some combination
of spatial or time clustering; in many cases, time is the simplest to
handle and the first “line of defense” against being overrun by too
much data. (It is often impractical to consume all the data generated
by all the elements —data reduction is the name of the game at most
stages of these experiments.)&lt;/p&gt;
&lt;p&gt;
This data is typically generated continously ad infinitum, and must
therefore be processed differently than, say, a single file on
disk. Such infinite sequences of data are an excellent fit for the
functional pattern known as &lt;em&gt;laziness&lt;/em&gt;, in which, rather than chewing up
all your RAM and/or hard disk space, data is consumed and transformed
only as needed / as available. This kind of processing is baked into
Clojure at many levels and throughout its library of core functions,
dozens of which can be combined (“composed”) to serve an endless
variety of data transformations. (This style of data wrangling is also
available in Python via generators and functional libraries such as
&lt;a href=&#34;http://toolz.readthedocs.org/&#34;&gt;Toolz&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;
Prompted by a recent question on the topic from a physicist and former
colleague, I got to thinking about the classic problem of triggering,
and realized that the time series trigger provides a nice showcase for
Clojure’s core library and for processing lazy sequences. The rest of
this post will describe a simple trigger, essentially what particle
astrophysicists I know call a “simple majority trigger”; or a “simple
multiplicity trigger” (depending on whom you talk to).&lt;/p&gt;
&lt;p&gt;
Now for some Clojure code. (A small amount of familiarity with
Clojure’s simple syntax is recommended for maximum understanding of
what follows.) We will build up our understanding through a series of
successively more complex code snippets. The exposition follows
closely what one might do in the Clojure REPL, building up
successively more complete examples. In each case, we use &lt;code class=&#34;verbatim&#34;&gt;take&lt;/code&gt; to
limit what would otherwise be infinite sequences of data (so that our
examples can terminate without keeping us waiting forever…).&lt;/p&gt;
&lt;p&gt;
First we create a sorted, infinite series of ever-increasing times
(in, say, nsec):&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(def times (iterate #(+ % (rand-int 1000)) 0))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; Caution: infinite sequence...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(take 30 times)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(0 955 1559 2063 2735 2858 3542 4067 4366 5246 5430 6168 7127 7932
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; 8268 8929 9426 9918 10436 10850 11680 12367 12569 13343 14155 14420
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; 15062 15171 15663 16355)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;code class=&#34;verbatim&#34;&gt;times&lt;/code&gt; is an infinite (but “unrealized”) series, constructed by
iterating the anonymous function &lt;code class=&#34;verbatim&#34;&gt;#(+ % (rand-int 1000))&lt;/code&gt; which adds a
random integer from 0 to 999 to its argument (starting with zero). The
fact that it is infinite does not prevent us from defining it or
(gingerly) interrogating it via take&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-1&#34; href=&#34;#footnote-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;
Now, the way we’ll look for excesses is to look for groupings of hits
(say, eight of them) whose first and last hit times are within 1
microsecond (1000 nsec) of each other. To start, there is a handy
function called &lt;code class=&#34;verbatim&#34;&gt;partition&lt;/code&gt; which groups a series in blocks of fixed
length:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(take 10 (partition 8 times))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;((0 955 1559 2063 2735 2858 3542 4067)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (4366 5246 5430 6168 7127 7932 8268 8929)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (9426 9918 10436 10850 11680 12367 12569 13343)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (14155 14420 15062 15171 15663 16355 16700 16947)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (17919 17949 18575 18607 18849 19597 20410 20680)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (20737 21289 21315 21323 21426 21637 22422 23000)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (23477 24351 24426 25106 25861 26568 27511 28332)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (29071 29831 29957 30761 31073 31914 32591 33187)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (33878 34739 34842 35674 36444 36960 36983 37400)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (37587 38012 38969 39131 39317 40135 40587 40759))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
We’ll rewrite this using Clojure’s thread-last macro &lt;code class=&#34;verbatim&#34;&gt;-&amp;gt;&amp;gt;&lt;/code&gt;, which is a
very helpful tool for rewriting nested expressions as a more readable
pipeline of successive function applications:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(-&amp;gt;&amp;gt; times
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (partition 8)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (take 10))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;((0 955 1559 2063 2735 2858 3542 4067)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (4366 5246 5430 6168 7127 7932 8268 8929)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; ...same as above...)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
However, this isn’t quite what we want, because it won’t find clusters
of times close together who don’t happen to begin on our &lt;code class=&#34;verbatim&#34;&gt;partition&lt;/code&gt;
boundaries. To fix this, we use the optional &lt;code class=&#34;verbatim&#34;&gt;step&lt;/code&gt; argument to
&lt;code class=&#34;verbatim&#34;&gt;partition&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(-&amp;gt;&amp;gt; times
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (partition 8 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (take 10))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;((0 955 1559 2063 2735 2858 3542 4067)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (955 1559 2063 2735 2858 3542 4067 4366)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (1559 2063 2735 2858 3542 4067 4366 5246)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (2063 2735 2858 3542 4067 4366 5246 5430)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (2735 2858 3542 4067 4366 5246 5430 6168)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (2858 3542 4067 4366 5246 5430 6168 7127)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (3542 4067 4366 5246 5430 6168 7127 7932)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (4067 4366 5246 5430 6168 7127 7932 8268)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (4366 5246 5430 6168 7127 7932 8268 8929)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (5246 5430 6168 7127 7932 8268 8929 9426))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This is getting closer to what we want—if you look carefully, you’ll
see that each row consists of the previous one shifted by one
element. The next step is to grab (via &lt;code class=&#34;verbatim&#34;&gt;map&lt;/code&gt;) the first and last times
of each group, using &lt;code class=&#34;verbatim&#34;&gt;juxt&lt;/code&gt; to apply both &lt;code class=&#34;verbatim&#34;&gt;first&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;last&lt;/code&gt; to each
subsequence….&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(-&amp;gt;&amp;gt; times
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (partition 8 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (map (juxt last first))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (take 10))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;([4067 0]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [4366 955]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [5246 1559]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [5430 2063]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [6168 2735]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [7127 2858]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [7932 3542]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [8268 4067]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [8929 4366]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [9426 5246])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
… and turn these into time differences:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(-&amp;gt;&amp;gt; times
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (partition 8 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (map (comp (partial apply -) (juxt last first)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (take 10))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(4067 3411 3687 3367 3433 4269 4390 4201 4563 4180)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Note that so far these time differences are all &amp;gt; 1000. &lt;code class=&#34;verbatim&#34;&gt;comp&lt;/code&gt;, above,
turns a collection of multiple functions into a new function which is
the composition of these functions, applied successively one after the
other (right-to-left). &lt;code class=&#34;verbatim&#34;&gt;partial&lt;/code&gt; turns a function of multiple arguments
into a function of fewer arguments, by binding one or more of the
arguments in a new function. For example,&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;((partial + 2) 3)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;5
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;((comp (partial apply -) (juxt last first)) [3 10])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;7&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Recall that we only want events whose times are close to each other;
say, whose duration is under a maximum limit of 1000 nsec. In general,
to select only the elements of a sequence which satisfy a filter
function, we use &lt;code class=&#34;verbatim&#34;&gt;filter&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(-&amp;gt;&amp;gt; times
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (partition 8 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (map (comp (partial apply -) (juxt last first)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (filter (partial &amp;gt; 1000))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (take 10))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(960 942 827 763 597 682 997 836 986 966)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
(&lt;code class=&#34;verbatim&#34;&gt;(partial &amp;gt; 1000)&lt;/code&gt; is a function of one argument which returns true if
that argument is strictly less than 1000.)&lt;/p&gt;
&lt;p&gt;
Great! We now have total “durations”; for subsequences of 8 times, where the total durations are less than 1000 nsec.&lt;/p&gt;
&lt;p&gt;
But this is not actually that helpful. It would be better if we could get both the total durations and the actual subsequences satisfying the requirement (the analog of this in a real physics experiment would be returning the actual hit data falling inside the trigger window).&lt;/p&gt;
&lt;p&gt;
To do this, &lt;code class=&#34;verbatim&#34;&gt;juxt&lt;/code&gt; once again comes to the rescue, by allowing us to
&lt;code class=&#34;verbatim&#34;&gt;juxt&lt;/code&gt;-apose the original data alongside the total duration to show both
together….&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(-&amp;gt;&amp;gt; times
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (partition 8 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (map (juxt identity (comp (partial apply -) (juxt last first))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (take 10))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;([(0 309 410 562 979 1423 2180 3159) 3159]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [(309 410 562 979 1423 2180 3159 3585) 3276]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [(410 562 979 1423 2180 3159 3585 4325) 3915]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [(562 979 1423 2180 3159 3585 4325 4573) 4011]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [(979 1423 2180 3159 3585 4325 4573 5074) 4095]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [(1423 2180 3159 3585 4325 4573 5074 5942) 4519]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [(2180 3159 3585 4325 4573 5074 5942 6599) 4419]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [(3159 3585 4325 4573 5074 5942 6599 7458) 4299]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [(3585 4325 4573 5074 5942 6599 7458 8128) 4543]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [(4325 4573 5074 5942 6599 7458 8128 8439) 4114])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
… and adapt our filter slightly to apply our filter only to the time
rather than the original data:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(-&amp;gt;&amp;gt; times
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (partition 8 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (map (juxt identity (comp (partial apply -) (juxt last first))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (filter (comp (partial &amp;gt; 1000) second))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (take 3))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;([(1577315 1577322 1577514 1577570 1577793 1577817 1577870 1578151)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  836]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [(3119967 3120203 3120416 3120469 3120471 3120620 3120715 3120937)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  970]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [(6752453 6752483 6752522 6752918 6752966 6753008 6753026 6753262)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  809])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Finally, to turn this into a function for later use, use &lt;code class=&#34;verbatim&#34;&gt;defn&lt;/code&gt; and
remove &lt;code class=&#34;verbatim&#34;&gt;take&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn smt-8 [times]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (-&amp;gt;&amp;gt; times
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (partition 8 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (map (juxt identity (comp (partial apply -) (juxt last first))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (filter (comp (partial &amp;gt; 1000) second))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;code class=&#34;verbatim&#34;&gt;smt-8&lt;/code&gt; consumes one, potentially infinite sequence and outputs another,
“smaller” (but also potentially infinite) lazy sequence of
time-clusters-plus-durations, in the form shown above.&lt;/p&gt;
&lt;p&gt;
Some contemplation will suggest many variants; for example, one in
which some number of hits outside the trigger “window” are also
included in the output. This is left as an exercise for the advanced
reader.&lt;/p&gt;
&lt;p&gt;
A “real” physics trigger would have to deal with many other details:
each hit, in addition to its time, would likely have an amplitude, a
sensor ID, and other data associated with it. Also, the data may not
be perfectly sorted, some sensors may drop out of the data stream,
etc. But in some sense this prototypical time clustering algorithm is
one of the fundamental building blocks of experimental high energy
physics and astrophysics and was used (in some variant) in every
experiment I worked on over a 25+ year period. The representation
above is certainly one of the most succinct, and shows off the power
and elegance of the language, its core library, and lazy
sequences. (It is also reasonably fast for such a simple algorithm;
&lt;code class=&#34;verbatim&#34;&gt;smt-8&lt;/code&gt; consumes input times at a rate of about 250 kHz. This is not,
however, fast enough for an instrument like IceCube, whose 5160
sensors each count at a rate of roughly 300 Hz, for a total rate of
1.5 MHz. A future post may look at ways to get better performance.)&lt;/p&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr class=&#34;footnotes-separatator&#34;&gt;
&lt;div class=&#34;footnote-definitions&#34;&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-1&#34;&gt;&lt;a href=&#34;#footnote-reference-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;To model a Poisson process — one in which any given event time is independent of the future or past times — one would normally choose an exponential rather than a uniformly flat distribution of time differences, but this is not important for our discussion, so, in the interest of simplicity, we’ll go with what we have here.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Fun with Instaparse</title>
      <link>http://johnj.com/posts/fun-with-instaparse/</link>
      <pubDate>Tue, 12 Nov 2013 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/fun-with-instaparse/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/instaparse-example.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/instaparse-example_hu_56a7c137cd68f43d.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
One of my favorite talks from this month’s excellent &lt;a href=&#34;http://clojure-conj.org/&#34;&gt;Clojure/conj&lt;/a&gt; was
&lt;a href=&#34;http://gigasquid.github.io/&#34;&gt;Carin Meier&lt;/a&gt;&amp;#39;s presentation, which combined storytelling, live coding,
philosophy, the history of computing, and flying robotic drones. She
used the relatively new &lt;a href=&#34;https://github.com/Engelberg/instaparse&#34;&gt;Instaparse library&lt;/a&gt; to create her own language
to explore something called “Speech Acts” (which I won’t go into here,
but do catch the video of her talk when it goes up).&lt;/p&gt;
&lt;p&gt;
My university work was in physics (and art) rather than CS, but I have
long been interested in the implementation of programming languages,
even going so far as to write a simple parser for Lisp-style math
expressions in Pascal many years ago. Last year I had the opportunity
to take the first “&lt;a href=&#34;http://dabeaz.blogspot.com/2012/01/compiler-experiment-begins.html&#34;&gt;write a compiler in Python&lt;/a&gt;” class offered by &lt;a href=&#34;http://dabeaz.com/&#34;&gt;David
Beazley&lt;/a&gt; here in Chicago, in which we implemented a subset of the Go
language. His &lt;a href=&#34;http://www.dabeaz.com/ply/index.html&#34;&gt;PLY library&lt;/a&gt; is a great way to get started with
implementing language parsers in Python, and the relative ease of
doing so, compared with classic C implementations described in the
infamous &lt;a href=&#34;https://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools&#34;&gt;Dragon Book&lt;/a&gt;, inspired me to do some further &lt;a href=&#34;https://github.com/eigenhombre/PyClojure&#34;&gt;experimentation
of my own&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
With this background, and inspired by Carin’s talk, I have been
waiting for an opportunity to try out Instaparse, which is getting
great press in the Clojure world. Instaparse takes a grammar as input
(in the form of a string), and gives you a parser in the language
specified by that grammar. It will also let you specify rules for
transforming the resulting tree into something your Clojure program
can use more directly (for example, by converting data types or
removing unneeded elements from the parse tree).&lt;/p&gt;
&lt;p&gt;
When the need arose this weekend to read in Python configuration files
into a Clojure program, I decided the time was ripe. I also wanted to
document the journey using some form of &lt;a href=&#34;http://en.wikipedia.org/wiki/Literate_programming&#34;&gt;literate programming&lt;/a&gt;. A
library called &lt;a href=&#34;https://github.com/gdeer81/marginalia&#34;&gt;Marginalia&lt;/a&gt; (Michael Fogus et. al.) made this pretty
easy.&lt;/p&gt;
&lt;p&gt;
The results are on &lt;a href=&#34;https://github.com/eigenhombre/parsepy&#34;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
My impressions, after doing this project in just a few hours, are that
(1) literate programming is great fun; and (2) Instaparse sets a new
standard for power and expressiveness when converting structured text
into abstract syntax trees. If you have a DSL or some other
text-based, formal language you want to parse, and you are either
literate in Clojure or interested in becoming so, Instaparse would be
a great tool to check out.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Nucleotide Repetition Lengths</title>
      <link>http://johnj.com/posts/nucleotide-repetition-lengths/</link>
      <pubDate>Sun, 03 Nov 2013 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/nucleotide-repetition-lengths/</guid>
      <description>
&lt;p&gt;
After a long hiatus, let’s continue &lt;a href=&#34;http://johnj.com/posts/exploratory-genomics-with-clojure&#34;&gt;our foray into amateur genomics
with Clojure&lt;/a&gt;, in which we continue to encounter elegant expressions of
Clojure’s power as well as a few additional wrinkles in the Clojure
ecosystem (in this case, Incanter).&lt;/p&gt;
&lt;p&gt;
In &lt;a href=&#34;http://johnj.com/posts/updating-the-genome-decoder-resulting-consequences&#34;&gt;our last post&lt;/a&gt; we upgraded our genome decoder and used it to show
frequencies of the four nucleotides, illustrating &lt;a href=&#34;http://en.wikipedia.org/wiki/Chargaff&amp;#39;s_rules&#34;&gt;Chargaff’s Rule&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Another simple question to be asked of the data is, What is the
distribution of nucleotide repetition lengths? In other words, if we
represent the number of times any nucleotide is repeated as a
histogram, then &lt;code class=&#34;verbatim&#34;&gt;AAGGCATTTT&lt;/code&gt; would yield two entries for 1, two entries
for 2, zero for 3, and one for 4. What does this distribution look
like for the entire human or yeast genome?&lt;/p&gt;
&lt;p&gt;
As a “null hypothesis”, consider the likelihood of getting $N$ A’s
when drawing at random from A, G, C or T. The probability for the
first selection to be A is 25%; for the first two draws to be AA the
probability is $P(AA) = {1 \over {4^2}} = 0.625$, and for $N$
consecutive draws, $P(A \times N) = 4^{-N}$.&lt;/p&gt;
&lt;p&gt;
You can easily simulate (“&lt;a href=&#34;http://en.wikipedia.org/wiki/Monte_Carlo_method&#34;&gt;Monto Carlo&lt;/a&gt;”) such a situation using a
purely random sequence:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn randgenome []
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (repeatedly #(rand-nth [:A :G :C :T])))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This function yields a sequence like &lt;code class=&#34;verbatim&#34;&gt;(:A :A :C :A :T :G :G :T :G :A :C :C ...)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
To convert this into repetition lengths, we can first divide the
sequence up into repeating elements using &lt;code class=&#34;verbatim&#34;&gt;partition-by&lt;/code&gt; and the
&lt;code class=&#34;verbatim&#34;&gt;identity&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(partition-by identity (randgenome))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt; ((:A :A) (:C) (:A) (:T) (:G :G) (:T) (:G) (:A) (:C :C) ...)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Extracting the lengths is then trivial: just map &lt;code class=&#34;verbatim&#34;&gt;count&lt;/code&gt; over the
sequences:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn get-lengths [s]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (-&amp;gt;&amp;gt; s
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (partition-by identity)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (map count)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(get-lengths (randgenome))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;=&amp;gt; (2 1 1 1 2 1 1 1 2 ...)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
(Note: running these functions unmodified will hang your REPL, since
&lt;code class=&#34;verbatim&#34;&gt;randgenome&lt;/code&gt; yields an infinite sequence! Wrap them with &lt;code class=&#34;verbatim&#34;&gt;take&lt;/code&gt; if
needed.)&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-1&#34;&gt;
Histogramming the data
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
The plots in my previous posts were made by the &lt;del&gt;simple&lt;/del&gt; easy
expedient of copying data into a Numbers spreadsheet on my Mac. We’d
like to eventually do some more ambitious plotting, however, so let’s
investigate a Clojure-based solution.&lt;/p&gt;
&lt;p&gt;
&lt;a href=&#34;http://incanter.org/&#34;&gt;Incanter&lt;/a&gt; provides a broad set of Clojure-based utilities for data
analysis, including matrices and linear algebra operations,
statistical distributions, and so on. Built on top of &lt;a href=&#34;http://www.jfree.org/jfreechart/&#34;&gt;JFreeChart&lt;/a&gt;, it
implements several different kinds of plots, including histograms, and
it should be an obvious candidate for displaying our length
distribution histogram.&lt;/p&gt;
&lt;p&gt;
Unfortunately, because of &lt;a href=&#34;https://github.com/liebke/incanter/issues/210&#34;&gt;two&lt;/a&gt; &lt;a href=&#34;https://github.com/liebke/incanter/issues/211&#34;&gt;issues&lt;/a&gt; I discovered, Incanter will not
work for our purposes. To make a long story short, it &lt;a href=&#34;https://github.com/liebke/incanter/issues/210&#34;&gt;does not handle
empty (zero) entries&lt;/a&gt; in histograms properly when displaying on a
logarithmic scale, and it &lt;a href=&#34;https://github.com/liebke/incanter/issues/211&#34;&gt;generates out-of-memory errors&lt;/a&gt; when given
more than a million or so entries. (Coming from high energy physics,
where such histograms are extremely common, these both seem like
serious flaws to me, which I hope will be remedied in the next
Incanter release.)&lt;/p&gt;
&lt;p&gt;
I wound up using the &lt;a href=&#34;http://www.jfree.org/jfreechart/api/javadoc/index.html&#34;&gt;JFreeChart API&lt;/a&gt; directly, though this was very
time consuming, as the API has approximately the same complexity as
the entire US space program or the Large Hadron Collider. (In what
follows below I elide details about false starts, descriptions of hair
pulling, and expletives.)&lt;/p&gt;
&lt;p&gt;
First, I needed to convert the lengths from &lt;code class=&#34;verbatim&#34;&gt;get-lengths&lt;/code&gt; into a
histogram with arbitrarily many entries:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn make-hist
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Convert seq of input xs into a histogram of nbins bins, from xmin to
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  xmax.  Discard overflows or underflows
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  [xmin xmax nbins xs]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let [;; &amp;#34;base&amp;#34; histogram (zeros):
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        zero-map (into (sorted-map)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                       (map (fn [x] [x 0]) (range nbins)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ;; get actual bin values for every input in xs:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        xbins (map #(int (* nbins (/ (- % xmin)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                     (- xmax xmin))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   xs)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        ;; strip out undeflows &amp;amp; overflows:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        no-overflows (-&amp;gt;&amp;gt; xbins
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                          (remove #(&amp;lt; % 0))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                          (remove #(&amp;gt;= % nbins)))]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ;; yield histogram as array of [ibin, height] pairs:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (into [] (reduce #(update-in %1 [%2] inc) zero-map no-overflows))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Supplying the minimum and maximum value ahead of time simplifies the
histogramming code substantially and allows us to choose the same
range for multiple plots, as will be shown below.&lt;/p&gt;
&lt;p&gt;
Armed with this transformation, the generation of the histogram plot
is as follows:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(ns jenome.graphs
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (:import [org.jfree.data.xy XYSeriesCollection XYSeries]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           [org.jfree.chart ChartFrame JFreeChart]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           [org.jfree.chart.plot XYPlot]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           [org.jfree.chart.axis NumberAxis]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           [org.jfree.chart.renderer.xy XYBarRenderer StandardXYBarPainter]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           [org.jfree.chart.renderer.category]))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn trim-zeros 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Convert zeros (or negatives) to small positive values to allow for
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  graphing on log scale
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  [vals]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (map (fn [[x y]] [x (if (&amp;gt; y 0) y 0.0001)]) vals))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn draw-hist
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Draw histogram of bins as generated by make-hist
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  [x-label values]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let [renderer (XYBarRenderer.)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        painter (StandardXYBarPainter.)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        series (XYSeries. [])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        blue (java.awt.Color. 0x3b 0x6c 0x9d)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        coll (XYSeriesCollection. series)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        y-axis (org.jfree.chart.axis.LogarithmicAxis. &amp;#34;Entries&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        plot (XYPlot. coll (NumberAxis. x-label) y-axis renderer)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        panel (JFreeChart. plot)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        frame (ChartFrame. &amp;#34;Histogram&amp;#34; panel)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (doto plot
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (.setBackgroundAlpha 0.0)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (.setRangeGridlinesVisible false)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (.setDomainGridlinesVisible false))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (doto renderer
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (.setBarPainter painter)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (.setPaint blue)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (.setDrawBarOutline true)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (.setOutlinePaint blue)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (.setOutlineStroke (java.awt.BasicStroke. 1))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (.setShadowVisible false))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (doseq [[x y] values]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (.add series (+ x 0.5) y))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (.setLowerBound y-axis 0.5)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (.setVisible (.getLegend panel) false)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (doto frame
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (.setSize 800 250)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (.setVisible true))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
I will omit a detailed explanation of how &lt;code class=&#34;verbatim&#34;&gt;draw-hist&lt;/code&gt; works because I’m
still not a JFreeChart expert (though if I do many more blog posts on
this topic I may be forced to become one, however reluctantly). The
principal difference with the Incanter implementation of histograms is
that we provide our own set of bin heights and simply plot those. This
follows a better separation of concerns anyways: our fairly simple
binning function remains separate from the visual presentation of the
bin positions and heights (we could, for example, add the counting of
overflows and underflows – this is left as an exercise to the reader).&lt;/p&gt;
&lt;p&gt;
(&lt;code class=&#34;verbatim&#34;&gt;trim-zeros&lt;/code&gt; exists to transform bin values of zero to small positive
numbers to avoid taking the logarithm of zero, which is undefined.)&lt;/p&gt;
&lt;p&gt;
Armed with these tools, we can now make our first distribution:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(-&amp;gt;&amp;gt; (randgenome)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (take 1000000)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     get-lengths
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (make-hist 0.5 60.5 60)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     trim-zeros
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (draw-hist &amp;#34;Repeat Lengths, random hypothesis&amp;#34;))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/random-repeat-lengths.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/random-repeat-lengths_hu_881e08ea0182744b.png&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Nucleotide repetition lengths for the random hypothesis
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
As expected by our analysis above, this shows the falling “&lt;a href=&#34;http://en.wikipedia.org/wiki/Power_law&#34;&gt;power-law&lt;/a&gt;”
distribution of randomly-occuring nucleotide repetitions. Compare this
with the genome for the yeast &lt;em&gt;S. Cerviciae&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(-&amp;gt;&amp;gt; (genome-sequence yeast)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     get-lengths
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (make-hist 0.5 60.5 60)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     trim-zeros
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (draw-hist &amp;#34;Repeat Lengths, S. Cerviciae&amp;#34;))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/yeast-repeat-lengths.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/yeast-repeat-lengths_hu_bd0821e6f373b4ee.png&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Nucleotide repetition lengths for the yeast S. Cerviciae
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
And, for humans (here we did not wait for the result for the entire genome):&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(-&amp;gt;&amp;gt; (genome-sequence human)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (take 10000000)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     get-lengths
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (make-hist 0.5 60.5 60)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     trim-zeros
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (draw-hist &amp;#34;Repeat Lengths, human genome&amp;#34;))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/human-repeat-lengths.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/human-repeat-lengths_hu_23fe744369465141.png&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Nucleotide repetition lengths for humans
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
The actual genome data clearly deviate from our null hypothesis of
randomness, as one might expect. However, these graphs raise more
questions than they answer. In particular, note that there is a sort
of bimodal characteristic or extended, secondary bump in the data for
humans, with hints of an outlier feature on the tail which may or may
not just be a statistical fluctuation.&lt;/p&gt;
&lt;p&gt;
One complicating factor we neglected is the role of “N-blocks”, which
should be eliminated without introducing artificially longer lengths;
e.g. &lt;code class=&#34;verbatim&#34;&gt;ANNNNA&lt;/code&gt; with the Ns removed should be considered two 1-blocks
rather than a two-block &lt;code class=&#34;verbatim&#34;&gt;AA&lt;/code&gt; group. This simple modification to
&lt;code class=&#34;verbatim&#34;&gt;get-lengths&lt;/code&gt; is left as another exercise to the reader (the change does
not affect the resulting distributions).&lt;/p&gt;
&lt;p&gt;
A real biologist could no doubt tell us a lot about these
distributions. Meanwhile, &lt;a href=&#34;https://github.com/eigenhombre/jenome&#34;&gt;the latest code&lt;/a&gt; has been pushed to GitHub.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Updating the Genome Decoder</title>
      <link>http://johnj.com/posts/updating-the-genome-decoder-resulting-consequences/</link>
      <pubDate>Sat, 13 Jul 2013 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/updating-the-genome-decoder-resulting-consequences/</guid>
      <description>
&lt;p&gt;
In our &lt;a href=&#34;http://johnj.com/posts/getting-our-hands-dirty/&#34;&gt;last post&lt;/a&gt; we saw that so-called “N-blocks” (regions of the
genome for which sequences are not available) were not getting decoded
correctly by &lt;a href=&#34;http://johnj.com/posts/a-two-bit-decoder&#34;&gt;our decoder&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
The solution is to look back into the so-called “file index” which
specifies where the N-blocks are, and how long each block is. The
modified decoder looks like this:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn genome-sequence
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Read a specific sequence, or all sequences in a file concatenated
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  together; return it as a lazy seq.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ([fname]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (let [sh (sequence-headers fname)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (lazy-mapcat (partial genome-sequence fname) sh)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ([fname hdr]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (let [ofs (:dna-offset hdr)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           dna-len (:dna-size hdr)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           byte-len (rounding-up-divide dna-len 4)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           starts-and-lengths (get-buffer-starts-and-lengths ofs 10000 byte-len)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (-&amp;gt;&amp;gt; (for [[offset length] starts-and-lengths
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                  b (read-with-offset fname offset length)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              (byte-to-base-pairs b))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            (apply concat)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            (take dna-len)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            (map-indexed (fn [i x] (if (is-in-an-n-block i hdr)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                    :N
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                    x)))))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The primary modification is the &lt;code class=&#34;verbatim&#34;&gt;map-indexed&lt;/code&gt; bit at the end, which
looks up the position of the base pair in the index using the
&lt;code class=&#34;verbatim&#34;&gt;is-in-an-n-block&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn is-in-an-n-block
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ([x hdr]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (let [{:keys [n-block-starts n-block-sizes]} hdr]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (is-in-an-n-block x n-block-starts n-block-sizes)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ([x n-block-starts n-block-lengths]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (let [pairs (map (fn [a b] [a (+ a b)])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      n-block-starts n-block-lengths)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (some (fn [[a b]] (&amp;lt; (dec a) x b)) pairs))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
I tested the new decoder against FASTA files of the first two
chromosomes of the human genome using the same procedure we used for
yeast in &lt;a href=&#34;http://johnj.com/posts/validating-the-genome-decoder&#34;&gt;my validation post&lt;/a&gt;.  The N-blocks (and all other sequences)
were decoded correctly.&lt;/p&gt;
&lt;p&gt;
The astute reader will note the use of &lt;code class=&#34;verbatim&#34;&gt;lazy-mapcat&lt;/code&gt; instead of =mapcat:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn lazy-mapcat
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Fully lazy version of mapcat.  See:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  http://clojurian.blogspot.com/2012/11/beware-of-mapcat.html
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  [f coll]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (lazy-seq
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   (if (not-empty coll)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (concat
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (f (first coll))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (lazy-mapcat f (rest coll))))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
A version of &lt;code class=&#34;verbatim&#34;&gt;genome-sequence&lt;/code&gt; which used mapcat instead of &lt;code class=&#34;verbatim&#34;&gt;lazy-mapcat&lt;/code&gt;
worked fine for individual chromosomes (file sections), but
consistently ran out of memory when processing whole genome files. It
took a bit of research and hair-pulling to figure out that there is a
rough edge with mapcat operating on large lazy sequences.&lt;/p&gt;
&lt;p&gt;
Lazy sequences are a strength of Clojure in general – they allow one
to process large, or even infinite, sequences of data without running
out of memory, by consuming and emitting values only as needed, rather
than all at once. Many of the core functions and macros in Clojure
operate on sequences lazily (producing lazy sequences as output),
including &lt;code class=&#34;verbatim&#34;&gt;map&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;for&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;concat&lt;/code&gt;, and so on. &lt;code class=&#34;verbatim&#34;&gt;mapcat&lt;/code&gt; is among these; however,
&lt;code class=&#34;verbatim&#34;&gt;mapcat&lt;/code&gt; is apparently not “maximally lazy” when concatenating other
lazy seqs, causing excessive memory consumption as explained in this
blog post. Using that post’s fully lazy (if slightly slower) version
of &lt;code class=&#34;verbatim&#34;&gt;mapcat&lt;/code&gt; fixed my memory leak as well. Though lazy seqs are awesome
in many ways, one does have to be careful of gotchas such as this one.&lt;/p&gt;
&lt;p&gt;
So, in the process of handling this relatively large dataset, we have
discovered two rough edges of Clojure, namely with &lt;code class=&#34;verbatim&#34;&gt;mapcat&lt;/code&gt; and
&lt;code class=&#34;verbatim&#34;&gt;count&lt;/code&gt;. We shall see if other surprises await us. Meanwhile, the latest
code is &lt;a href=&#34;https://github.com/eigenhombre/jenome&#34;&gt;up on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-1&#34;&gt;
Back to Frequencies
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Now that we are armed with a decoder which handles N-blocks correctly,
let us return to our original problem: nucleotide frequencies. For
yeast, we again have:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jenome.core&amp;gt; (-&amp;gt;&amp;gt; yeast genome-sequence frequencies)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{:C 2320576, :A 3766349, :T 3753080, :G 2317100}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Same as last time. For humans,&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jenome.core&amp;gt; (-&amp;gt;&amp;gt; human genome-sequence frequencies)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{:N 239850802, :T 856055361, :A 854963149, :C 592966724, :G 593325228}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
As expected, the GAC numbers are the same as what we had previously;
only T and N have changed. The distributions look like so:&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/hg-yeast-frequencies-2.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/hg-yeast-frequencies-2_hu_2259fa694663c15.png&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Updated nucleotide frequencies
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
We can see that &lt;a href=&#34;http://en.wikipedia.org/wiki/Chargaff&amp;#39;s_rules&#34;&gt;Chargaff’s Rule&lt;/a&gt; obtains now: A/T ratios are equal, as
are G/C ratios. (BTW, this rule is intuitively obvious if you consider
that in the double-helix structure, As are paired with Ts and Gs are
paired with Cs.) Interestingly, the relative abundance of GC pairs in
the human genome is higher than it is in yeast.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-2&#34;&gt;
Timing and Parallelizing
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Many of these “queries” on our data take a long time to run
(particularly for the human genome). So as not to tie up my REPL and
preventing me from doing other (presumably shorter) experiments, I
find it helpful to run such tasks inside a little macro (similar to
Clojure’s time) which performs the computation in a thread and, when
the task is finished, prints the time elapsed, the code that was run,
and the result:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defmacro tib
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  tib: Time in the Background
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Run body in background, printing body and showing result when it&amp;#39;s done.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  [expr]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  `(future (let [code# &amp;#39;~expr
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                 start# (. System (nanoTime))]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             (println &amp;#34;Starting&amp;#34; code#)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             (let [result# ~expr
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   end# (. System (nanoTime))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                   dursec# (/ (double (- end# start#)) (* 1000 1000 1000.0))]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               (println (format &amp;#34;Code: %s\nTime: %.6f seconds\nResult: %s&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                code#
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                dursec#
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                result#))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               result#))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
For example, our overflowing &lt;code class=&#34;verbatim&#34;&gt;count&lt;/code&gt; runs as follows:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(tib (count (range (* 1000 1000 1000 3))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Starting (count (range (* 1000 1000 1000 3)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Code: (count (range (* 1000 1000 1000 3)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Time: 399.204845 seconds
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Result: -1294967296&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Another tool which has proved useful is:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defmacro pseq
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Apply threading of funcs in parallel through all sequences specified
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  in the index of fname.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  [fname &amp;amp; funcs]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  `(pmap #(-&amp;gt;&amp;gt; (genome-sequence ~fname %)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               ~@funcs)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         (sequence-headers ~fname)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This threads one or more &lt;code class=&#34;verbatim&#34;&gt;funcs&lt;/code&gt; through all the sequences in the file,
as mapped out by the file headers. The magic here is &lt;code class=&#34;verbatim&#34;&gt;pmap&lt;/code&gt;, which is
&lt;code class=&#34;verbatim&#34;&gt;map&lt;/code&gt; parallelized onto separate threads across all available
cores. &lt;code class=&#34;verbatim&#34;&gt;pseq&lt;/code&gt; maxes out the CPU on my quad-core Macbook Pro and gives
results significantly faster:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Code: (-&amp;gt;&amp;gt; yeast genome-sequence frequencies)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Time: 33.090855 seconds
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Result: {:C 2320576, :A 3766349, :T 3753080, :G 2317100}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Code: (apply (partial merge-with +) (pseq yeast frequencies))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Time: 16.056695 seconds
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Result: {:C 2320576, :A 3766349, :T 3753080, :G 2317100}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
With our updated decoder and these new tools, we can &lt;a href=&#34;http://johnj.com/posts/nucleotide-repetition-lengths&#34;&gt;continue our
poking and prodding of the genome&lt;/a&gt; in subsequent posts.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Getting Our Hands Dirty (with the Human Genome)</title>
      <link>http://johnj.com/posts/getting-our-hands-dirty/</link>
      <pubDate>Wed, 10 Jul 2013 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/getting-our-hands-dirty/</guid>
      <description>&lt;p&gt;
In the past &lt;a href=&#34;http://johnj.com/posts/a-two-bit-decoder&#34;&gt;two&lt;/a&gt; &lt;a href=&#34;http://johnj.com/posts/validating-the-genome-decoder&#34;&gt;posts&lt;/a&gt;, we created and validated a decoder for genome
data in 2bit format.&lt;/p&gt;
&lt;p&gt;
Let’s start actually looking at the human and yeast genomes &lt;em&gt;per
se&lt;/em&gt;. First, if you haven’t downloaded it yet, you’ll need a copy of the
human genome data file:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cd /tmp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;wget http://hgdownload.cse.ucsc.edu/goldenPath/hg19/bigZips/hg19.2bit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
(Depending on your local bandwidth conditions, this can take quite awhile.)&lt;/p&gt;
&lt;p&gt;
Again we define convenience vars for the two data files:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(def human &amp;#34;/tmp/hg19.2bit&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(def yeast (as-file (resource &amp;#34;sacCer3.2bit&amp;#34;)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The simplest thing we can do is count base pairs:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jenome.core&amp;gt; (time (-&amp;gt;&amp;gt; yeast genome-sequence count))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#34;Elapsed time: 17577.042 msecs&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;12157105
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jenome.core&amp;gt; (time (-&amp;gt;&amp;gt; human genome-sequence count))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#34;Elapsed time: 4513537.422 msecs&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;-1157806032&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
WTF?! count has overflowed (if you convert -1157806032 to an unsigned
int you get 3137161264, which makes more sense). This, and our running
time of 75 minutes, is our first hint of pain associated with handling
with such a large dataset.&lt;/p&gt;
&lt;p&gt;
It’s worth noting that number overflows in Clojure generally raise an
ArithmeticException (or silently get promoted to BigIntegers,
depending on the operators used) – I emailed &lt;a href=&#34;https://groups.google.com/forum/#!forum/clojure&#34;&gt;the Clojure mailing list&lt;/a&gt;
about this surprise and &lt;a href=&#34;http://dev.clojure.org/jira/browse/CLJ-1229&#34;&gt;a ticket has been made&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
The overflow is easily enough remedied with a non-overflowing &lt;code class=&#34;verbatim&#34;&gt;count&lt;/code&gt;
(&lt;code class=&#34;verbatim&#34;&gt;inc&amp;#39;&lt;/code&gt; is one of the aforementioned promoting operators):&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn count&amp;#39; [s]   ;; Regular count overflows to negative int!
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (loop [s s, n 0]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (if (seq s)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (recur (rest s)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             (inc&amp;#39; n))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      n)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Which gives us the unsigned version of our previous answer, in 10%
more time:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jenome.core&amp;gt; (time (-&amp;gt;&amp;gt; human genome-sequence count&amp;#39;))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#34;Elapsed time: 4931630.301 msecs&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;3137161264
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jenome.core&amp;gt; (float (/ 3137161264 12157105))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;258.05167&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
(Update 2/14/2014: Matthew Wampler-Doty came up with a more elegant
&lt;code class=&#34;verbatim&#34;&gt;count&amp;#39;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn count&amp;#39; [s] (reduce (fn [x _] (inc x)) 0 s))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
which is about 25% faster than my slightly more naïve version.)&lt;/p&gt;
&lt;p&gt;
We now have our first bit of insight into human vs. yeast genomes: we
humans have about 260x more base pairs than yeast do.&lt;/p&gt;
&lt;p&gt;
The next question is, What are the relative proportions of occurrence
of each base pair? Easily answered by the &lt;code class=&#34;verbatim&#34;&gt;frequencies&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jenome.core&amp;gt; (-&amp;gt;&amp;gt; yeast genome-sequence frequencies)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{:C 2320576, :A 3766349, :T 3753080, :G 2317100}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jenome.core&amp;gt; (-&amp;gt;&amp;gt; human genome-sequence frequencies)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{:T 1095906163, :A 854963149, :C 592966724, :G 593325228}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jenome.core&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Those numbers have a lot of digits, so here are some bar charts:&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/hg-yeast-frequencies-1.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/hg-yeast-frequencies-1_hu_222d7c4682de624c.png&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Our first stab at nucleotide frequencies
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Though we are playing ignorant data analysts rather than real
biologists, this looks a bit fishy right out of the gate. Why so many
Ts?&lt;/p&gt;
&lt;p&gt;
As a sanity check, perhaps we ought to look more closely at the actual
data:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jenome.core&amp;gt; (-&amp;gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                human
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                genome-sequence
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                (map name)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                (take 100)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                (apply str))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;=&amp;gt; &amp;#34;TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;    TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
That doesn’t look good at all. How are the first 10000 base pairs
distributed?&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jenome.core&amp;gt; (-&amp;gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                human
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                genome-sequence
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                (take 10000)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                frequencies)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;=&amp;gt; {:T 10000}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
How about the next 10,0000?&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jenome.core&amp;gt; (-&amp;gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                human
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                genome-sequence
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                (drop 10000)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                (take 10000)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                frequencies)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;=&amp;gt; {:T 2012, :A 2065, :C 3028, :G 2895}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
That looks a lot better. Playing around with this shows that exactly
the first 10,000 base pairs are Ts.&lt;/p&gt;
&lt;p&gt;
The astute reader will recall that the file index in our decoder had
slots for unknown (“N-block”) sequences. Though we didn’t explore them
explicitly, /S. Cerviciae/’s genome had nothing in these slots. It’s
time we went back and looked at our human’s file index:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (-&amp;gt;&amp;gt; human
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       sequence-headers
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (map (juxt :name :dna-size :n-block-count))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       clojure.pprint/pprint)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; =&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;([&amp;#34;chr1&amp;#34; 249250621 39]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [&amp;#34;chr2&amp;#34; 243199373 24]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [&amp;#34;chr3&amp;#34; 198022430 9]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [&amp;#34;chr4&amp;#34; 191154276 12]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [&amp;#34;chr5&amp;#34; 180915260 7]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [&amp;#34;chr6&amp;#34; 171115067 11]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [&amp;#34;chr7&amp;#34; 159138663 17]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [&amp;#34;chrX&amp;#34; 155270560 23]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [&amp;#34;chr8&amp;#34; 146364022 9]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; ;; LOTS more entries...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Holy cow, they all have N-blocks. This is only the first section; &lt;a href=&#34;https://gist.github.com/eigenhombre/5967388&#34;&gt;this
Gist&lt;/a&gt; shows the entire set of N-blocks for all the sequences. (It also
shows that there are many more files in the index than the yeast
genome had, and many more than one for each of the 24 human
chromosomes – clearly there are many things to learn about this data.)&lt;/p&gt;
&lt;p&gt;
Moreover, if we look at the N-blocks for the first sequence:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (-&amp;gt;&amp;gt; human
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       sequence-headers
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       first
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       ((juxt :n-block-starts :n-block-sizes))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (apply interleave)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (partition 2)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (map vec)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       clojure.pprint/pprint)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; Gives:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;([0 10000]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [177417 50000]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [267719 50000]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [471368 50000]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; ;; ... total of 39 entries.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
As expected, our first 10,000 base pairs are actually unknown. The
2-bit file format apparently uses 0’s for the unknowns AND to
represent Ts. The rest of the offsets and lengths are in &lt;a href=&#34;https://gist.github.com/eigenhombre/5967451&#34;&gt;this
Gist&lt;/a&gt;. (Perhaps someone can explain to me why these are all multiples
of 10000!)&lt;/p&gt;
&lt;p&gt;
All this means that our decoder needs a tweak to give us &lt;code class=&#34;verbatim&#34;&gt;:N&lt;/code&gt; instead
of &lt;code class=&#34;verbatim&#34;&gt;:T&lt;/code&gt; when the position of the base pair is inside one of the
N-blocks. This we will accomplish in the next post, before we proceed
to the study of other properties of the genome.&lt;/p&gt;
&lt;p&gt;
Before we end, it’s worth noting that, had we been real biologists, we
would surely have known about &lt;a href=&#34;http://en.wikipedia.org/wiki/Chargaff&amp;#39;s_rules&#34;&gt;Chargaff’s Rule&lt;/a&gt;, which states that A and
T ratios should be the same, as are G and C, as born out in our yeast
distribution, above.&lt;/p&gt;
&lt;p&gt;
Though we haven’t gained mastery over too much of the genome yet, it
is worth pointing out Clojure’s strengths in the above and previous
posts. With comparatively little code we are able to investigate many
of the features of these data sets, thanks to the power of the
threading macro &lt;code class=&#34;verbatim&#34;&gt;-&amp;gt;&amp;gt;&lt;/code&gt;, higher-order functions such as &lt;code class=&#34;verbatim&#34;&gt;juxt&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;map&lt;/code&gt;, and
sequence handling functions such as &lt;code class=&#34;verbatim&#34;&gt;interleave&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;partition&lt;/code&gt;, and
&lt;code class=&#34;verbatim&#34;&gt;frequencies&lt;/code&gt;. We’ve also processed large data sets “lazily” without
needing to fit large amounts of data in memory at once. And we have
hardly scratched the surface of Clojure’s tools for parallel
computation, though we may make more use of these in coming posts.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Validating the Genome Decoder</title>
      <link>http://johnj.com/posts/validating-the-genome-decoder/</link>
      <pubDate>Sun, 07 Jul 2013 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/validating-the-genome-decoder/</guid>
      <description>&lt;p&gt;
Today we’ll validate the genome decoder &lt;a href=&#34;http://johnj.com/posts/a-two-bit-decoder&#34;&gt;we described yesterday&lt;/a&gt;, once
again with our friend the yeast Saccharomyces cerevisiae (you may want
to enjoy a slice of freshly-baked bread and a stein of Pilsner with
this post).&lt;/p&gt;
&lt;p&gt;
We are aided in this case by the availability of the SacCer3 genome in
both 2bit and FASTA formats. We can get &lt;a href=&#34;https://hgdownload.soe.ucsc.edu/goldenPath/sacCer3/chromosomes/&#34;&gt;the FASTA version&lt;/a&gt; in the same
place &lt;a href=&#34;https://hgdownload.soe.ucsc.edu/goldenPath/sacCer3/chromosomes/&#34;&gt;we got the 2bit file&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mkdir /tmp/sacCer3_fasta
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cd /tmp/sacCer3_fasta
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;wget http://hgdownload-test.cse.ucsc.edu/goldenPath/sacCer3/bigZips/\
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;chromFa.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tar xvzf chromFa.tar.gz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
There is one FASTA file per sequence, starting something like this:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;gt;chrI
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CCACACCACACCCACACACCCACACACCACACCACACACCACACCACACC
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CACACACACACATCCTAACACTACCCTAACACAGCCCTAATCTAACCCTG
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;GCCAACCTGTCTCTCAACTTACCCTCCATTACCCTGCCTCCACTCGTTAC
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CCTGTCCCATTCAACCATACCACTCCGAACCACCATCCATCCCTCTACTT
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ACTACCACTCACCCACCGTTACCCTCCAATTACCCATATCCAACCCACTG
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CCACTTACCCTACCATTACCCTACCATCCACCATGACCTACTCACCATAC&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Back in the REPL, we can now spit out our own copy in the same format
(carrying over &lt;code class=&#34;verbatim&#34;&gt;yeast&lt;/code&gt; and other functions and vars from the previous
post).&lt;/p&gt;
&lt;p&gt;
First we need a new directory for the FASTA files we’ll generate:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(.mkdir (clojure.java.io/file &amp;#34;/tmp/decoded&amp;#34;))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Then we convert the keywords in our sequence to strings:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn genome-str
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Convert e.g. [:A :G :T :C] to \&amp;#34;AGTC\&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  [s]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (-&amp;gt;&amp;gt; s
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (map name)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (apply str)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
A simple function will spit out the files, given a seq:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn write-seq
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Write a (potentially very long) sequence of lines to a text file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  [filename s]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (with-open [wrt (clojure.java.io/writer filename)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (doseq [x s]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (.write wrt (str x &amp;#34;\n&amp;#34;)))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
And now for the actual converter:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(doseq [{:keys [name dna-offset dna-size]} (sequence-headers yeast)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let [fname (str &amp;#34;/tmp/decoded/&amp;#34; name &amp;#34;.fa&amp;#34;)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (write-seq fname
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               (cons (str &amp;#34;&amp;gt;&amp;#34; name)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                     (-&amp;gt;&amp;gt; (genome-sequence yeast dna-offset dna-size)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                          (partition-all 50)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                          (map genome-str))))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Did it work?&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cd /tmp/sacCer3_fasta
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;for f in *.fa; do diff $f /tmp/decoded/$f; done&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
No output – it succeeded! This builds more confidence that we didn’t
screw anything up in the decoder. (There are also a few other
hard-coded unit tests in &lt;code class=&#34;verbatim&#34;&gt;test_core.clj&lt;/code&gt;.)&lt;/p&gt;
&lt;p&gt;
Comparing file sizes, the FASTA files are about 4 times larger than
the original 2bit file. If you tar and compress both versions, the
FASTA files are still about 30% larger. It is left as as an exercise
to the reader (with some spare hard disk) to do the same comparison
with the human genome. (Though larger, the FASTA files would clearly
be simpler to work with, and these days 4 GB isn’t too terribly much
data; nevertheless, we’ll continue to use the 2bit file and decoder
for our explorations.)&lt;/p&gt;
&lt;p&gt;
Now we are ready to begin playing with the actual data – &lt;a href=&#34;http://johnj.com/posts/getting-our-hands-dirty&#34;&gt;starting in
the next post&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>A Two Bit Decoder</title>
      <link>http://johnj.com/posts/a-two-bit-decoder/</link>
      <pubDate>Sat, 06 Jul 2013 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/a-two-bit-decoder/</guid>
      <description>&lt;p&gt;
The entire human genome is available as a single .2bit file &lt;a href=&#34;http://hgdownload.cse.ucsc.edu/downloads.html#human&#34;&gt;here&lt;/a&gt;
(click on “Full Data Set”, then download &lt;code class=&#34;verbatim&#34;&gt;hg19.2bit&lt;/code&gt;). Unlike the
stellar signal in &lt;em&gt;His Master’s Voice&lt;/em&gt;, &lt;a href=&#34;http://genome.ucsc.edu/FAQ/FAQformat#format7&#34;&gt;the 2bit format&lt;/a&gt; is reasonably
clearly documented.&lt;/p&gt;
&lt;p&gt;
We want to write Clojure code to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Provide base pairs in symbolic (rather than raw binary) form as
lazy sequences – i.e., sequences which need not all fit in memory
at once, but can be consumed and processed as needed;&lt;/li&gt;
&lt;li&gt;Provide “random access” to this data selectively, e.g. by
chromosome, rather than always reading through the entire file;&lt;/li&gt;
&lt;li&gt;Provide access to metadata encoded in the file.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The functionality to do this is posted in the &lt;a href=&#34;https://github.com/eigenhombre/jenome&#34;&gt;jenome&lt;/a&gt; project on
GitHub. In this post, we’ll explore this code a little; in following
posts, we’ll do some investigating of the actual genome &lt;em&gt;per se&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;
Capability (2) is provided, in part, by implementing random-access
reads from file &lt;code class=&#34;verbatim&#34;&gt;fname&lt;/code&gt; of &lt;code class=&#34;verbatim&#34;&gt;len&lt;/code&gt; bytes starting at &lt;code class=&#34;verbatim&#34;&gt;offset&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(ns jenome.rafile
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (:import (java.io RandomAccessFile)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn read-with-offset [fname offset len]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let [raf (RandomAccessFile. fname &amp;#34;r&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        bb (byte-array len)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (.seek raf offset)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (.readFully raf bb)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (.close raf)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    bb))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Armed with this, we can get the &lt;code class=&#34;verbatim&#34;&gt;.2bit&lt;/code&gt; file header:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn file-header [fname]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let [[sig ver seqcnt resvd] (-&amp;gt;&amp;gt; (read-with-offset fname 0 16)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                    (partition 4)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                    (map bytes-to-number))]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (assert (= sig 0x1A412743))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (assert (= ver 0))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (assert (= resvd 0))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    seqcnt))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;code class=&#34;verbatim&#34;&gt;file-header&lt;/code&gt; basically just gives us the number of sequences (usually,
chromosomes) in the file, doing some sanity checks along the
way. &lt;code class=&#34;verbatim&#34;&gt;bytes-to-number&lt;/code&gt; converts an arbitrary sequence of bytes to the
appropriate unsigned integer. (For brevity’s sake, I won’t show every
utility function in this blog post; &lt;a href=&#34;https://github.com/eigenhombre/jenome/blob/master/src/jenome/core.clj&#34;&gt;the source code on GitHub&lt;/a&gt; is
reasonably short.)&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/2bitfig1.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/2bitfig1_hu_b6d2f6b94b026559.png&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
The next part of the file, as shown in Figure 1, is called the “file
index,” and contains a list of sequences contained the rest of the
file. It can be read as follows:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn file-index [fname seqcnt]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (loop [i 0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         ofs 16
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         ret []]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (if (&amp;lt; i seqcnt)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (let [[nlen] (read-with-offset fname ofs 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            name (apply str (map char (read-with-offset fname 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                                        (+ ofs 1) nlen)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            seq-offset (get32 fname (+ ofs 1 nlen))]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        (recur (inc i) (+ ofs nlen 5) (conj ret [nlen name seq-offset])))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      ret)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This somewhat imperative code walks through the &lt;code class=&#34;verbatim&#34;&gt;seqcnt&lt;/code&gt; sequence
portions of the index, pulling out sequence names and lengths as we
go.&lt;/p&gt;
&lt;p&gt;
It’s here that we introduce a new friend, the yeast &lt;a href=&#34;http://en.wikipedia.org/wiki/Saccharomyces_cerevisiae&#34;&gt;Saccharomyces
cerevisiae&lt;/a&gt; (SacCer3), used since antiquity for making bread and
fermented beverages. Relatively small in comparison with the human
genome, SacCer3 will be our “unit test” organism. Available online and
checked into the &lt;code class=&#34;verbatim&#34;&gt;resources&lt;/code&gt; folder in this repo, the file can be accessed as&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(def yeast
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   (as-file (resource &amp;#34;sacCer3.2bit&amp;#34;)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
(I have imported &lt;code class=&#34;verbatim&#34;&gt;resource&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;as-file&lt;/code&gt; from &lt;code class=&#34;verbatim&#34;&gt;clojure.java.io&lt;/code&gt;; again, see
the source code.)&lt;/p&gt;
&lt;p&gt;
Our index-reading code yields:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let [seqcnt (file-header yeast)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (file-index yeast seqcnt))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ;=&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[[4 &amp;#34;chrI&amp;#34; 191]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [5 &amp;#34;chrII&amp;#34; 57762]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [6 &amp;#34;chrIII&amp;#34; 261074]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [5 &amp;#34;chrIV&amp;#34; 340245]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [5 &amp;#34;chrIX&amp;#34; 723245]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [4 &amp;#34;chrV&amp;#34; 833233]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [5 &amp;#34;chrVI&amp;#34; 977468]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [6 &amp;#34;chrVII&amp;#34; 1045025]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [7 &amp;#34;chrVIII&amp;#34; 1317776]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [4 &amp;#34;chrX&amp;#34; 1458453]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [5 &amp;#34;chrXI&amp;#34; 1644907]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [6 &amp;#34;chrXII&amp;#34; 1811627]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [7 &amp;#34;chrXIII&amp;#34; 2081188]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [6 &amp;#34;chrXIV&amp;#34; 2312312]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [5 &amp;#34;chrXV&amp;#34; 2508412]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [6 &amp;#34;chrXVI&amp;#34; 2781251]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; [4 &amp;#34;chrM&amp;#34; 3018284]]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The apparent consistency of these values give us some initial
confidence that we are reading the index correctly. Note, however, the
curious fact that &lt;code class=&#34;verbatim&#34;&gt;chrIX&lt;/code&gt; appears between &lt;code class=&#34;verbatim&#34;&gt;IV&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;V&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;
With this encouraging start, we can now attack the sequences
proper. These are laid out as shown in Figure 2, with block metadata
prepended to the actual DNA sequences:&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/2bitfig2.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/2bitfig2_hu_2c43bf82fda34b83.png&#34; style=&#34;width:300px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Sequence Record Layout
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
The “N blocks” are blocks of unknown sequences with specified offsets
and lengths. Masked blocks are blocks which are known repetitions
(indicated as lower case &lt;code class=&#34;verbatim&#34;&gt;a&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;g&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;c&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;t&lt;/code&gt; in the text-based
‘FASTA’ file format). We are obviously most interested in &lt;code class=&#34;verbatim&#34;&gt;dnaSize&lt;/code&gt;, the
number of base pairs in the sequence, and the actual sequence values
themselves.&lt;/p&gt;
&lt;p&gt;
Unpacking the above data format (except the base pairs &lt;em&gt;per se&lt;/em&gt;) makes
heavy use of &lt;code class=&#34;verbatim&#34;&gt;get32&lt;/code&gt;, which just returns the unsigned 32-bit integer at
the specified file location. This code doesn’t need to be super
efficient, since the block headers themselves are quite small. The
metadata for the entire file is returned as a sequence of maps.&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn getblk [fname offset n]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let [ret (map #(get32 fname (+ offset (* 4 %))) (range n))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        offset (skip offset n)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [ret offset]))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn sequence-headers
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Get sequence headers from .2bit file, as documented in
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  http://genome.ucsc.edu/FAQ/FAQformat#format7. Returns a list of maps
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  with details for each sequence.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  [fname]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (let [seqcnt (file-header fname)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (for [[nlen name ofs] (file-index fname seqcnt)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (let [[[dna-size]         ofs] (getblk fname ofs 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            [[n-block-count]    ofs] (getblk fname ofs 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            [n-block-starts     ofs] (getblk fname ofs n-block-count)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            [n-block-sizes      ofs] (getblk fname ofs n-block-count)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            [[mask-block-count] ofs] (getblk fname ofs 1)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            [mask-block-starts  ofs] (getblk fname ofs mask-block-count)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            [mask-block-sizes   ofs] (getblk fname ofs mask-block-count)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            [[reserved]         ofs] (getblk fname ofs 1)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        (assert (zero? reserved))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        {:name name
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         :nlen nlen
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         :dna-size dna-size
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         :n-block-count n-block-count
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         :n-block-starts n-block-starts
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         :n-block-sizes n-block-sizes
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         :mask-block-starts mask-block-starts
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         :mask-block-sizes mask-block-sizes
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         :dna-offset ofs}))))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
A few sanity checks are included in &lt;code class=&#34;verbatim&#34;&gt;test_core.clj&lt;/code&gt; to make sure we’re
decoding the metadata correctly. Requirement (3) is done!&lt;/p&gt;
&lt;p&gt;
The final step (Requirement (1)), is to actually get our base pairs
(BPs). Since we have to assume the data set is very large (as is the
case with the human genome), we cannot read the entire DNA sequence at
once. The first part is to break the &lt;code class=&#34;verbatim&#34;&gt;dna-size&lt;/code&gt; base pairs (remember we
have 2 bits per BP, or 4 BP/byte), starting at &lt;code class=&#34;verbatim&#34;&gt;dna-offset&lt;/code&gt;. First we
obtain the “coordinates” of the sequences we want to read:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn get-buffer-starts-and-lengths 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Return buffer offsets (starting at ofs) required to cleanly read a
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  total of m bytes no more than n at a time
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  [ofs n m]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (loop [a ofs
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         len n
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         ret []]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    (if (&amp;gt;= a (+ m ofs))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      ret
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (recur (+ a n)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             n
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             (conj ret [a (min len (- (+ m ofs) a))])))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; Example:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(get-buffer-starts-and-lengths 100 200 512)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;=&amp;gt; [[100 200] [300 200] [500 112]]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
At long last, having obtained the locations and lengths we want to read from, we can get our sequences out:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn genome-sequence
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Read a specific sequence, or all sequences in a file concatenated
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  together; return it as a lazy seq.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ([fname]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (let [sh (sequence-headers fname)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (mapcat #(genome-sequence fname %1 %2)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               (map :dna-offset sh)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               (map :dna-size sh))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ([fname ofs dna-len]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     (take dna-len
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           (apply concat
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                  (let [byte-len (rounding-up-divide dna-len 4)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        starts-and-lengths (get-buffer-starts-and-lengths
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                              ofs 10000 byte-len)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    (for [[offset length] starts-and-lengths
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                          :let [buf (read-with-offset fname offset length)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                          b buf]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      (byte-to-base-pairs b)))))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;; Example:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; (-&amp;gt;&amp;gt; yeast
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      genome-sequence
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      (take 30))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;=&amp;gt; (:C :C :A :C :A :C :C :A :C :A :C :C :C :A :C
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;    :A :C :A :C :C :C :A :C :A :C :A :C :C :A :C)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This function allows us to choose the entire genome, or that for a
given offset and number of base pairs (whether from the metadata for
an entire chromosome, or some smaller region, thus satisfying (2)).&lt;/p&gt;
&lt;p&gt;
The next post will focus on verification of correctness of this code;
subsequent posts will begin to explore the characteristics of this
data for various genomes, human or otherwise.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Exploratory Genomics with Clojure</title>
      <link>http://johnj.com/posts/exploratory-genomics-with-clojure/</link>
      <pubDate>Fri, 05 Jul 2013 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/exploratory-genomics-with-clojure/</guid>
      <description>&lt;p&gt;
In Stanislaw Lem’s &lt;em&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/His_Master&amp;#39;s_Voice_(novel)&#34;&gt;His Master’s Voice&lt;/a&gt;&lt;/em&gt;, humanity receives a “letter
from the stars,” in the form of regularly repeating binary data
encoded in a beam of extraterrestrial neutrinos. The protagonists know
nothing &lt;em&gt;a priori&lt;/em&gt; about the content of the letter. The plot unfolds as
the message slowly, as a result of careful study, yields a few (not
many) of the signal’s secrets.&lt;/p&gt;
&lt;p&gt;
What would you do if you received such a dataset? How would you study
it? What real world datasets are similarly mysterious?&lt;/p&gt;
&lt;p&gt;
As most readers will know, every living being contains a “message” of
sorts, encoded, not in base 2 (binary), but rather base 4: A, G, C, or
T, arranged in paired, sequential molecular strands called DNA (in
which every A is paired with a T, every C with a G). From 159,662 base
pairs for &lt;a href=&#34;http://www.nature.com/news/2006/061009/full/news061009-10.html&#34;&gt;the smallest known genome&lt;/a&gt;, to 3.3 billion BPs for humans, to
&lt;a href=&#34;http://www.sciencemag.org/news/2010/10/scienceshot-biggest-genome-ever&#34;&gt;149 billion BPs&lt;/a&gt; for the largest genome, that of &lt;em&gt;Paris japonica&lt;/em&gt;, each
organism carries its own unique tome locked in its cells.&lt;/p&gt;
&lt;p&gt;
In the past ten years, the human genome &lt;a href=&#34;http://en.wikipedia.org/wiki/Human_Genome_Project&#34;&gt;has been sequenced&lt;/a&gt; and &lt;a href=&#34;http://en.wikipedia.org/wiki/Human_Genome_Project&#34;&gt;made
widely available&lt;/a&gt;. Though downloadable in a variety of formats, the
most compact seems to be the ‘2bit’ format (two bits per base pair):
the genome in this format is just under a gigabyte,
uncompressed. Plenty of genomes of simpler organisms are available for
study as well.&lt;/p&gt;
&lt;p&gt;
I am not a genomicist or biologist, but am curious about the
properties of the “data” stored within us all. In the next few blog
posts I intend to investigate genomic data (human or otherwise) using
Clojure, a modern Lisp developed for the JVM. Clojure’s strengths are
simplicity, concurrency, expressiveness and speed – assets which will
be helpful as we tackle a few simple analytical tasks aimed at
understanding some of the properties of life’s very own “Big Data.”&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Rosalind Problems in Clojure</title>
      <link>http://johnj.com/posts/rosalind-problems-in-clojure/</link>
      <pubDate>Sun, 09 Jun 2013 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/rosalind-problems-in-clojure/</guid>
      <description>&lt;p&gt;
This weekend I’ve been having a lot of fun working the Bioinformatics
problems from &lt;a href=&#34;http://rosalind.info/&#34;&gt;Rosalind&lt;/a&gt;. Most people work them in Python, but so far
they have been very amenable to Clojure except where BioPython
libraries are used for access to online databases. The problems have
been straightforward so far but I have enjoyed the elegance and
brevity that Clojure lends the solutions.&lt;/p&gt;
&lt;p&gt;
In particular, I like this short translator &lt;a href=&#34;http://rosalind.info/problems/prot/&#34;&gt;from RNA sequences to
amino acids&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;;;; Translating RNA into Amino Acids
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defmacro deftable [tname &amp;amp; rest]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  `(def ~tname (apply hash-map &amp;#39;(~@rest))))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(deftable proteins
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  UUU F      CUU L      AUU I      GUU V
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  UUC F      CUC L      AUC I      GUC V
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  UUA L      CUA L      AUA I      GUA V
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  UUG L      CUG L      AUG M      GUG V
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  UCU S      CCU P      ACU T      GCU A
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  UCC S      CCC P      ACC T      GCC A
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  UCA S      CCA P      ACA T      GCA A
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  UCG S      CCG P      ACG T      GCG A
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  UAU Y      CAU H      AAU N      GAU D
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  UAC Y      CAC H      AAC N      GAC D
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  UAA Stop   CAA Q      AAA K      GAA E
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  UAG Stop   CAG Q      AAG K      GAG E
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  UGU C      CGU R      AGU S      GGU G
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  UGC C      CGC R      AGC S      GGC G
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  UGA Stop   CGA R      AGA R      GGA G
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  UGG W      CGG R      AGG R      GGG G)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(defn to-protein [s]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  (-&amp;gt;&amp;gt; s
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (partition 3)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (map (partial apply str))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (map symbol)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (map proteins)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (take-while #(not= % &amp;#39;Stop))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       (apply str)))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The body of the &lt;code class=&#34;verbatim&#34;&gt;proteins&lt;/code&gt; table is literally cut-and-pasted from &lt;a href=&#34;http://rosalind.info/problems/prot/&#34;&gt;the
problem page&lt;/a&gt; (click on “RNA codon table”). I think it’s a good example
of using macros to provide a little bit of syntactic sugar to make the
code just a little more readable and elegant, or to encode domain
facts as directly as possible.&lt;/p&gt;
&lt;p&gt;
This and my other solutions so far are &lt;a href=&#34;https://github.com/eigenhombre/rosalind&#34;&gt;up on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/roz.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/roz_hu_8fb41ee3fe8b1cdb.jpg&#34; style=&#34;width:600px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Introduction to Context Managers in Python</title>
      <link>http://johnj.com/posts/intro-to-context-managers-in-python/</link>
      <pubDate>Sat, 20 Apr 2013 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/intro-to-context-managers-in-python/</guid>
      <description>
&lt;p&gt;
Context managers are a way of allocating and releasing some sort of
resource exactly where you need it. The simplest example is file
access:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;with file(&amp;#34;/tmp/foo&amp;#34;, &amp;#34;w&amp;#34;) as foo:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    print &amp;gt;&amp;gt; foo, “Hello!”&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This is essentially equivalent to:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;foo = file(&amp;#34;/tmp/foo&amp;#34;, &amp;#34;w&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;try:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    print &amp;gt;&amp;gt; foo, “Hello!”
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;finally:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    foo.close()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Locks are another example. Given:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;import threading
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;lock = threading.Lock()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
then&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;with lock:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    my_list.append(item)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
replaces the more verbose:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;lock.acquire()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;try:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    my_list.append(item)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;finally:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    lock.release()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
In each case a bit of boilerplate is eliminated, and the “context” of
the file or the lock is acquired, used, and released cleanly.&lt;/p&gt;
&lt;p&gt;
Context managers are a common pattern in Lisp, where they are usually
defined using macros.  Examples include &lt;code class=&#34;verbatim&#34;&gt;with-open&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;with-out-str&lt;/code&gt; in
Clojure and &lt;code class=&#34;verbatim&#34;&gt;with-open-file&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;with-output-to-string&lt;/code&gt; in Common Lisp.&lt;/p&gt;
&lt;p&gt;
Python, not having macros, must include context managers as part of
the language. Since 2.5, it does so, providing an easy mechanism for
rolling your own. Though the default, “low level” way to make a
context manager is to make a class which implements the &lt;a href=&#34;http://docs.python.org/2/library/stdtypes.html#typecontextmanager&#34;&gt;context
management protocol&lt;/a&gt;, by implementing &lt;code class=&#34;verbatim&#34;&gt;__enter__&lt;/code&gt; and &lt;code class=&#34;verbatim&#34;&gt;__exit__&lt;/code&gt; methods,
the simplest way is using the &lt;code class=&#34;verbatim&#34;&gt;contextmanager&lt;/code&gt; decorator from the
contextlib library, and invoking &lt;code class=&#34;verbatim&#34;&gt;yield&lt;/code&gt; in your context manager
function in between the setup and teardown steps.&lt;/p&gt;
&lt;p&gt;
Here is a context manager which you could use to time the use of
threads vs. processes in Python:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;import contextlib
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;import time
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;@contextlib.contextmanager
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;def time_print(task_name):
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    t = time.time()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    try:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        yield
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    finally:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        print task_name, “took&amp;#34;, time.time() - t, “seconds.”
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;with time_print(“processes”):
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [doproc() for _ in range(500)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# processes took 15.236166954 seconds.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;with time_print(“threads”):
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [dothread() for _ in range(500)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# threads took 0.11357998848 seconds.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Composition
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Context managers can be composed very nicely. While you can certainly
do the following,&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;with a(x, y) as A:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    with b(z) as B:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        # Do stuff&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
in Python 2.7 or above, the following also works:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;with a(x, y) as A, b(z) as B:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    # Do stuff&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
with Python 2.6, using &lt;code class=&#34;verbatim&#34;&gt;contextlib.nested&lt;/code&gt; does almost the same thing:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;with contextlib.nested(a(x, y), b(z)) as (A, B):
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    # Do the same stuff&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
the difference being that with the 2.7+ syntax, you can use the value
yielded from the first context manager as the argument to the second
(e.g., &lt;code class=&#34;verbatim&#34;&gt;with a(x, y) as A, b(A) as C:...&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;
If multiple contexts occur together repeatedly, you can also roll them
together into a new context manager:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;import contextlib
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;@contextlib.contextmanager
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;def c(x, y, z):
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    with a(x, y) as A, b(z) as B:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        yield (A, B)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;with c(x, y, z) as C:  # C == (A, B)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    # Do that same old stuff&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
What does all this have to do with testing? I have found that for
complex integration tests where there is a lot of setup and teardown,
context managers provide a helpful pattern for making compact, simple
code, by putting the “context” (state) needed for any given test close
to where it is actually needed (and not everywhere else). Careful
isolation of state helps eliminate bugs and makes code easier to reason about.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Processes vs. Threads for Integration Testing</title>
      <link>http://johnj.com/posts/process-vs-threads/</link>
      <pubDate>Fri, 19 Apr 2013 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/process-vs-threads/</guid>
      <description>&lt;p&gt;
Python has become notorious for being somewhat problematic when it
comes to concurrency. The language supports threads, but performance
is known to be dismal in some cases. In particular, &lt;a href=&#34;http://www.dabeaz.com/GIL/&#34;&gt;as David Beazley
discovered&lt;/a&gt;, when I/O-bound and CPU-bound threads run in the same
program, the GIL performs very badly (worse than if you ran the tasks
one after the other on a single thread/CPU). Alternative approaches
which have become popular are to use asynchronous or event-driven
programming techniques (&lt;a href=&#34;http://twistedmatrix.com/trac/&#34;&gt;Twisted&lt;/a&gt;, &lt;a href=&#34;http://docs.python.org/2/library/asyncore.html&#34;&gt;asyncore&lt;/a&gt;), or to make heavy use of
the &lt;code class=&#34;verbatim&#34;&gt;multiprocessing&lt;/code&gt; module.&lt;/p&gt;
&lt;p&gt;
These wrinkles aside, there are situations where threads in Python are
still very useful. One of these is integration testing of distributed
systems.&lt;/p&gt;
&lt;p&gt;
Imagine you have a distributed system with some 30 (or 3, or 300)
software components running on some cluster. These programs might
interact with a database, with a user via command line or a GUI (Web
or otherwise), and with each other via a messaging or RPC protocol
(XML-RPC, ZeroMQ, …).&lt;/p&gt;
&lt;p&gt;
While low-level (functional, unit) testing will perhaps be the bulk of
your tests, integration tests are important to make sure all the
programs talk to each other as they should. Like your other tests, you
want to automate these. And they should run as fast as possible to
optimize the feedback cycle during development.&lt;/p&gt;
&lt;p&gt;
A straightforward way to test these components is to run them all in
separate programs (locally or distributed), each in their own
process. However, you’re likely to get much better performance from
your many short-running tests if you run the components as local
threads in a single process. The components running in these threads
would, of course, still talk to each other via RPC, ZeroMQ, etc., same
as if they were processes. But for short tests the setup and teardown
for threads is much faster. The most trivial example (assigning a
value to a variabled) shows the difference dramatically:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# in ipython:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;import threading, subprocess
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;doproc = lambda: subprocess.Popen([&amp;#34;python&amp;#34;, &amp;#34;-c&amp;#34;, &amp;#34;&amp;#39;a=1&amp;#39;&amp;#34;],
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                  stdout=subprocess.PIPE).communicate()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;def dothread():
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    def run():
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        a = 1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    th = threading.Thread(target=run)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    th.start()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    th.join()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;time junk = [doproc() for _ in range(500)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# CPU times: user 0.18 s, sys: 1.81 s, total: 1.98 s
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Wall time: 14.30 s
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;time junk = [dothread() for _ in range(500)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# CPU times: user 0.09 s, sys: 0.05 s, total: 0.14 s
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Wall time: 0.16 s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
That’s a factor of about a hundred – something you will most
definitely notice in your test suite.&lt;/p&gt;
&lt;p&gt;
Another advantage of this approach is that, when you write your code
so that it can be run as threads, you can put as many or few of these
threads in actual processes (programs) as you’d like. In other words,
the coupling of processes to components is loosened. Your automated
tests will force you to implement clean shutdown semantics for each
thread (otherwise your test program will likely not terminate without
manual interruption).&lt;/p&gt;
&lt;p&gt;
Finally, it’s much easier to interrogate the state of each component
when it’s running as a thread, than it is to query a subprocess (via
e.g. RPC). This greatly simplifies the assertions you have to make in
your integration tests, since you don’t have to send a message of some
sort via RPC or message queues – you can just query variables.&lt;/p&gt;
&lt;p&gt;
I found, while writing the automated tests in IceCube Live (the
control and monitoring system of the &lt;a href=&#34;https://icecube.wisc.edu/&#34;&gt;IceCube Neutrino Detector&lt;/a&gt;), that
making components that could be instantiated in threads (for testing)
or in processes (for production) greatly sped up my test suite and
simplified the actual tests quite a bit. I should note that, prior to
release, there is still a final integration test done on a mirror test
system which simulates actual data collection and makes sure IceCube
Live can play along with other systems. The mirroring, however, is not
exact, since the actual detector elements we deployed at South Pole
are expensive and rely on a billion tons of crystal-clear ice to work
as intended.&lt;/p&gt;
&lt;p&gt;
In &lt;a href=&#34;http://johnj.com/posts/intro-to-context-managers-in-python&#34;&gt;the next post&lt;/a&gt; we will explore the use of context managers, which
are helpful for organizing setup and teardown of complex tests cases
involving multiple components.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Resources for Learning Clojure</title>
      <link>http://johnj.com/posts/resources-for-learning-clojure/</link>
      <pubDate>Mon, 21 May 2012 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/resources-for-learning-clojure/</guid>
      <description>&lt;p&gt;
I thought I’d take a moment to present one possible path, or set of
alternate paths, for learning Clojure, a modern Lisp implemented on
top of the Java Virtual Machine.&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Update:&lt;/em&gt; Since this was written in 2012, a number of additional
excellent books have come out. These include Carin Meier’s &lt;em&gt;&lt;a href=&#34;http://shop.oreilly.com/product/0636920034292.do&#34;&gt;Living
Clojure&lt;/a&gt;&lt;/em&gt;; Vandgrift and Miller, &lt;em&gt;&lt;a href=&#34;https://pragprog.com/titles/vmclojeco/clojure-applied/&#34;&gt;Clojure Applied&lt;/a&gt;&lt;/em&gt;; and Daniel
Higginbotham’s, &lt;a href=&#34;http://www.braveclojure.com/&#34;&gt;&lt;em&gt;Clojure for the Brave and True&lt;/em&gt;&lt;/a&gt;. These are all great
choices, and &lt;em&gt;Clojure for the Brave and True&lt;/em&gt; is a strong competitor
for the best introductory Clojure book.&lt;/p&gt;
&lt;p&gt;
In addition to a surprising number of very good resources out there
for such a young language, there are resources specific to other Lisps
which map reasonably well onto Clojure.&lt;/p&gt;
&lt;p&gt;
Clojure does have a learning curve, especially for one coming from
imperative languages such as Java, Python, C++, or Ruby. These
languages are, in some ways, more similar to each other than they are
to functional languages such as Clojure (though they all have features
which were pioneered originally in implementations of Lisp, one of the
oldest computer languages).&lt;/p&gt;
&lt;p&gt;
Since the approach I took was somewhat haphazard and I have the
benefit of some hindsight now, I present here a rough sequence which
might make the road a little less bumpy for others. Though not an
exhaustive list of resources by any means, the following diagram
summarizes the discussion points that follows.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/learnclojure2.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/learnclojure2_hu_539b572e992e76c8.png&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
A Flow Chart for Learning Clojure
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
The approach I recommend goes something like this:&lt;/p&gt;
&lt;p&gt;
If you are going to pick just one of these resources to get started, I
recommend the O’Reilly book &lt;a href=&#34;http://www.clojurebook.com/&#34;&gt;Clojure Programming&lt;/a&gt; by C. Emerick
et. al. I have both the PDF and print versions of this book, and it’s
not only an excellent book on Clojure, it’s one of the best O’Reilly
books I’ve seen in the dozen or so years I’ve been reading them. The
other two books are also good (I have not checked out the 2nd edition
of Programming Clojure yet)… Clojure is particularly blessed in having
not just one but at least three excellent “starter books” on the
language.&lt;/p&gt;
&lt;p&gt;
If you’re curious why one might want to learn a Lisp as your next (or
last?) programming language, Paul Graham &lt;a href=&#34;http://www.paulgraham.com/avg.html&#34;&gt;evangelizes&lt;/a&gt; very effectively
about Lisp in some of his many &lt;a href=&#34;http://www.paulgraham.com/articles.html&#34;&gt;essays&lt;/a&gt;. You might want to check those
out before diving into Clojure per se.&lt;/p&gt;
&lt;p&gt;
Additionally, videos of Rich Hickey’s talks, particularly &lt;a href=&#34;https://www.infoq.com/presentations/Simple-Made-Easy&#34;&gt;Simple Made
Easy&lt;/a&gt;, though not so much about Lisp or Clojure per se, explain the
challenges and limitations involved with stateful Object-Oriented
programming and motivate the ideas behind functional programming in
general and Clojure in particular. I very much recommend these videos,
though reaction to them among programmers I’ve shown them to has
varied wildly from enthusiasm to extreme irritation.&lt;/p&gt;
&lt;p&gt;
People with exposure to Common Lisp or Scheme may be familiar with
Abelson and Sussman’s &lt;a href=&#34;http://mitpress.mit.edu/sicp/&#34;&gt;Structure and Interpretation of Computer
Programs&lt;/a&gt;; Friedman’s &lt;a href=&#34;http://www.ccs.neu.edu/home/matthias/BTLS/&#34;&gt;The Little Schemer&lt;/a&gt; and its sequels &lt;a href=&#34;http://www.ccs.neu.edu/home/matthias/BTSS/&#34;&gt;The Seasoned
Schemer&lt;/a&gt; and &lt;a href=&#34;http://www.ccs.neu.edu/home/matthias/BRS/&#34;&gt;The Reasoned Schemer&lt;/a&gt; ; and P. Seibel’s &lt;a href=&#34;http://www.gigamonkeys.com/book/&#34;&gt;Practical Common
Lisp&lt;/a&gt;, which I’ve only peeked at but which has an excellent
reputation. These books could provide a gateway into Clojure, or might
merit a look at once you’ve got some Clojure basics under your belt. I
find them to be interesting supplemental reading.&lt;/p&gt;
&lt;p&gt;
Before getting to the more advanced books, the &lt;a href=&#34;https://github.com/functional-koans/clojure-koans&#34;&gt;Clojure Koans&lt;/a&gt; are a fun
and pleasantly gradual way to start reinforcing your Clojure basics (I
worked most of them on various airplane flights to the South Pole last
year). Similar but somewhat more challenging are the &lt;a href=&#34;https://4clojure.oxal.org/&#34;&gt;4clojure problems&lt;/a&gt;
(I’m about 3/4 of the way through these).&lt;/p&gt;
&lt;p&gt;
I find these kinds of problems alternately soothing (when I get them
right away) and maddening (when I actually have to work at them). They
are like crossword puzzles for programmers, and they do really help
reinforce the material from the books. Due to the way the problems are
implemented, they are unfortunately limited in terms of how they cover
Java interoperability, macros, and concurrency.&lt;/p&gt;
&lt;p&gt;
After you’ve read an introductory text, worked some problems and maybe
started one or two personal projects with the language, you’re ready
for &lt;a href=&#34;http://www.joyofclojure.com/&#34;&gt;The Joy of Clojure&lt;/a&gt;. This book is somewhat hard to describe; I
started it too early, then came back after six months and it made a
whole lot more sense. The best way to explain The Joy of Clojure is
that it helps you to understand both some of the quirks of the
language and what makes it truly great, and will help you evolve from
writing clumsy translations of what you’ve learned in other languages,
to truly compact, elegant, idiomatic Clojure code.&lt;/p&gt;
&lt;p&gt;
After, or perhaps during, Joy of Clojure, take a deep dive into
macros, the secret sauce of Lisp. Macros allow one to implement new
language features in order to make one’s code elegant and expressive,
and to optimize the fit to one’s problem domain. Paul Graham’s &lt;a href=&#34;http://www.paulgraham.com/onlisp.html&#34;&gt;On Lisp&lt;/a&gt;
is mostly about macros; Hoyte’s &lt;a href=&#34;http://letoverlambda.com/&#34;&gt;Let over Lambda&lt;/a&gt; refers to On Lisp many
times and builds on some of the foundations laid in that book.&lt;/p&gt;
&lt;p&gt;
To summarize (strongest suggestions in &lt;strong&gt;bold&lt;/strong&gt;):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Graham essays&lt;/li&gt;
&lt;li&gt;Hickey videos&lt;/li&gt;
&lt;li&gt;Introductory book (&lt;strong&gt;Clojure Programming&lt;/strong&gt;, Programming Clojure, or
Practical Clojure)&lt;/li&gt;
&lt;li&gt;Possibly detour into SICP, Practical Common Lisp and/or The * Schemer books&lt;/li&gt;
&lt;li&gt;Clojure Koans&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;4Clojure Problems&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Joy of Clojure&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;On Lisp&lt;/li&gt;
&lt;li&gt;Let Over Lambda&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are many other Lisp books which I haven’t read yet, as well as a
Clojure book or two I’ve left out. Also, lest I forget, the Clojure
community has a reputation for being extremely welcoming and
helpful. There is a &lt;a href=&#34;http://groups.google.com/group/clojure&#34;&gt;Google Group&lt;/a&gt; / mailing list and an IRC chat as
well.&lt;/p&gt;
&lt;p&gt;
The bottom line is that for such a young language (or young variant of
an old language), we are fortunate to have such a rich selection of
resources to pick and choose from. Enjoy!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Continuous Testing in Python, Clojure and Blub</title>
      <link>http://johnj.com/posts/continuous-testing/</link>
      <pubDate>Sat, 31 Mar 2012 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/continuous-testing/</guid>
      <description>&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/paintbrushes-optional.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/paintbrushes-optional_hu_b8fb8c13dac542c1.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
A separate monitor is handy for showing tests results continuously while working. The paintbrushes are strictly optional.
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
&lt;strong&gt;What follows is a somewhat rambling introduction to continuous, test-driven development, focusing mainly on Python and influenced by Clojure tools and philosophy. At the end, a simple script is introduced to help facilitate continuous TDD in (almost) any language.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
For the last four years I have increasingly followed a test-driven
approach in my development. My approach continues to evolve and deepen
even as some of the &lt;a href=&#34;http://patrick.lioi.net/2011/11/23/guard-rail-programming/&#34;&gt;limits of TDD&lt;/a&gt; are becoming clearer to me.&lt;/p&gt;
&lt;p&gt;
Initially, I had a hard time getting my head around TDD. Writing tests
AND production code seemed like twice as much work, and, even before I
wrote tests, I typically ran the program under development, e.g. with
print statements added, to test each change. But making changes to old
code was always a fairly daunting proposition, since there was no way
to validate all the assumptions I’d checked “by eye” just after I’d
written the code.&lt;/p&gt;
&lt;p&gt;
TDD helps reduce risk by continuously verifying your assumptions about
how the code should perform at any time. Using TDD for &lt;a href=&#34;https://arxiv.org/abs/1612.05093&#34;&gt;a fairly large
project&lt;/a&gt; has saved my bacon any number of times.&lt;/p&gt;
&lt;p&gt;
The basic approach is that the test code and the production code
evolve together more or less continuously, as one follows these rules:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Don’t write any production code without a failing unit test;&lt;/li&gt;
&lt;li&gt;Write only enough production code needed to make the tests pass.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once I started writing tests for all new production code, I found I
could change that code and make it better without fear. That led to
much better (and usually simpler) code. I realized I was spending much
less time debugging; and when there were bugs, the tests helped find
them much faster. As I have gained experience with this approach I
have found that the reliability of, and my trust in, my code written
with TDD is vastly superior than otherwise. The two-rule cycle also
tends to foster simplicity, as one tends to eschew any modifications
that don’t actually achieve the desired objectives (i.e. meet the
goals of the software, as specified formally in the tests
themselves). The process is also surprisingly agreeable!&lt;/p&gt;
&lt;p&gt;
It goes without saying that if you follow this approach you will be
running your tests a lot. The natural next step is to automate this
more. In the book Foundations of Agile Python Development, Jeff
Younker explains how to make Eclipse run your unit tests every time
you save a file in the project. The speed and convenience of this
approach was enough to get me to switch from Emacs to Eclipse for
awhile.&lt;/p&gt;
&lt;p&gt;
Most of my daily programming work is in Python, but I have been an
avid &lt;a href=&#34;http://johnj.com/posts/in-defense-of-hobbies&#34;&gt;hobbyist&lt;/a&gt; in Clojure for several months now. It wasn’t until I saw
Bill Caputo’s preparatory talk for Clojure/West here in Chicago that I
heard the term continuous testing and realized that this is what I was
already doing; namely, the natural extension of TDD in which one runs
tests continuously rather than “by hand.” Bill demoed the expectations
module and the autoexpect plugin for Leiningen, which runs your tests
after every save without incurring the overhead of starting a fresh
JVM each time.&lt;/p&gt;
&lt;p&gt;
(One point Bill made in his talk was that if your tests are slow,
i.e. if you introduce some new inefficiency, you really notice
it. Ideally the tests should take a few seconds or less to complete.)&lt;/p&gt;
&lt;p&gt;
Back to Python-land. Not wanting to be always leashed to Eclipse, and
inspired by the autoexpect plugin, I started looking for an
alternative to using Eclipse’s auto-builders — something I could use
with Emacs or any other editor. There are a lot of continuous build
systems out there, but I wanted something simple which would just run
on the command line on my laptop screen while I edited code on my
larger external monitor. I found &lt;a href=&#34;https://github.com/brunobord/tdaemon/blob/master/tdaemon.py&#34;&gt;tdaemon&lt;/a&gt; on GitHub; this program walks
a directory tree and runs tests whenever anything changes (as
determined by keeping a dictionary/map of SHA values for all the
files). This is most of what I want, but it restricts you to its own
choices of test programs.&lt;/p&gt;
&lt;p&gt;
In a large project with many tests, some fast and some slow, I often
need to specify a specific test program or arguments. For example, I
have a wrapper for &lt;a href=&#34;http://readthedocs.org/docs/nose/en/latest/&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;nosetests&lt;/code&gt;&lt;/a&gt; which will alternately run all my “fast”
unit tests, check for PEP-8 compliance, run Django tests, etc. In some
cases, such as debugging a system with multiple processes, I may need
to do something complex at the shell prompt to set up and/or tear down
enough infrastructure to perform an existing test in a new way.&lt;/p&gt;
&lt;p&gt;
One piece of Clojure philosophy (from Functional Programming,
a.k.a. “FP”) that has been influencing my thinking of late is the
notion of &lt;strong&gt;composability&lt;/strong&gt;: the decoupling or disentanglement of the
pieces of the systems one builds into small, general, composable
pieces. This will make those pieces easier to reuse in new ways, and
will also facilitate reasoning about their use and
behaviors. (Unfortunately, the merits of the FP approach, which are
many, have poisoned my enthusiasm for OO to the extent that I will
typically use a function, or even a closure, before using an object,
which would perhaps be more Pythonic in some cases).&lt;/p&gt;
&lt;p&gt;
So, in the current case under discussion (continuous testing), rather
than making some kind of stateful object which knows about not only
your current file system, but also what tests should be allowed, their
underlying dependencies, etc., it would be better (or at least more
“functional”) instead to simply provide a directory-watching function
that checks a dictionary of file hashes, and compose that function
with whatever test program suits your purposes at the moment.&lt;/p&gt;
&lt;p&gt;
The result of these thoughts is a small script called &lt;a href=&#34;https://github.com/eigenhombre/continuous-testing-helper&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;conttest&lt;/code&gt;&lt;/a&gt; which
is a simplification of &lt;code class=&#34;verbatim&#34;&gt;tdaemon&lt;/code&gt; that composes well with any test suite
you can specify on the command line.&lt;/p&gt;
&lt;p&gt;
Some examples follow:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ conttest nosetests  # Runs nosetests whenever the files on disk change
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ conttest nosetests test.path:harness  # Runs only tests in &amp;#39;harness&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                        # object in path/to/test — handy
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                        # for developing a single feature
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                        # or fixing a single bug.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Check both PEP-8 style and unit tests:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ conttest &amp;#39;pep8 -r . ; nosetests&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
It would work equally well with a different language (“&lt;a href=&#34;http://www.paulgraham.com/avg.html&#34;&gt;blub&lt;/a&gt; language”)
with a separate compilation step:&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ conttest &amp;#39;make &amp;amp;&amp;amp; ./run-tests&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Using this program, depending on my needs of the moment, I can
continuously run a single unit test, all my “fast” unit tests, or, if
I’m willing to deal with slower turnaround times, all my unit and
integration tests.&lt;/p&gt;
&lt;p&gt;
The script is on &lt;a href=&#34;https://github.com/eigenhombre/continuous-testing-helper&#34;&gt;GitHub&lt;/a&gt; for your continuous enjoyment of continuous
testing. May you find it helpful.&lt;/p&gt;
&lt;p&gt;
(Ironically, this script does NOT work that well for JVM languages
like Clojure since the startup time is lengthy (a couple of seconds on
my MacBook Pro). Most of Clojure&amp;#39;s testing frameworks have autotest
capabilities built in, which work great.)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Programming Languages</title>
      <link>http://johnj.com/posts/programming-languages/</link>
      <pubDate>Thu, 22 Dec 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/programming-languages/</guid>
      <description>
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/c17-clojure-koans.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/c17-clojure-koans_hu_461266ccbcb0552c.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Working on Clojure Koans while riding on a C-17, bound for Antarctica
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Today I am inspired to ponder many languages at once and review which
ones I use regularly, which ones I’m curious about, which ones I
avoid, and what I’d like to use, if it were to exist.&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Programming Languages I Use Regularly
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-2&#34;&gt;
Python
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;By far the language I use most for work. I like it for its clean
philosophy, its expressiveness, its “batteries included” extensive set
of libraries, and, first and foremost, for its readability.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-3&#34;&gt;
C
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;Of all the languages I use regularly, C is the one I learned first. I
maintain a large Linux kernel device driver I wrote for the &lt;a href=&#34;http://icecube.wisc.edu/&#34;&gt;IceCube
project&lt;/a&gt; as well as an embedded system written for 5000+ sensors
designed for the same.&lt;/p&gt;
&lt;p&gt;
C now feels like assembly language to me but I still appreciate its
power and elegance.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-4&#34;&gt;
Clojure
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;I have dabbled in Lisp since the 1980s but not seriously until
recently. Somewhat seduced by Paul Graham’s &lt;a href=&#34;http://www.paulgraham.com/avg.html&#34;&gt;essays on Lisp&lt;/a&gt; and
encouraged by a bit of a Lisp renaissance, I have started reading up
on Clojure and working through problems on &lt;a href=&#34;https://4clojure.oxal.org/&#34;&gt;4clojure.com&lt;/a&gt;. While not
without its warts, I like many things about Clojure, including the
Lisp “code-as-data” philosophy, availability of macros (something I
wish Python had) and its interoperability with Java classes. While I
doubt I’ll be able to use this in my paying work any time soon, I have
started playing with Clojure for personal projects. Having to deal
with significantly concurrent systems in my work, I am intrigued by
functional programming, as opposed to the usual object-oriented
approaches where state is king and &lt;a href=&#34;https://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html&#34;&gt;where tangled hierarchies of
relatively meaningless relationships&lt;/a&gt; can obscure intent.  Clojure
takes an interesting approach, with its emphasis on immutability,
software-transactional memory and other concurrency primitives.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-5&#34;&gt;
Bash / Unix Tools
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;It amuses me slightly to include Bash here, but combining simple
iteration with conditional statements and adding basic Unix concepts
and tools such as pipelines, &lt;code class=&#34;verbatim&#34;&gt;grep&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;awk&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;sed&lt;/code&gt;, &lt;code class=&#34;verbatim&#34;&gt;wc&lt;/code&gt;, etc. is
surprisingly powerful. Every small Bash trick or new tiny-Unix-tool I
learn seems to eliminate the need for some number of actual programs,
at least for quick-and-dirty work. The results tend to be obscure and
hard to parse; if I can do something in a single line of bash, I will;
otherwise I’ll resort to Python for most things.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-6&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-6&#34;&gt;
Javascript / Coffeescript
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-6&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;Not my favorite language by any stretch, but you can’t avoid it if
you’re working in the browser (I don’t consider closed-source Flash an
option). The language has a lot of warts, but some &lt;a href=&#34;http://shop.oreilly.com/product/9780596517748.do&#34;&gt;good parts&lt;/a&gt; too. I
can feel the Lisp bones deep underneath the surface of the language
when I dive into JavaScript. CoffeeScript is sweet because it’s so
much more readable and offers protection from common JavaScript
gotchas, but has &lt;a href=&#34;http://lucumr.pocoo.org/2011/12/22/implicit-scoping-in-coffeescript/&#34;&gt;some flaws of its own&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-7&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-7&#34;&gt;
Programming Languages I Have Used in the Past but Tend to Avoid
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-7&#34; class=&#34;outline-text-2&#34;&gt;
&lt;div id=&#34;outline-container-headline-8&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-8&#34;&gt;
Perl
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-8&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;I fell in love with the power of Perl (“the duct-tape of the
Internet”) back in the 1990s, but now dislike its strange, ad-hoc
syntax and the relative inscrutability when compared to Python.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-9&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-9&#34;&gt;
Java
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-9&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;I haven’t done a ton of Java development, but have done enough to be
irritated by certain things about it: its extremely verbose syntax,
strict typing, distance from the actual hardware, and lack of (at
least until now) anonymous functions (“lambda”). Also the JVM startup
time is irritating, a problem Clojure inherits from Java (though &lt;a href=&#34;https://github.com/ninjudd/drip&#34;&gt;there
are workarounds&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;
Java has become so ubiquitous, however, that it’s hard to avoid, and
it does have a certain self-consistent habitability to it. I think
current JVM languages such as Clojure and Scala will only strengthen
the role of Java and the JVM in modern computing, unless Oracle
massively screws things up.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-10&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-10&#34;&gt;
C++
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-10&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Another language I’ve played with a bit. A language that splits the
difference between C and Java (I realize C++ came before Java); I
would prefer to write in a “real” higher level language and glue C in
where needed.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-11&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-11&#34;&gt;
FORTRAN
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-11&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;I’m sorry to say that, coming from physics, I’ve written more FORTRAN
code than I care to admit. I find it interesting, however, that while
Lisp and FORTRAN are almost the same age, Lisp still holds interest
where FORTRAN does not (except to pure number-crunchers, due to
ancient and venerable numeric libraries).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-12&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-12&#34;&gt;
Languages I’m Curious About But Haven’t Had Time to Look At Much
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-12&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;Exposure to purely functional programming and lazy evaluation in
Clojure made me curious about Haskell.&lt;/p&gt;
&lt;p&gt;
I am curious about Erlang, which is supposed to have excellent
concurrency features.&lt;/p&gt;
&lt;p&gt;
I saw some talks about Go at OSCON. Go looks like it has some really
nice features compared to C (compilation speed, concurrency support,
and improved readability), but it may be a bit low-level for my
interests.&lt;/p&gt;
&lt;p&gt;
I have only tinkered with Objective-C, but that is the language of
choice for serious Mac OS X or iOS development. Its syntax looks
pretty odd, but perhaps that’s a small price to pay for running on all
that pretty hardware.&lt;/p&gt;
&lt;p&gt;
Purely logical languages such as Prolog (equivalents of which can be
easily implemented in Lisp) are of interest for their ability to
process large amount of semantically-related content. I’m curious
about expert systems, ontologies, the Semantic Web, and many other
related areas of AI research.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-13&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-13&#34;&gt;
The Language I Wish Existed
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-13&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
The perfect language would:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Be very readable, like Python (whitespace or other visual cues
probably playing a significant role)&lt;/li&gt;
&lt;li&gt;Support full Lisp-like macros (“homoiconicity”)&lt;/li&gt;
&lt;li&gt;Have very broad library support (Python, Java, …)&lt;/li&gt;
&lt;li&gt;Have built-in features in support of test-driven development
(Python’s doctests and Clojure’s :test metadata seem like just the
beginning of what might be possible)&lt;/li&gt;
&lt;li&gt;Handle concurrency very well (Clojure, Erlang, … but not Python)&lt;/li&gt;
&lt;li&gt;Run in the browser, or be implemented efficiently on top of
JavaScript&lt;/li&gt;
&lt;li&gt;Allow you to get very close to the machine if necessary, or at
least the bytecodes of the virtual machine or interpreter (Python,
C, C++, …)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Points 1-3 are the most important to me. Resolving the tension between
points 1 and 2 is of particular interest.&lt;/p&gt;
&lt;p&gt;
I doubt such a language will come along any time soon. But I’m taking
&lt;a href=&#34;http://www.dabeaz.com/chicago/compiler.html&#34;&gt;a class next month&lt;/a&gt; which, who knows? … might help someday.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Milvans and Container Malls</title>
      <link>http://johnj.com/posts/milvans-and-container-malls/</link>
      <pubDate>Fri, 02 Dec 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/milvans-and-container-malls/</guid>
      <description>&lt;p&gt;
Dec. 2, 2011, 08:10 NZDT Tranz Coastal train from Christchurch to Picton&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6443326759_c11f631340_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6443326759_c11f631340_o_hu_4d2846fc21a1a2c9.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Observatory Hill in McMurdo
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6443344379_31d9172afc_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6443344379_31d9172afc_o_hu_7f7034694902e9c4.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
The new Cashel Mall in Christchurch
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Another gorgeous summer day here as the countryside rolls by: grassy,
green hills punctuated by trees passing singly and in groups, as well
as cattle, horses, and the ubiquitous sheep, which appeal strongly for
some reason today, signaling tranquility, domesticity… humans living
in pastoral harmony with the land. Icebreaker, perhaps my favorite
clothing brand, puts tags on their merino wool clothes, each with a
unique code you can type into their Web site to find out which sheep
farm in New Zealand your woollen item comes from. I wonder if I’ll
pass the farm that made the wool in the shirt I’m wearing. It’d be
nice they would sell the sheep as well from their Web site. Or maybe
even whole farms….&lt;/p&gt;
&lt;p&gt;
I’m on my habitual route from Christchurch to Wellington to see
friends Neil and Amelia for a few days before heading back to
Chicago. The usual blue, slightly creaky train cars have been upgraded
to sleek new tan-colored ones with power outlets under the seats,
bigger windows and a quieter ride — overall, an improvement. Flying
would take one-tenth the time but I’m spending enough time on
airplanes, and at any rate the scenery is quite gorgeous, an antidote
to both the polar plateau and the coming Chicago winter.&lt;/p&gt;
&lt;p&gt;
I had just over a full day in Christchurch. As with the Elms hotel on
the way down, the Pavillions was a disappointment. Expensive WiFi and
rooms, noisy, with somewhat cheesy decor. Paying for WiFi is
particularly irksome since it I know how cheap it is to implement — it
feels like paying for tap water, by the cup. However, beggars cannot
be choosers and the hotel situation in Christchurch is dismal after
the February quake.&lt;/p&gt;
&lt;p&gt;
The advantage of the Pavilions is that is it relatively close to
downtown. Had a big breakfast yesterday at a nearby cafe, and an
interesting conversation with a friendly fellow diner who is very into
meditation and marathoning and was accompanying a group of kids coming
out of some month-long South Island adventure. Then I trotted down
Victoria Street into the downtown area. Much is still fenced off so I
had to circumambulate a couple-block area in various stages of
demolition. Eventually I found myself on Armagh street staring at a
familiar sign, that of the Winsor hotel, the first place I ever stayed
in New Zealand. The familiar building, however, is gone, replaced by a
generic looking construction-in-progress. Half a block closer to
downtown, the Devon, my favorite place to stay, is completely gone,
recognizable only by the fence behind the original parking lot. It’s
all parking lot now. One thing to be said about Christchurch is that,
on average, you can see farther now.&lt;/p&gt;
&lt;p&gt;
I’ve laid down a lot of pre- and post-Antarctic memories in these
places so it was a blow to see them gone… gone so completely that it
was hard to even tell where they’d been. Certainly a vivid
illustration of the impermanence of things. Walking back towards the
hotel I was snatched up by IceCube colleagues driving by: Stephanie
and Anthony from Canterbury University. We were joined by Sarah at a
combination cafe and garden store, where I had a delicious salad
(still making up for polar freshie deficit) and “chocolate ice” (a
sort of shake made with chocolate and whipped cream). After lunch we
drove downtown to the new Cashel Mall, an area that was hit so hard
that no original buildings remain. Instead, a few dozen structures
made of shipping containers occupy a roughly one block area, serving
as a new shopping mall. This sounds dubious on paper but in execution
it was, like many things New Zealand, fabulously gorgeous and chic —
imagine FEMA as tutored by hip architects gunning for a multi-page
spread in Dwell Magazine. Walked back alone past the Christchurch art
gallery, the Arts Centre, and the Dux De Lux, all still closed. Then
through the Botanic Garden, in full bloom and betraying no evidence of
seismic calamity, and “home” for Thai dinner and an early bedtime to
prepare for the early morning departure of the train.&lt;/p&gt;
&lt;p&gt;
Christchurch and McMurdo seemed to lift me out of my slightly numb
South Pole funk. In McMurdo, I felt some of the thrill towards the
gritty texture of the town I used to experience each time I came
down. Much of that texture has been bypassed in recent trips because
they were straight-throughs, landing at Pegasus only to change planes.&lt;/p&gt;
&lt;p&gt;
My roommate in McMurdo was Bill, a kindly videographer from Chicago
who’s lived in Louisiana long enough to acquire the Southern
drawl. Bill said out of the blue, “It really is the simple pleasures
down here which make life worth living.” A couple of showers and
salads and nine hours of sleep, concurrent with continual
re-saturation in oxygen, and I was inclined to agree. By Wednesday
morning, I had enough time and energy to walk to Hut Point and summit
Ob Hill before lunch, taking lots of pictures of “milvans” (shipping
containers), buildings, and rock and ice along the way. At Hut Point I
sat for awhile with eleven seals sunning themselves nearby on the ice,
some the size of small Chevies. Trails from the seals to nearby holes
in the ice which looked far too small to accommodate the animals… and
some blood stains near one of these were a reminder that this was not
a sanitized game park but actual habitat, with life and death
coexisting precariously as always… perhaps more so, at the base of
Mount Erebus (whose volcanic plume could be seen in the clear,
continual daylight), there on the edge of the highest, windiest,
driest, coldest, iciest, emptiest, cleanest, darkest, quietest
continent.&lt;/p&gt;
&lt;p&gt;
At lunch I met a longtime colleague Ryan, waiting for his LC-130 ride
to Wais Divide. Ryan went to the Pole as an undergraduate on AMANDA,
years before I did, and now he does mostly glaciology and climate
studies at UC Berkeley, logging dust concentrations as a function of
depth in deep holes across Antarctica. We talked about deploying to
the Ice over and over again. His perspective interested me. “It’s a
nice break from your routine, back up North. And you come back
stronger each time.” I thought about it for a bit, and I think I
agree. As one gets older it is easy to get into a comfortable routine
— I have a really good life in the North: Eden, meditation, art, work,
Chicago, Madison, family and friends. But the months do speed by, and
deviations from routine seem more and more jarring. Traveling does
break you out of that. Even simple things like remembering what needs
to be done without relying on a computerized to-do list seem easier
after a few weeks of having to keep track of gear, travel dates, and
ever-changing circumstances.&lt;/p&gt;
&lt;p&gt;
I had time for a nap before reporting to the Movement Control Center
for the flight to Christchurch. Eighteen of us packed our gear and
selves into a Delta and headed out to the Ice Runway, one of the last
flights to do so this season (flight operations transition to Pegasus
airfield as of today, considerably farther away from town). Despite
the quick trip to the plane, we wound up spending a good hour parked
nearby, while the back of the Delta gradually turned into a
greenhouse, cooking us in our ECW gear until we opened, against strict
instructions not to, the back door of the vehicle to let in some cool
air. Finally we made it on board and got a good look at the cause for
delay — two empty liquid helium dewars, each the size of a small
school bus, which no doubt were tricky to tie down correctly (I, for
one, was happy for the extra attention to detail on the matter).&lt;/p&gt;
&lt;p&gt;
Eighteen passengers is a pretty light manifest for a C-17. After
takeoff some people took several seats along the side walls and
managed to sleep that way for most of the five hours to
Christchurch. I was perhaps the only one to mosey up to the flight
deck. Talked with one of the pilots for awhile, who said he’d been to
55 countries since he started flying in his squadron. Most commonly
Iraq and Afghanistan, of course, but also frequently to Southeast Asia
— they are apparently still finding remains of American soldiers in
Vietnam (DNA techniques being the evident game-changer there), and
aren’t above sending C-17s down to collect them, with appropriate
ceremony, one assumes.&lt;/p&gt;
&lt;p&gt;
We’re pulling into Kaikoura now, so I’m going to tie this off for
today and get a breath of fresh air. Already saw some seals in the
water from the train. Liquid water, as far as the eye can see… what a
strange and marvelous improvement, over an ocean of ice.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6444387801_6c5182651d_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6444387801_6c5182651d_o_hu_ff27fcaa13248371.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
New train in Kaikoura
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6444387113_dda21c553c_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6444387113_dda21c553c_o_hu_16f6bcf420a85e5b.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Marlborough Sounds
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Oxygen</title>
      <link>http://johnj.com/posts/oxygen/</link>
      <pubDate>Tue, 29 Nov 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/oxygen/</guid>
      <description>&lt;p&gt;
Nov. 29, 2011 17:30 NZDT Crary Lab, McMurdo Station&lt;/p&gt;
&lt;p&gt;
Made it back to McMurdo where liquid water runs in the streets,
mountains can be seen in all directions, helicopters take off and land
every twenty minutes or so, and the oxygen flows thick and warm into
your lungs.&lt;/p&gt;
&lt;p&gt;
Our flight to McMurdo had only five passengers. After packing a lunch
and waiting with bated breath for the announcements from Comms
indicating the plane’s arrival, I headed out, with Carlos, Sven, Ralf,
Gary, Martin and David coming out as well to say farewell (thanks
guys!). We took a few group photos in various combinations of cameras
and individuals, and then those of us who were leaving headed onto the
plane. There were no instructions of any kind from the crew (indeed,
it would be hard to hear anything anyways)… just strap in and off
you go… and so, in a few moments, we were aloft over the Polar
Plateau.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6422979267_2b61220836_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6422979267_2b61220836_o_hu_a592df095814d12e.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Leg room
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
I managed to sleep a bit after take-off (I’ve been up since 4 AM),
slumped over and wrapped up in Big Red, with no shortage of leg room
(the plane was nearly empty). Read a bit, ate my makeshift
burrito-and-cookie lunch, and then took pictures out the windows for
45 minutes or so.&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/6422995953_8e45ab7e42_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6422995953_8e45ab7e42_o_hu_17b9ff56f1013588.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/6422989141_acf68b71ca_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6422989141_acf68b71ca_o_hu_d3774101a03c855c.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/6422985897_e5090d61fa_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6422985897_e5090d61fa_o_hu_a31c6c7f04564b4a.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/6422982013_2715577de7_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6422982013_2715577de7_o_hu_be885d1787987163.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/6422977967_c4ec0dd7ce_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6422977967_c4ec0dd7ce_o_hu_ca3d937e4073d5a5.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/6422968995_25b2447c7f_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6422968995_25b2447c7f_o_hu_4ea18f7d24d707fe.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/6422962887_5d76a53ca2_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6422962887_5d76a53ca2_o_hu_9fbdac8af98fc9ec.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/6422971347_88e7fdb6d1_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6422971347_88e7fdb6d1_o_hu_3916fd7832531875.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
After ten trips here, one thing I do not tire of or take for granted
is the view from the plane of the Trans-Antarctic mountains. As a
Midwesterner I have always found mountains to be a bit alien and
fascinating, but mountains in Antarctica are ever more so. I think
I’ve probably taken the same photos of the same features over and over
again, but the terrain is stunning. It feels like looking down from
orbit onto another planet — a land you know you will never set foot
upon (and, in many spots, nor will anybody), but you cannot help but
wonder what it would be like to see it up close.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6422999397_374ece43ca_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6422999397_374ece43ca_o_hu_a5268d6e10e2bc40.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Arriving in McMurdo
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
We arrived in McMurdo to a buzz of activity. There was a mass casualty
drill just before we arrived; they are also packing up the Ice Runway
in preparation to move out to Pegasus airfield, much further away from
town. We had to wait for a shuttle into town for half an hour or
so. When the shuttle did arrive, both passengers and crew from South
Pole piled on, as well as other airmen, and crew and passengers from a
Twin Otter flight arriving from somewhere out in that aforementioned
crazy terrain. I had to ask around to figure out where I would be
staying the night — finally I found my room, got some linens, headed
off to Crary Lab for Internet access and now am about to head off to
the dining hall for dinner. Tonight we weigh in with our bags and gear
and should get the flight schedule for the trip back to Christchurch
tomorrow.&lt;/p&gt;
&lt;p&gt;
Starting tomorrow, hopefully, I am going to get spoiled with a week of
summer before heading back to the beginning of Chicago winter. But
first, dinner.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Ghost</title>
      <link>http://johnj.com/posts/ghost/</link>
      <pubDate>Mon, 28 Nov 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/ghost/</guid>
      <description>&lt;p&gt;
Nov. 28, 2011 15:51 NZDT B2 Science, Amundsen-Scott South Pole Station&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6409663069_e0d5f29e97_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6409663069_e0d5f29e97_o_hu_9194b1776fc084c5.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Walking home
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Last full day here, &lt;em&gt;insh’Allah&lt;/em&gt;. We had flights today, so whatever
weather problems were plaguing McMurdo seem to have sorted themselves
out. I’m ready to leave, despite the short and comfortable trip
(relatively speaking). So far on this trip, unlike some previous
trips, I have not had to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go to Medical for assistance with altitude/sinus/cold/flu issues
(roughly 1/3 of trips)&lt;/li&gt;
&lt;li&gt;Work outside for 16-20 hrs straight (AMANDA deployments, ’97, ’98,
’00)&lt;/li&gt;
&lt;li&gt;Give an impromptu presentation or tour to Distinguished Visitors or
&amp;#39;tourists’ (&amp;#39;08 at least)&lt;/li&gt;
&lt;li&gt;Implement software without which IceCube would not be able to take
data (&amp;#39;05, ’06, ’07)&lt;/li&gt;
&lt;li&gt;Prototype a brand-new Experiment Control system in situ (&amp;#39;08)&lt;/li&gt;
&lt;li&gt;Sleep in Summer Camp (&amp;#39;97, ’98, ’00, ’05)&lt;/li&gt;
&lt;li&gt;Try and sleep during daytime through fire alarm testing (&amp;#39;07 at
least)&lt;/li&gt;
&lt;li&gt;Wait due to flight cancellations in McMurdo or Christchurch (knock
on wood)&lt;/li&gt;
&lt;li&gt;“Boomerang” (have flight turn around, a relatively common occurrence
which I have so far avoided) (” “)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is going to be short because I have to go pack. No satellite
connection to the real world anyways at the moment.&lt;/p&gt;
&lt;p&gt;
21:54 NZDT Greenhouse&lt;/p&gt;
&lt;p&gt;
Now it’s a few hours later. Having cleaned out my room and packed,
eaten paella and bread pudding in the galley, dropped in on Pole Mart
(the Station store), chatted for awhile in B2 and watched two episodes
of Firefly in the video lounge, I’m headed now to bed but am first
making a slow farewell circuit of the Station — possibly the last one
“for awhile” (let’s leave it at that). After hitting the sauna for a
few minutes (yes, there is a real cedar sauna in the Station), I’m
sitting on a couch in our tiny greenhouse, to write and read a bit for
a few minutes before bed.&lt;/p&gt;
&lt;p&gt;
Leaving is always bittersweet, but differently so now. As I was
sitting in the sauna I realized that, having said my goodbyes so
thoroughly in January, I feel a bit ghost-like here, like someone who
needs to move on but hasn’t yet for some reason or another. It’s a
feeling I think I need to take seriously, regardless of what happens
in the future.&lt;/p&gt;
&lt;p&gt;
I think that’s all I have to say for tonight. We shall see what the
trip North brings tomorrow.&lt;/p&gt;
&lt;p&gt;
Update Nov. 29, 08:24 NZDT B2: Plane from/to McMurdo is en route, so
my next post will be from there or Christchurch….&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6420413403_793856218e_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6420413403_793856218e_o_hu_5f93222dc6c72bf1.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Today&amp;#39;s Flight Schedule
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Turkey, Stuffing, Eclipse</title>
      <link>http://johnj.com/posts/turkey-stuffing-eclipse/</link>
      <pubDate>Sun, 27 Nov 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/turkey-stuffing-eclipse/</guid>
      <description>&lt;p&gt;
Nov. 27, 2011 18:37 NZDT B2 Science, Amundsen-Scott South Pole Station&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6409662185_e4ee9b57de_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6409662185_e4ee9b57de_o_hu_8519974dc18ae93c.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
The iClipse
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Interesting last couple of days. Friday (two days ago, for us) we had
a partial solar eclipse, my second here. Whereas two years ago I
traipsed outside with colleagues to take pictures, this time I stayed
in the Galley where a viewing party formed. Aside from being much
warmer and cozier, this also turned out to be a good move because,
while nearly perfect for every other photographic task, my little
Canon S95 was not up to direct shooting of the event; a big DSLR with
a telephoto lens (and a mylar partially-silvered filter) is really
needed to do justice to a direct exposure.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6409654435_3a9a41aacd_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6409654435_3a9a41aacd_o_hu_ec2d747225e6ea4.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
That&amp;#39;s a nice eclipse you&amp;#39;ve got there, ma&amp;#39;am….
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6409656051_911798d607_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6409656051_911798d607_o_hu_338316f6cde753f9.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
70% totality
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6409657993_de35029e94_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6409657993_de35029e94_o_hu_ae2cd5968649ad1d.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Getting just a little bit closer to that eclipse
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Fortunately, one scientist set up a pair of binoculars in reverse atop
a tripod, projecting the image of the sun on a cardboard box on an
adjacent table for convenient viewing and photographing. This was cool
even before the eclipse started, since you could see sunspots on the
projected image. The eclipse got to about 70% of totality, during
which the snow outside turned the same liquid-silver-grey colors I saw
here two years ago during the last eclipse. Quite beautiful and a
little eerie. The viewing turned into quite a gathering, with maybe
fifty or so people turning up. A few die-hards also went outside to
view the mercurial snowscape up close and personal.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6407070975_fcec17939c_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6407070975_fcec17939c_o_hu_e889baef14d5e454.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Carlos and Julie at Thanksgiving
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Yesterday, finally, was “Thanksgiving,” or Thanksgiving dinner at any
rate, two days after the official date — my first major holiday meal
at the Pole. Nearly the entire station turned out for appetizers,
followed by dinner, in three separate seatings (most of us IceCubers
took the 2nd). The galley windows were blocked off by screens, and lit
candles adorned the tables — probably the first open flames I’ve ever
seen at the ever-so-fire-safety-conscious South Pole. Rather than
displaying information about how cold it was outside or the day’s
flight cancellations, the overhead monitors showed images of
flickering fireplaces. It was downright cozy, I have to say, and we
had a fabulous meal:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Turkey&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Smoked&lt;/li&gt;
&lt;li&gt;Roasted&lt;/li&gt;
&lt;li&gt;Fried&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Mashed potatoes&lt;/li&gt;
&lt;li&gt;Sweet potato medley (probably kumara from New Zealand – tasty)&lt;/li&gt;
&lt;li&gt;Stuffing&lt;/li&gt;
&lt;li&gt;Gravy&lt;/li&gt;
&lt;li&gt;Cranberries&lt;/li&gt;
&lt;li&gt;Fresh salad with REAL tomatoes and REAL cucumbers&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Pie with whipped cream&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pumpkin&lt;/li&gt;
&lt;li&gt;Walnut&lt;/li&gt;
&lt;li&gt;Apple&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Red and white wine&lt;/li&gt;
&lt;li&gt;Other great stuff which my food coma has forced me to forget&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6407102987_04bf7f7558_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6407102987_04bf7f7558_o_hu_dde4a4563217d70a.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Dinner is served
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
After our seating, several of us stayed to help out with the next. I
served wine and pie for an hour or so, then helped with the dishes. It
really felt like a community effort, with so many people helping, from
the kitchen staff who clearly had worked hard for days, to Katie the
station manager making sure the place settings were correct, to
several wine-n-pie servers. Fun, also, to do physical work with other
people — while bustling to and fro, pouring wine, busing tables, and
cleaning plates, I remembered taking pleasure in moving quickly, with
purpose, with others, in my restaurant job days (so many years ago
now).&lt;/p&gt;
&lt;p&gt;
Today was fairly quiet, with much of the station recovering from
dinner and the follow-on parties (which I mostly skipped, creeping
back to my room and watching Avatar on my laptop before conking
out). But the friendly communal feeling still hangs in the air, a
feeling I will miss when I head North in two days… something I am
nevertheless very much looking forward to doing (weather and
mechanical gods permitting).&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6407069257_c6f69428e8_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6407069257_c6f69428e8_o_hu_389909921f3362e9.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Serving wine at the third seating
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Wind Storm and Moon Dust</title>
      <link>http://johnj.com/posts/wind-storm-and-moon-dust/</link>
      <pubDate>Fri, 25 Nov 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/wind-storm-and-moon-dust/</guid>
      <description>&lt;p&gt;
Nov. 25, 2011 15:32 NZDT B2 Science, Amundsen-Scott South Pole Station&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6396999069_412f0e7463_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6396999069_412f0e7463_o_hu_cb066b8b37bd1376.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
The &amp;#34;South Pile&amp;#34; in windstorm
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
For those of you who don’t know, December and January are the
centennial anniversaries of Amundsen and Scott’s arrival at the South
Pole, respectively. I think a lot of people are writing online about
the event, and at any rate, I’m going to miss the celebration here, so
I won’t go too much into the preparation and planning that’s being
done to prepare for a record number of &amp;#39;tourists’; but it is
interesting to contemplate the history a bit and to think about how
comfortable it is here compared to what Amundsen and Scott went
through.&lt;/p&gt;
&lt;p&gt;
Today we received an email &amp;#39;status report’ of where Amundsen and Scott
were about this time one hundred years ago. Amundsen recorded that the
dogs were doing well and that he had pitched his tent in the most
beautiful campsite in the world. Scott wrote, “quite the most trying
march we’ve had…. If it were not for the surface and bad light, things
would not be so bad. There are few sastrugi and little deep snow. For
the most part men and ponies sink to a hard crust some 3 or 4 inches
beneath the soft upper snow…. Our forage supply necessitates that we
should plug on the 13 (geographical) miles daily under all conditions,
so that we can only hope for better things. It is several days since
we had a glimpse of land, which makes conditions especially gloomy. A
tired animal makes a tired man, I find, and none of us are very bright
now after the day’s march, though we have had ample sleep of late.”&lt;/p&gt;
&lt;p&gt;
Other interesting tidbits on Thanksgiving Day (in the States, anyways
— it’s Friday here): there is a partial solar eclipse this evening at
about 6:30. Unfortunately it is cloudy and windy here and you cannot
even see the horizon. Yesterday is was even windier. We have not had
flights for three days or so because of the weather here and in
McMurdo.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6397008155_f99c2a8a07_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6397008155_f99c2a8a07_o_hu_402214d1d9451b10.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Halo in windstorm
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Last night I went to the greenhouse to read a bit before bed. I’ve
learned that it’s OK to be in there when the greenhouse guy is
working, so I didn’t clear out when he came in. He introduced himself
as Jon and we talked for quite awhile. We both agreed that one of the
best things about coming to Antarctica is meeting all sorts of really
interesting people and learning about what they do, but Jon himself
personifies that very phenomenon. He explained in fascinating detail
about the greenhouse, its control systems and its yearly cycle of
operation. In the winter, it produces enough veggies for one salad per
person each week (!). But what I found most interesting is that he
also studies greenhouse designs for possible lunar and Martian
habitats. Did you know that there are recent indications that the dirt
on Mars is extremely toxic, which could severely impact the
possibility for creating long-term habitations there? That the
International Space Station has (or has had) a small greenhouse that
revolves around an axis to create simulated gravity for plants? Or
that the lunar south pole contains lots of water ice and is possibly
the coldest place in the solar system? He has also touched (studied)
moon dust — I dare say a lot more people have been to the South Pole
than have touched objects from the moon.&lt;/p&gt;
&lt;p&gt;
Today I’m feeling a bit under the weather, perhaps due to something in
the food not agreeing with me. But I have less than four days to go,
the winter-overs are doing well, and I’m eager to start heading back
northwards. The weather will have to clear up first, however!&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6397005637_97b2fdd110_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6397005637_97b2fdd110_o_hu_fc45ad6bf4473919.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Ceremonial Pole from B2
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6397004085_29c7e595ea_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6397004085_29c7e595ea_o_hu_cacbb9b6562e0532.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Sven and David
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Shower Instructions</title>
      <link>http://johnj.com/posts/shower-instructions/</link>
      <pubDate>Wed, 23 Nov 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/shower-instructions/</guid>
      <description>
&lt;p&gt;
Nov. 23, 2011 14:53 NZDT B2 Science, Amundsen-Scott South Pole Station&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6386963581_f3e180f980_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6386963581_f3e180f980_o_hu_11a54e344a329f5a.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Forlorn Slippers
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
How to take a twenty second shower
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
First, work up a sweat in the gym or the sauna. Change out of all
clothes except flip flops (you might want to go into the bathroom
first). Turn water temperature to maximum heat without turning on
water yet. Get towel, soap, washcloth and shampoo ready.&lt;/p&gt;
&lt;p&gt;
Apply water to washcloth for 1/2 second, then turn off shower
immediately. Wet hair and dampen body. Apply shampoo to hair and
lather. Rub end of soap on towel to get it soapy. Rub soapy towel
across entire body and scrub with towel.&lt;/p&gt;
&lt;p&gt;
Step into shower and turn on water. The first five or six seconds of
water will be COLD. Use this to rinse hair. As the water warms, rinse
off the rest of your body. It only takes a few seconds to get the soap
off (short hair is definitely an advantage here). If the water gets
too hot either turn off the shower and get out or turn the heat down
for the last five seconds.&lt;/p&gt;
&lt;p&gt;
Dry off and enjoy that clean feeling.&lt;/p&gt;
&lt;p&gt;
Busy last few days. My departure time has been moved forward by two
days, so I’m pushing a little harder to get through all the training
exercises I came up with for the WOs, as well as helping out with some
software upgrades on our servers. My ragged sleep schedule is back,
but I’m in pretty good spirits today. I’m also keeping busy in my free
time, going to the gym, reading a novel (“Surface Detail”) left here
by ex-WO Freija, listening to Neal Stephenson’s REAMDE, learning a new
programming language (Clojure), and have started writing a book of my
own….! (Don’t hold your collective breaths, it’s going to be awhile.)&lt;/p&gt;
&lt;p&gt;
Thanksgiving is on Saturday here. That’s Friday for most of you; I
suppose the reason for the delay is to avoid having to give people an
extra day off (as far as I can tell, non-scientists here get one
weekend day off per week; scientists take off when they want, which is
usually never). That may seem unreasonable but if people take time off
there are no flights, no cargo, no meals, etc. — it costs a lot to
keep people here so I guess it makes sense to use that time as
productively as possible. Thanksgiving and Christmas are a big deal at
the Pole (I’ve heard). There are three seatings, the second one of
which I signed up for, as well as dish duty afterwards. I like washing
dishes here — it’s an excuse to plunge your hands into warm water
(compare with shower instructions, above) and move around after a day
sitting at the computer.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6386957897_2d330c3a6d_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6386957897_2d330c3a6d_o_hu_f33b98aaf23050c.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Gary prepares to meet the plane
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6386951345_cddebd34db_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6386951345_cddebd34db_o_hu_3533542b7e322c2b.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Off-roading it
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Fresh Air and Bananas</title>
      <link>http://johnj.com/posts/fresh-air-and-bananas/</link>
      <pubDate>Sun, 20 Nov 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/fresh-air-and-bananas/</guid>
      <description>&lt;p&gt;
Nov. 20, 2011 12:49 NZDT B2 Science, Amundsen-Scott South Pole Station&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6365794001_05c4abce37_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6365794001_05c4abce37_o_hu_2e76aca345d0b808.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Peek-a-boo with the Ceremonial Pole
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Sunday here, so a light work day. Station has been pretty quiet all
day. Slept a solid 8 hours, had a banana and oatmeal for breakfast,
then suited up and went out for a walk. It’s funny, yesterday morning
I had a dream about bananas, and then the first bananas showed up
on-station. I’m eating one now (hi Dad!).&lt;/p&gt;
&lt;p&gt;
If you don’t go outside you forget how amazing it is out there. You
get to feeling like you are living on a cross between a cruise ship
(comfy and isolated) and an aircraft carrier (not so comfy but still
isolated). We are indeed floating on an ocean… a solid one. But the
solidity of the water doesn’t always make it easier to get out and
about, if you’re sleeping on station and your duties don’t take you
outside.&lt;/p&gt;
&lt;p&gt;
Get out, though, and it’s another story. The air is cold, yes (100
degrees colder than inside the station) but it is fresher than any
most other air you could conceivably breathe — the cleanest air in the
world, they say. When you walk, the snow squeaks like styrofoam. It
actually sounds hollow and had me wondering if it was at all possible
to encounter crevasses at this part of the Polar Plateau. After
several days of crystal-clear skies, there are a few clouds, doing
their usual it’s-so-cold-and-flat-here-let’s-also-do-the-flat-thing
thing. Nearby, the power plant belches a steam cloud the size and
speed of about one Graf Zeppelin flying away every ten seconds.&lt;/p&gt;
&lt;p&gt;
Went out to the Geographic and Ceremonial Poles just to say hi and
look around. I have been noticing that the horizon here is not
strictly flat — there is a slight rise between the end of the skiway
and the Clean Air building, which is easy to see if you look for it
from the Galley, and still noticeable from the Pole markers. What
passes for terrain is a barely visible inflection of an otherwise
perfect horizon.&lt;/p&gt;
&lt;p&gt;
Went to the gym and did some stretching, sat, and just got back from
brunch. In short, between some fresh fruit, a couple of good night’s
sleep, and a stroll, I’m in better spirits today. I know that getting
outside is part of it and so I moved all my ECW gear to the coat room
near Destination Zulu so I don’t have to drag it out of my room every
time I feel like a stroll. I don’t think I want to do a lot of running
outside (my co-worker Carlos regularly does 10k or more out on the
skiway—he just passed in front of the window in front of my desk mere
seconds ago, covered in frost), but will make more time for walks, and
continue my runs on the treadmill.&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/6365788621_7a24685660_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6365788621_7a24685660_o_hu_5d978babcb1e46e2.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Traveller and the Human Chain</title>
      <link>http://johnj.com/posts/traveller-and-the-human-chain/</link>
      <pubDate>Thu, 17 Nov 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/traveller-and-the-human-chain/</guid>
      <description>&lt;p&gt;
Nov. 17, 2011 11:39 NZDT B2 Science, Amundsen-Scott South Pole Station&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6351772267_d0663ae803_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6351772267_d0663ae803_o_hu_97b54bd78a850b4a.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Summer Camp from the A4 wing
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Just helped form a human chain to bring the mail into the Station,
brought to Destination Zulu by a snowmobile/sled combo and a
front loader from Cargo, and swapped hand-to-hand up the stairs into
the airlock to the Post Office. Mail is a big deal here, and I’ve
enjoyed getting it in the past, so it’s fun to be a part of that, even
if just a few minutes.&lt;/p&gt;
&lt;p&gt;
Though I’ve continued to acclimate and have started running in the
Gym, I have not been sleeping well. Not sure why, because, though
noisy, it’s not as loud as it’s been in the past. It’s still
bearable. But I have to admit it feels as there is no getting away
from this place sometimes. Getting through a few weeks is enough of a
challenge that I find it hard to imagine a whole year (much less
multiple years like some winter-overs here have done). I do remember,
however, that it always seems to take a period of adjustment to get
into a rhythm here. The irony of the short trips I usually take is
that I’m generally more or less settled in by the time I leave.&lt;/p&gt;
&lt;p&gt;
At some point I owe returning readers to this blog an
explanation. Though I’ve always looked at my trips to the Pole as
potentially “the last time” (as any visit to an extremely
strange/strangely extreme place can be), I was pretty sure last season
WOULD be the last time, since we were done with IceCube
construction. I kind of made a big deal out of it, and said my
goodbyes to this place in this blog last January.&lt;/p&gt;
&lt;p&gt;
Clearly I was wrong, since here I am. The reason why is that we still
have to run the experiment we built, at great cost and effort, for
many years to come. Each season we have new winter-over scientists,
who have to get trained in many different, rather technical and
esoteric areas relating to the operation of the detector itself. This
includes the maintenance of roughly 150 servers in our laboratory
building, keeping an eye on network switches, disk and tape drives,
UPSs, etc.; and running a dozen or so homebrew software subsystems,
each written (mostly) by physicists, and each with its own
characteristic quirks and features. Though we do some days training on
a test system in Madison, Wisconsin, there is no substitute like
training &lt;em&gt;in situ&lt;/em&gt;, and so my task for this early-season visit is to
help facilitate that training, to answer those questions I can answer,
to provide exercises and training tasks which will help them prepare
for the coming year. My hope was also to get a bit more caught up on
various programming tasks (a hope so far not really realized).&lt;/p&gt;
&lt;p&gt;
All this raises the question, how many more times am I going to do
this? Some of you probably figured out long before I did that I might
have to actually “decline further missions” if I want to be certain
that this trip (or any future one) is the last.&lt;/p&gt;
&lt;p&gt;
To contemplate further trips requires some notion of how such work
aligns with one’s goals and aspirations.&lt;/p&gt;
&lt;p&gt;
In the 1980s, at the height of the Dungeons and Dragons-inspired
craze, my friends and I would occasionally take a break from D&amp;amp;D to
play a science-fiction variant called Traveller. The basic idea is the
same as D&amp;amp;D — one person &amp;#39;creates the world’ and the other players
create characters who do various things in the world, with a sort of
story unfolding spontaneously out of the interactions between the
characters and the world, and each other. But rather than knights and
magicians entering lairs of monsters, in Traveller, one learns
esoteric skills and then travels from planet to planet to carry out
various adventures. Worlds can vary wildly in climate, culture, and
technological sophistication, from backwards forested planets to
dazzling urban arcologies to frozen wastes….&lt;/p&gt;
&lt;p&gt;
The first few times I arrived at Pole, it felt like I was in a
Traveller game. The military modes of transportation; the quirky,
unwashed characters; the utter lack of scenery; the
only-slightly-breatheable atmosphere; and the elusive sub-atomic
quarry we were hunting… it was all just &lt;em&gt;so damned sci-fi&lt;/em&gt;. Of course
the old Station with its ’70s-era geodesic aluminum dome and the
somewhat ramshackle orange buildings within, the slightly chaotic,
dirty charm of the place, contributed to the atmosphere of
duct-tape-and-gritty-humor. I loved that aspect of it… in a way, I
guess I was living out the dream we had carved out gaming in my friend
Fred’s basement fifteen years earlier, and in the books and films I
consumed wholesale throughout my (er, extended?) adolescence.&lt;/p&gt;
&lt;p&gt;
Now, much of that feeling has been worn away with familiarity. I’ve
been asking myself what’s left when you take away that sci-fi
feeling. The South Pole is a job site. People make money here, make
and lose friends, fall in and out of love, go to the bathroom, get
inspired or depressed (or both), have accidents, get older. What
arises to fill the absence of the fantasies that this place used to
fulfill? Other than, of course, the physical and emotional discomfort
— sleeplessness, chapped hands/lips/elbows/…, headaches,
light-headedness, shortness of breath, sinuses made of wood, lack of
fresh fruits and vegetables, two minute showers twice a week, lack of
privacy, restricted entertainment options, lots of rules, nowhere to
go.&lt;/p&gt;
&lt;p&gt;
I don’t have the answer now but I’m living it, whatever it is. It
seems to be something about how to maintain cheerfulness under
discomfort and duress. About trying to stay curious about other people
when your own life doesn’t feel that easy. About the gap between when
someone coughs in an adjacent berthing and when the wind rattles the
wall behind your pillow. About enjoying small things like a good
cookie or a shared laugh. About accomplishing what you set out to do,
with as much contentment as you can manage. And, when you leave, about
the satisfaction of seeing night time, and leaves, and (liquid) water,
and loved ones again.&lt;/p&gt;
&lt;p&gt;
Regardless of whether or how I return here in the future, at the
moment, getting to know some of these things better is the way
forward: both the effort, and the reward.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6352516056_61d0b512c1_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6352516056_61d0b512c1_o_hu_46abb876d6bf044b.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Gary tries out a helmet
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6351773993_d95f3db9bc_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6351773993_d95f3db9bc_o_hu_b763fa2ee0ade31a.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Departing Hercules
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6351771287_f0cab14fa2_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6351771287_f0cab14fa2_o_hu_8848596ca1506295.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Shadow and Summer Camp
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6352513606_c67643da5d_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6352513606_c67643da5d_o_hu_4296288a01456995.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Station Exterior
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6351769881_1778912bd9_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6351769881_1778912bd9_o_hu_eea6f01c5f544f48.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Destination Alpha
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6351768757_63943f1268_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6351768757_63943f1268_o_hu_1e79d230958e3999.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Carlos after a 10k run at -40F/-40C
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Reveille</title>
      <link>http://johnj.com/posts/reveille/</link>
      <pubDate>Mon, 14 Nov 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/reveille/</guid>
      <description>&lt;p&gt;
Nov. 15, 2011 05:36 NZDT Berthing A4-209, Amundsen-Scott South Pole Station&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6338734777_956cbb8234_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6338734777_956cbb8234_o_hu_31bf137870c46960.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Fire sled next to refueling pit
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Well, that’ll wake you up nice and quick. We just had a fire alarm
which went on for long enough to get everyone out of bed and the fire
team half-dressed for action. False alarm, apparently.&lt;/p&gt;
&lt;p&gt;
I’ve had a checkered history with fire alarms here. A few years ago
when they were testing out the system, I was on night shift. Of
course, testing only occurred during the day. So for about four days I
could be practically guaranteed to be pulled out of bed (or at least
woken up by the shrieking of the alarm in my room) a couple of times a
night. Sleep is a precious commodity at South Pole (altitude and noise
conspire to make it challenging for me), and I was not a happy camper.&lt;/p&gt;
&lt;p&gt;
But testing or no, frequent fire alarms are a fact of life
here. Though it may seem counter-intuitive with the cold, the
practically zero percent humidity and frequent high winds make fire an
ever-present hazard. Couple that with the remoteness of the Station
and, well, you take it seriously. If a fire starts, help will not
arrive from McMurdo on time, except to collect the injured.&lt;/p&gt;
&lt;p&gt;
And even that assistance can only come in summer. As I understand it,
every winter-over is either on the fire team or the trauma team. There
is no “Let’s sit around and let’s see how it plays out” team.&lt;/p&gt;
&lt;p&gt;
We had a real incident here a few days ago with a glycol spill in the
power plant. Fortunately everyone was OK but we had to reduce power
consumption for several hours afterwards while they cleaned up and
brought everything back online. A similar episode happened a few years
ago which resulted in injuries and medical evacuations.&lt;/p&gt;
&lt;p&gt;
So I’m OK with false alarms.&lt;/p&gt;
&lt;p&gt;
Now to try to get back to sleep. Morning, all! :-)&lt;/p&gt;
&lt;p&gt;
(Postscript: beat the odds and managed to sleep a few more
hours. Sometimes you’re so tired that you can just sleep no matter
what.)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Drifts</title>
      <link>http://johnj.com/posts/drifts/</link>
      <pubDate>Sun, 13 Nov 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/drifts/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/6338735475_78d2300746_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6338735475_78d2300746_o_hu_7cddc5ef1ceaeae6.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Feeling a bit run down this afternoon. Got up and decided it was my
first “workout” day, working out consisting of twenty minutes of
walking since this is still just my fourth day here. Had a nice walk
and a bit of a stretch, and then a SHOWER, my first since
McMurdo. Feeling pretty peppy, I had decided today would mostly be a
day off, to rejuvenate and prepare for the week ahead. I was headed
back to my room to practice, and ran into WO Carlos who informed me
that a server had crashed in the IceCube Lab (ICL) and that the
detector was therefore running short one string. So much for a day
off, but this was another training opportunity, training being
primarily what I came down for. Sven and Carlos and I suited up and
Sven got a snowmobile with passenger sled ready (I was happy not to
have to walk the half-mile distance there and back, having perhaps
already pushed it a bit by walking in the gym).&lt;/p&gt;
&lt;p&gt;
I’ve been thinking more about what I wrote the other day, about being
tuned into differences between this trip and previous ones. In fact, I
have mostly been struck by the &lt;em&gt;sameness&lt;/em&gt;. The rhythm of the plane rides
here, the same faces year after year, the process of acclimatizing to
altitude, the same nooks and crannies (unmarked bathrooms, locations
of semi-private phones for calling home) — much has simply not changed
at all (at least in the past several years, since the new station was
built). It feels as though this place is on another plane altogether,
not part of Earth or the world at all, a kind of parking ground for
(temporarily?) lost souls. I would liken it to the Tibetan notion of
bardo, but bardo is an in-between state between incarnations, and this
place doesn’t feel in-between at all to me, but somehow out of the
normal flow of things. Limbo, perhaps.&lt;/p&gt;
&lt;p&gt;
A shift in perspective came to me as I was riding the sled out to the
ICL. The winds are still quite high, keeping the wind chills below
-60F, and making snow drifts and sastrugi everywhere. As we crossed
the skiway I looked out across the vast space and thought about the
drifting snow, the constant shifting and drifting, and realized that
the change I was curious about, in myself and in others, is more
subtle, a building and shifting over time which is hard to notice even
on the time scale of months or years. Yesterday in the galley a
colleague of many years, Robert, looked at me and said, “You’re
getting grey, man.” True enough. The wearing of time sometimes is
noticed not in sudden shifts but in gradual drifting, accumulation,
wear and tear and the greying of hair. Doesn’t sound cheerful, I
guess, but it was actually a pleasant notion to contemplate as we
zipped across the wide white waste.&lt;/p&gt;
&lt;p&gt;
After which, of course, we quickly fixed what needed fixing and headed
back for brunch.&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/6339469060_6153b75109_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6339469060_6153b75109_o_hu_e4621b0ce8f4a3da.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Bon Voyage</title>
      <link>http://johnj.com/posts/bon-voyage/</link>
      <pubDate>Fri, 11 Nov 2011 10:51:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/bon-voyage/</guid>
      <description>&lt;p&gt;
Nov. 12, 2011 11:46 NZDT B2 Science, Amundsen-Scott South Pole Station&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6335161057_f54dd33c4b_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6335161057_f54dd33c4b_o_hu_eaa7ef442278399e.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Jens and Freija departing South Pole after 12 months
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Just said farewell to IceCube winter-overs Freija and Jens on the
“flight deck” (outdoor waiting area near the plane… wind chill -65
F). Bittersweet partings for all concerned, I’d say. Their plane is
taxiing as I write this. Carlos and Sven take over now as winter-overs
for the coming year.&lt;/p&gt;
&lt;p&gt;
This was the first time I’ve been outside since I arrived two days
ago. It was cold but great to get out. I’m feeling even better today
and may try a walk in the gym tomorrow.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6335922242_1297892cca_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6335922242_1297892cca_o_hu_32ff9f3c08b0dd9d.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Heading out to meet the plane
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6335163953_6c3d6be3d9_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6335163953_6c3d6be3d9_o_hu_54d21ea7519151c4.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Farewell
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>A Nicer Guy?</title>
      <link>http://johnj.com/posts/a-nicer-guy/</link>
      <pubDate>Fri, 11 Nov 2011 06:08:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/a-nicer-guy/</guid>
      <description>
&lt;p&gt;
17:01 NZDT B2 Science, Amundsen-Scott South Pole Station&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6333051401_fff7b4cde3_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6333051401_fff7b4cde3_o_hu_cf903cf8d199bdab.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
En route to South Pole
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Been here just over a day now and am settling in. Once I get here it’s
easy to settle into a work routine, which makes it harder to do much
writing. But I’m still acclimating to the altitude, trying to rest and
stay hydrated, and the schedule isn’t too intense so far.&lt;/p&gt;
&lt;p&gt;
Did a debrief today of our outgoing winter-over (WO) scientists, who
are leaving tomorrow, and did some training of our new WOs as
well. Our old WOs are in good spirits but also happy to leave, and I
don’t blame them. In addition to having been here for most of a full
year (with just a brief R&amp;amp;R break before station closing), it sounded
like a pretty challenging winter, with medical emergencies you can
Google about (and some you can’t). I’m glad I came when I did because
it has been fascinating to hear their stories and their perspective.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6327681755_ac84151772_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6327681755_ac84151772_o_hu_621c0aa95284b089.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
McMurdo Evening
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6328431218_268aae5dd6_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6328431218_268aae5dd6_o_hu_7c2cd48c2c305fe0.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Building 155
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
My last post left off somewhere in the air between New Zealand and
McMurdo. We arrived safely at the seasonal Ice Runway and were quickly
put onto Ivan the Terra Bus. I couldn’t believe how close we were to
town — the last several seasons I’ve landed at Pegasus which is a good
hour (at minimum) from town. But Observation Hill and McMurdo proper
were clearly visible and seemed but a stone’s throw from the Ice
Runway, which I think they only operate early in the season when it’s
cold enough to land there. The trip into town took a mere 20 minutes
or so, after which we were briefed on life in town — a briefing which
I’ve attended ten times now and portions of which I think I can recite
from memory, despite the fact that much of it doesn’t really apply to
short-timer Polies (I have never done laundry in McMurdo, used the
gym, or even walked very far out of town, something which one cannot
do without attending an outdoor safety lecture).&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6333781134_bf4dba28ed_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6333781134_bf4dba28ed_o_hu_58be404f81238715.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Street texture
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
From the briefing I went to Crary Lab, got my laptop screened, and
checked email, and then went to settle into my room… but not before
grabbing someone else’s Big Red parka by mistake (they all look alike,
and his name is similar to mine, and …). Before long I noticed my
gloves, which were in my parka pockets, were missing, so I figured I’d
left them somewhere, and chased around trying to find them for an hour
or so (losing and re-finding USAP issue clothing seems to be my karmic
fate each and every trip). My hat, I noticed, was also gone — that
tipped me off to the fact that I had the &lt;em&gt;wrong jacket&lt;/em&gt;, so I went back
to Crary lab, gave back the jacket I “stole,” got mine (gloves and hat
included), and went to a very crowded galley for chow. After dinner we
weighed-in and I managed to get to bed early, in a room with only one
other fellow in it (McMurdo facilities manager and unicycle
aficionado).&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6333041917_46c8851ef2_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6333041917_46c8851ef2_o_hu_995ad43fdb6f0e87.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Flight manifest
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Our flight schedule was not nailed down by the time I went to bed, so
I was up at 5 AM and went off to check the flight manifest. By 8 we
were at the Movement Control Center along with passengers headed to
two other places on the continent. Our flight to the Pole consisted of
just five regular passengers, plus the Guard crew, and a woman,
already on the plane, who I assumed was a Distinguished Visitor or
reporter of some sort. The plane was jammed full of cargo and some
medical equipment and stretchers I assumed were bound for South Pole
Medical. Later I learned that our flight was actually a medevac flight
and that they were taking someone back to McMurdo in a hurry, which
may have explained the rather hasty briefing (barely audible over the
roar of the props) that we got on the plane.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6333793306_2c5aa60db0_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6333793306_2c5aa60db0_o_hu_71c9abda799b8c6c.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Baseler bound for Byrd Camp
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Though there were minor differences when compared to previous trips,
it was mostly quite familiar, and I found myself going through the
motions, not really being surprised by anything. At one point I sort
of woke up and said to myself, Dude, you are on a military aircraft
bound for the South Pole. Pay attention.&lt;/p&gt;
&lt;p&gt;
That more or less worked, and though I did play with some programming
stuff on my laptop for a lot of the flight, I also enjoyed the strange
familiarity of it, the familiar strangeness. Somehow being bundled up
in ECW gear and earplugs in a roaring C-130, with all its green guts
clearly exposed for the viewing, just feels like the canonical
Antarctic experience to me.&lt;/p&gt;
&lt;p&gt;
I managed to get up to the flight deck around when we passed over the
Trans-Antarctic Mountains. The vast Beardmore Glacier stretched below,
through black ridges of rock, a creamy, motionless river riddled with
great crevasses which looked like tiny scratches at that
distance. Though our window views were limited throughout the flight
(due to the bulk of the cargo), that view out the front windows of the
aircraft was stunning. The crew made sure I could take pictures and
video from various angles, moving aside and motioning me
forward. After I got my shots in, I talked to one of them and asked
him about the geography we were passing through; he said, “I don’t
know, I’m just a doctor.” (Presumably he was assisting with the
medevac.)&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/6333043895_8a8eff5b6d_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6333043895_8a8eff5b6d_o_hu_19e382bc19ced8ff.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/6333789324_bf735e806c_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6333789324_bf735e806c_o_hu_37f6d64c2b3a0b86.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/6333032527_12bfd4c8d1_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6333032527_12bfd4c8d1_o_hu_d57e8316fe85b415.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/6333790454_ab28815881_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6333790454_ab28815881_o_hu_fad09df2f22996e9.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/6333787198_c896936e67_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6333787198_c896936e67_o_hu_a504b5e5b190aff8.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/6333045095_d6185b59c2_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6333045095_d6185b59c2_o_hu_46cdcc7dc2e8bf75.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-1&#34;&gt;
Video from Flight Deck
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-3&#34;&gt;

&lt;iframe src=&#34;http://player.vimeo.com/video/31932373?byline=0&amp;amp;portrait=0&#34; width=&#34;512&#34; height=&#34;288&#34; frameborder=&#34;0&#34; webkitAllowFullScreen allowFullScreen&gt;&lt;/iframe&gt;

&lt;p&gt;
At some point between McMurdo and arriving at Pole, maybe on the
airporter bus to the Ice Runway, I thought about how much of a
collaborative effort all of this is, this whole Antarctic program. The
shuttle driver; the passenger manager who gave us our lunches,
earplugs and a safety briefing; the pilots and crew; the airplane
mechanics; the satellite techs; the waste management folks… there are
so many people working together here, professionally and (for the most
part) harmoniously… so many people doing their jobs, to keep us and
each other alive and safe and to enable scientists to do their
jobs. It is quite humbling, actually, to be on the receiving end of
that. That of course is the reality of the “Real World” too — it’s
just that so many of those people Up North are actually invisible… the
water treatment engineers, air traffic controllers, homicide
detectives, construction workers, priests… people you don’t normally
see but who keep you alive and safe. Here, things are turned inside
out, the machinery is exposed for all to see, you see each other more
— everybody pitches in, whether it’s “house mouse” duties (cleaning
bathrooms, etc.), working in the dish pit, helping to load “freshies”
into the galley, … you eat dinner with the people here who load your
cargo and handle fuels from the Hercs, with the cooks and the managers
and the dishwashers. People who could and would save your life if
needed. Somehow it’s just more clear who you rely on here… and they
rely on you too. It’s a good experience to have.&lt;/p&gt;
&lt;p&gt;
(It is also interesting to go somewhere where your comfort is not
anybody’s primary concern, and where nobody is trying to sell you
anything, but perhaps that’s a topic for another post.)&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6333802026_88035c7ebe_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6333802026_88035c7ebe_o_hu_fb2e4e59781f1695.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Briefing prior to boarding LC-130 to Pole
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Arriving at the Pole was a rush, as always. It was about 40 below,
maybe -66F with the wind chill. Freija, Sven, and Carlos met us at the
skiway. Strangely enough, of all the places I’ve passed through in the
past few days, this place feels most like home. And, as usual, I know
a bunch of people here and recognize many more faces. But it’s less
crowded than I’m used to, and I’m a bit more relaxed too, both of
which are nice.&lt;/p&gt;
&lt;p&gt;
I sat down at lunch with a communications engineer named James who I
met last season. James likes to discuss particle physics and quantum
mechanics. I sat down with him and a GA named Pete, a young fellow
with a robust blond beard who fights wildfires back in the real world.&lt;/p&gt;
&lt;p&gt;
James, sitting across from me, asked, “So, have you learned anything
in the past year?”&lt;/p&gt;
&lt;p&gt;
“You mean has IceCube made any discoveries, or have I personally?”&lt;/p&gt;
&lt;p&gt;
“You personally.”&lt;/p&gt;
&lt;p&gt;
I thought about it. “Yes, I think I’ve learned a lot, actually.”&lt;/p&gt;
&lt;p&gt;
“Such as?” asked James.&lt;/p&gt;
&lt;p&gt;
“Well, I think I’ve really learned a lot about programming.”&lt;/p&gt;
&lt;p&gt;
“Okay… I guess that’s good,” he replied.&lt;/p&gt;
&lt;p&gt;
“Also, I think I’m a nicer guy.”&lt;/p&gt;
&lt;p&gt;
At my side, Pete nodded sagely, and said, “That’s good. That’s good.”&lt;/p&gt;
&lt;p&gt;
It is.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>The Quiet Earth</title>
      <link>http://johnj.com/posts/the-quiet-earth/</link>
      <pubDate>Mon, 07 Nov 2011 18:21:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/the-quiet-earth/</guid>
      <description>&lt;p&gt;
2011/11/8 05:01 AM NZDT Christchurch&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6322623589_0fe8dbf022_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6322623589_0fe8dbf022_o_hu_d742b80f61381d4a.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Spring in Christchurch
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Woke up a few minutes ago and started thinking about a blog post. I
would have happily slept more but my body tells me that’s not going to
happen. It’s quiet here, with the only sound the faint snoring noises
coming from the next room over.&lt;/p&gt;
&lt;p&gt;
I’m at a hotel in an area of Christchurch called Papanui whose
distinguishing feature seems to be a shopping district with a mall and
a number of smaller stores and eateries. The shops include several
Asian restaurants, a comic store, and a small model train store. It’s
not bad area, but it feels like it could be anywhere in New
Zealand. I’m a bit sad not to stay at the Devon B&amp;amp;B, not to hear the
trolleys rattle by every so often, not to wander down to the Arts
Center or stroll down to the shops near Cathedral Square.&lt;/p&gt;
&lt;p&gt;
After my arrival yesterday, I tried to get out see a bit of what could
be seen. There is a rail line nearby with a path alongside it leading
to Hagley Park, which is close to the center of town near where I used
to stay. I went for a run down this path, perhaps a few miles, until I
reached the far side of the park. But I was out of water and energy,
so I didn’t go further.&lt;/p&gt;
&lt;p&gt;
Perhaps I’ll make it farther today or some other time. But, truth be
told, I’m not sure I have the stomach to see it. When we arrived at
the airport yesterday, we were met by a young woman who briefed us on
the conditions here. She made sure we kept our emergency information
cards on us at all times. She told me that, though she was from
Christchurch, she had yet to get the nerve up to go downtown and look
around. The cordon around the entire downtown area was apparently just
opened up a week or two ago — she said that the area is mostly a
write-off, with most buildings needing to be torn down and
rebuilt. Most of the Christchurch I have come to know over the years
is apparently gone. The newer parts around here seem mostly fine
(aside from a few fenced-off buildings), but the main reception area
of our hotel is closed off, with a rather lovely, elegantly-designed
shipping container structure serving as temporary office.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6322621813_8bca136732_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6322621813_8bca136732_o_hu_f9c703969c9e2f0a.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Ice People checking in at temporary reception container
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
The young woman described what it was like when the big earthquake hit
on February 22. She said that, out by the airport, it was eerily
silent just after the big shakes stopped. I was reminded of the 1980’s
New Zealand film, &lt;a href=&#34;http:http://en.wikipedia.org/wiki/The_Quiet_Earth_(film)&#34;&gt;The Quiet Earth&lt;/a&gt;, in which most of humanity is
suddenly spirited away. She said they could tell by the number and
intensity of the sirens which gradually filled that silence that it
was very bad for the downtown area.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/6323138550_b9ed8ea1d3_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6323138550_b9ed8ea1d3_o_hu_56dccf57b0f87275.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Fenced-off buildings in Papanui
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
My trip to Christchurch was pleasant. I asked for, and got, an exit
row window seat from Chicago to LAX. It even looked as though our
row’s middle seat would be empty (even more room!), but at the last
minute a large, Middle Eastern man got on and sat there. As we taxied
he pulled out a small book in Arabic, which I guessed was the Koran
until I noticed the picture of Jesus on the cover. We conversed a bit
and he told me he was a Copt, Copts being Egyptian Christians who,
according to Wikipedia, were the dominant religion there before the
Muslim conquest in the seventh century. He told me of recent
atrocities against Christians in Egypt by the majority Muslims, and
said that despite the Arab Spring things were not good now in Egypt
for Christians; in fact, he had won the Green Card lottery in the
States and went back to Egypt to settle some affairs before moving to
LA permanently. Nice guy.&lt;/p&gt;
&lt;p&gt;
At LAX, I managed to recharge my laptop and iPhone batteries at a
charging station and get my boarding pass for the Qantas flight to
Auckland. I asked if there was any choice of seats, and the guy at the
gate said, “no, but I got you an aisle seat.” Fair enough, I thought,
and went back to the charging station to do some work. When they
started calling my flight, I looked at my boarding pass and did a
double-take: they had upgraded me to Business Class! I was pretty
excited about this — the difference between Business and Economy for
me is 1-2 hours of sleep versus 5-7 hours, due to the extra space and
the fact that Business seats recline almost fully. I marched right on
the plane and sat down in the first row of seats and was happily
chatting on the phone and sipping orange juice in minutes. The flight
was very smooth; I really enjoyed the conversations with the guy next
to me, a lawyer from New York, and managed to both catch some sleep
and get some work done (there was a regular electrical power outlet
under my seat, another major bonus).&lt;/p&gt;
&lt;p&gt;
Electrical power and leg room are interesting to me; possibly less so
to potential readers. What does one write during one’s tenth trip to
the South Pole? I have written a journal of sorts during most or all
of my previous trips, usually some kind of blog. You can go back and
read a lot of that writing on this site. What can I say that hasn’t
already been said?&lt;/p&gt;
&lt;p&gt;
One answer that comes to mind is to work with difference — with what
has changed for me, or in external circumstances. Christchurch is
certainly different; we shall see how the Ice is different, if at
all. And I am different… older, certainly. Wiser? Perhaps. I plan to
explore some of these external and internal changes in future posts.&lt;/p&gt;
&lt;p&gt;
If you are interested in reading shorter updates (say, &amp;lt; 140
characters), I’ll be posting those to &lt;a href=&#34;https://twitter.com/eigenhombre&#34;&gt;my Twitter feed&lt;/a&gt;. And, as I did
in January, I’m &lt;a href=&#34;http://flickr.com/eigenhombre&#34;&gt;posting the pictures to Flickr&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Hotel fire alarm just went off. False alarm, but so much for the Quiet
Earth. Time to hunt down some breakfast. We get our cold-weather gear
at 1 PM.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Ten</title>
      <link>http://johnj.com/posts/ten/</link>
      <pubDate>Tue, 01 Nov 2011 21:03:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/ten/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/6283159199_eea2489f7e_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6283159199_eea2489f7e_o_hu_7b661024728be095.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
T minus four days and I’m getting ready for yet another trip to the
Pole — this one is number ten. I guess I’m not sure what I’m going to
write about on this trip, yet, but I will be posting updates as time
allows. Just spent a few hours getting the blog software up to speed
(there are lots of improvements I want to make if I have time). It’s
interesting coming back to a project after nearly a year and seeing
what I’ve learned since then.&lt;/p&gt;
&lt;p&gt;
Perhaps other aspects of the trip will put changes in other areas into
similar relief.&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/6283669550_2902942b27_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/6283669550_2902942b27_o_hu_847d904883514a49.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The Wheel</title>
      <link>http://johnj.com/posts/the-wheel/</link>
      <pubDate>Wed, 19 Oct 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/the-wheel/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/4figs-detail.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/4figs-detail_hu_115ba228a539b389.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/4figs-detail3.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/4figs-detail3_hu_4fcce0d217ff960d.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Details of drawing in progress
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
The wheel turns, and returns — during a very busy fall season
work-wise I have been unable to get much painting done but have lately
been drawing in the evenings with &lt;a href=&#34;http://johnj.com/posts/gouache-and-a-new-system&#34;&gt;ink and gouache&lt;/a&gt; — such a fun and
flexible pairing of media. Drawing seems to be what I come back to,
again and again.&lt;/p&gt;
&lt;p&gt;
Will be headed to the Pole again in just a few weeks, so check back
for some more blog posts!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Plein Air</title>
      <link>http://johnj.com/posts/plein-air/</link>
      <pubDate>Sat, 27 Aug 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/plein-air/</guid>
      <description>&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_6596_2.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_6596_2_hu_17aba524d1f99dbe.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Today’s painting — Town Line Road at OO, oil on panel, 8“x10”
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
I’ve had a week off and have been painting outside, at my mom’s house
out in the country near Chippewa Falls, Wisconsin. The investment
which has made this possible is called a &lt;a href=&#34;http://linesandcolors.com/2008/08/17/pochade-boxes/&#34;&gt;pochade box&lt;/a&gt; which is
essentially a small portable easel which fits on a tripod. The one I
got is called the Prochade by &lt;a href=&#34;http://www.artworkessentials.com/Index.htm&#34;&gt;Artwork Essentials&lt;/a&gt;. So far I’m pretty
happy with it, and slightly amazed and bemused at how fun it is to
use.&lt;/p&gt;
&lt;p&gt;
I’ve had a lot of resistance to painting outside over the years. The
few times I’ve done it have been enjoyable, but something about the
bugs, the cold, the heat, the sun, the rain, the lightning, the
tornadoes, the spectators, earthquakes, muggers, cosmic rays, etc. has
kept me from doing much of it. And my passion has always been
surrealism, fantasy &amp;amp; sci fi, nudes, painting from imagination, the
darker architecture of private spaces. Many of my favorite artists
also work this way, and I don’t think I met anyone in art school who
painted from life outdoors (or who admitted to doing so) … painting
outside seemed almost corny, a Sunday painter’s habit.&lt;/p&gt;
&lt;p&gt;
Lately, however, I’ve been interested in getting out there and working
from nature. Possibly some of that interest is thanks to blogs like
&lt;a href=&#34;http://gurneyjourney.blogspot.com/&#34;&gt;James Gurney’s&lt;/a&gt;. Gurney interests me because he is an artist of the
fantastic (see his Sci Fi book covers or the Dinotopia series), but is
also an avid plein-air painter, which very much informs his fantastic
work. (He even goes so far as to build sculptures or &amp;#39;maquettes’ of
his characters so as to be able to see and paint the real, natural
light on them.)&lt;/p&gt;
&lt;p&gt;
I’m also interested in making some slower, visual contact with the
real world, and perhaps ever so slightly less interested in aesthetic
navel-gazing (though I’m still very interested in painting imaginary
worlds).&lt;/p&gt;
&lt;p&gt;
Usually I paint sitting down at my easel in the studio, with a
computer, music, food, etc. all close at hand. I never liked painting
standing up in the studio; but standing up alone outside for a few
hours is surprisingly easy and pleasant. Also it is really nice to be
away from computers for awhile (an iPod can be nice while painting
outside, though being in the actual space with the crickets and the
wind is part of the experience too).&lt;/p&gt;
&lt;p&gt;
The French term for painting outdoors is “en plein air” — which could
be re-translated as “in the full air”. There is something pleasant and
“airy” about just choosing a subject and painting it &lt;em&gt;alla prima&lt;/em&gt; — no
preliminary sketches, no layers of glazes, photo transfers, reference
materials, SketchUp studies or traumatic mid-stream adjustments of
content — just walk up to the easel and make a painting! I finished
three paintings this week… my rate in the studio is sometimes less
than three per year. Plus the paintings themselves are more
lightweight — things I could just destroy or give away as gifts rather
than agonize for months about whether they’re done, where to show
them, how much to charge for them, etc.&lt;/p&gt;
&lt;p&gt;
I love photography and take lots of photographs in addition to the
studio paintings. Painting with the pochade box combines some of the
things I love about both art forms — you scout your terrain and frame
your image (à la photography) and then bring all your gestural and
color sensibilities to the material. You just do it, like clicking the
shutter, except it takes a couple of hours rather than a couple of
milliseconds. In the end your &amp;#39;shot’ is juicy, oily, full of bugs,
and, maybe, ready to hang on a friend’s wall for awhile. Nice and
easy!&lt;/p&gt;
&lt;p&gt;
Next, maybe we’ll see how it goes painting around Chicago.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_6584b.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_6584b_hu_b13235f905d3265e.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Pochade box in action
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>ISO50</title>
      <link>http://johnj.com/posts/iso50/</link>
      <pubDate>Thu, 28 Jul 2011 20:10:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/iso50/</guid>
      <description>&lt;p&gt;
Thanks to Jon at &lt;a href=&#34;http://blog.iso50.com/&#34;&gt;ISO50&lt;/a&gt; (Scott Hansen’s beautiful Web site/blog) for
&lt;a href=&#34;http://blog.iso50.com/24739/antarctica/&#34;&gt;mentioning / highlighting my Antarctic photography&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/is50jacobsen.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/is50jacobsen_hu_8aee43d1df5a9874.png&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>SketchUp and MakeHuman</title>
      <link>http://johnj.com/posts/sketchup-and-makehuman/</link>
      <pubDate>Mon, 27 Jun 2011 04:09:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/sketchup-and-makehuman/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/torus1.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/torus1_hu_f0adcd283eb7ed8f.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/torus2.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/torus2_hu_ccf294d9efeb5937.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Mockups for paintings
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/twofigs.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/twofigs_hu_45b447f64c45b283.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Makehuman figures imported into SketchUp
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
I’ve been playing around with the Golden Open acrylics a lot lately
and preparing a bunch of small and not-so-small supports for new
paintings. After trips to MOMA and the Chicago Art Institute’s
Architecture and Design room, I’m fired up to try more content using
SketchUp as a planning tool for dreamy, sci-fi spacious otherscapes.&lt;/p&gt;
&lt;p&gt;
While playing around with this I stumbled across a new program called
&lt;a href=&#34;http://www.makehuman.org/&#34;&gt;Makehuman&lt;/a&gt;. It pretty much does what it suggests — makes a 3D model of
a figure. There are for-pay software packages (Poser) which do this,
but Makehuman is open source. You can turn knobs to change gender,
body type, facial parameters, hair, etc… strangely addictive. Some
blog posts online suggested how you could import Makehuman figures
into SketchUp, but I had to hack around a bit before I got a recipe
which worked:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make model in Makehuman&lt;/li&gt;
&lt;li&gt;Export it as Wavefront .obj&lt;/li&gt;
&lt;li&gt;Import that into the latest Blender release&lt;/li&gt;
&lt;li&gt;Export THAT model as a 3D Studio Max (.3ds) file&lt;/li&gt;
&lt;li&gt;Import the .3ds file into SketchUp&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can’t really pose the figures yet in Makehuman, though that
feature is apparently in the queue. This stuff is evolving fast and I
think some really cool art could be made using the tools that are
being made now.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>In Defense of Hobbies</title>
      <link>http://johnj.com/posts/in-defense-of-hobbies/</link>
      <pubDate>Sun, 29 May 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/in-defense-of-hobbies/</guid>
      <description>&lt;p&gt;
I’ve been thinking about hobbies lately. Though “hobby” isn’t a word I
hear much these days, when I was a kid I thought about my hobbies all
the time. In fact, I can subdivide my youth into the various hobbies I
was interested in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Model trains&lt;/li&gt;
&lt;li&gt;Model airplanes&lt;/li&gt;
&lt;li&gt;Rock collecting&lt;/li&gt;
&lt;li&gt;Shell collecting and study of fish and ocean life&lt;/li&gt;
&lt;li&gt;Model rockets&lt;/li&gt;
&lt;li&gt;Electronics&lt;/li&gt;
&lt;li&gt;Science fiction&lt;/li&gt;
&lt;li&gt;Skateboarding&lt;/li&gt;
&lt;li&gt;Gaming (role playing, military, board games, …)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first two were big ones. Trains were a first love, and my
grandfather had a beautiful old HO-gauge steam train set with which I
was obsessed. During one family visit I was allowed to sleep with the
engine and tender. They smelled faintly of multi-purpose electric
motor oil and of the tablets which were placed in its smokestack
which, when heated during normal operation, simulated smoke. I can
also remember the smell of the HO-gauge green and white Burlington
Northern diesel engine I had, and the excitement and frustrations
involved with setting up my first layout in our basement.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/sleeping-with-trains.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/sleeping-with-trains_hu_caa1f73c3faeaee2.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Sleeping with Trains
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
My favorite store at the mall was called Hobby Horse [the etymology of
&lt;em&gt;hobby&lt;/em&gt; is late Middle English &lt;em&gt;hobyn&lt;/em&gt; or &lt;em&gt;hoby&lt;/em&gt;, from nicknames for the
given name Robin, which also, along with &lt;em&gt;Dobbin&lt;/em&gt; (aka Robert), denoted
a small horse]. Hobby Horse had a glass case with N-scale train
engines and cars in crystal boxes which you could shuffle or rotate
like a heavenly train-jukebox by pressing green “forward” and
“backwards” buttons.&lt;/p&gt;
&lt;p&gt;
When I was a little older I used to wander off on my own to spend my
allowance at the Midvale Hobby Shop. This trip used to involve a
several-mile trek on foot out the train tracks on the west side of
Madison, Wisconsin (this was back in the days when parents used to let
their kids wander around unattended as opposed to driving them
everywhere in minivans). After buying gum at the nearby grocery store,
I would wander the densely-packed aisles of the hobby shop, lusting
after the model airplanes and occasionally buying the cheaper ones
that were within my budget. These would get assembled by me and my
friends, painted and decal-ed somewhat haphazardly, and then have
bullet holes burned in the fuselage with magnifying glasses and
sunlight (like plenty of boys of that era, we were obsessed with the
Second World War and its aircraft in particular).&lt;/p&gt;
&lt;p&gt;
Long before it became its own focus of interest, drawing was a
meta-hobby — all my childhood hobbies involved drawing. Drawing could
be done just about anywhere, required very little hardware (a ball
point pen on IBM punch cards worked just fine, thank you very much),
and afforded the free ranging of the imagination over any aspect of
one’s obsession, whether trains, sharks, or Curtiss P-40 “Flying
Tiger” aircraft.&lt;/p&gt;
&lt;p&gt;
In High School, drawing metastasized into Art, including ceramics,
sculpture, woodworking, painting, and graphic design. No longer
hobby-like, since it was school, and therefore not leisure time
(“hobby” is defined as an activity done regularly for pleasure during
one’s leisure time), art was a social nucleus and a way to understand
and define who I was — not a mere hobby, but a core of identity.&lt;/p&gt;
&lt;p&gt;
After childhood, I hardly thought about hobbies at all. A decade-long
obsession with physics started (physics is a bit unforgiving to have
hobbyists, though there are some); I also went to art school and spent
some time growing an art career, and the fastest way to piss off an
art student or fledgling “serious” artist is to suggest that he or she
is doing it as a hobby.&lt;/p&gt;
&lt;p&gt;
Now it is another decade or two on and I hardly ever hear the word
“hobby” anymore. This may be in part because people have less leisure
time to begin with (particularly in the wake of the economic downturn
and shrinking incomes in general). It may also be due to the enormous
increase in variety and sophistication of entertainment, from video
games to movies and television, to social media and other online
distractions, any of which could I suppose could be called hobbies but
which lack the sort of active creativity I associate with the word.&lt;/p&gt;
&lt;p&gt;
Last night over dinner with my mom and stepdad and friends of theirs,
we were discussing hobbies. Ron’s brother simulates baseball games. He
and his pals gather virtually over the Internet (and, from time to
time, in the real world), accumulate deep wells of player-related
statistics, trade actual real-world players back and forth on virtual
teams, and slug out simulated National League games using intricate
rule systems. Ron’s brother apparently thinks (and talks) a great deal
about this activity despite, or perhaps because of, the fact that it
provides absolutely no illusion that, if only one worked hard enough,
one could eke out some sort of living as a “professional.”&lt;/p&gt;
&lt;p&gt;
The boundary between hobby and profession seems to be whether the
activity is paying the bills (this distinction is especially important
to the IRS, which essentially uses the profitability of one’s activity
to determine whether expenses in support of that activity are tax
deductible). Yet many of my friends in the visual or performing arts,
myself probably included, will never support themselves and their
families solely on their artistic activities (even art and dance
professors still have to teach, and teaching is a profession in its
own right). Nevertheless, they would not consider themselves hobbyists
— a word that we associate with dilettantism or lack of seriousness.&lt;/p&gt;
&lt;p&gt;
I think it’s time to rehabilitate the word “hobby.” Unlike
professions, hobbies can wax and wane without shame. To have a hobby
is to be an amateur, meaning one who loves something. To have a craft,
whether it’s needlework, growing orchids, or fixing your car. My dad’s
hobby is making deep Web sites for family genealogy and media. I know
guys who collect, fix and modify 1970s and ’80s era personal
computers. Another friend restores prairies.&lt;/p&gt;
&lt;p&gt;
At the moment, I am, among other things, a professional programmer. I
wonder what it would be like to be a hobbyist programmer. One who
programs solely for the love of programming, who has the luxury of
taking time to make things as beautiful and as clean as possible, to
polish and craft code like a jeweler or a fine cabinetmaker. Instead
of walking for hours on the railroad tracks to the hobby store (the
store is long gone and the tracks have been replaced by a bike trail),
I imagine a similar preparatory activity, walking outdoors among the
trees, calming my head and refreshing my body, and then sitting down
to engage with … my hobby.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Closure</title>
      <link>http://johnj.com/posts/closure/</link>
      <pubDate>Tue, 25 Jan 2011 05:22:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/closure/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5408573430_8b09b037b9_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5408573430_8b09b037b9_o_hu_e7fab15e0b97b02.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Once again on the train bound for Picton, to catch the Interislander
ferry to Wellington. I think this will be my last post for this trip,
so I may try to sum up a few things. First and foremost I want to
thank those of you who read along with me; knowing that there were at
least a couple of regular readers made the writing more enjoyable, and
helped keep me to the daily discipline of posting something, which in
turn helped establish a sort of rhythm for the trip.&lt;/p&gt;
&lt;p&gt;
I have called this my last trip to the South Pole and have tried to
treat it that way. Helping to hunt for neutrinos in Antarctica has
perhaps been my life’s biggest adventure, and it certainly is
bittersweet to say goodbye to it these past few days, thinking of each
step of my northbound journey as the last repetition of a pattern
established over years. Of course it is a fact that as long as life
continues one doesn’t know where one will wind up — just as one never
knows if the time one spends with a friend will be the last time or
not (and, in fact, every time is unique, never to be repeated, whether
you notice or not), I can’t say for certain whether or not I will ever
go back to the Pole. There will be other projects on the Ice and I
could see myself involved with those. Also, IceCube will hopefully run
another 15-20 years and they will be sending people every year, and
while I’m not sure I’ll be needed on the Ice I certainly wouldn’t rule
out helping if asked. But with the completion of IceCube’s
construction and the diminished likelihood of further trips, it seems
appropriate to let the place go in my mind. I feel that this is a time
in my life to start to let go of certain things, to let things fall
away and see what takes their place.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I remembered a sentence from Rudolf Steiner, … that when something
ends, we must think that something begins. His advice is salutary, but
the execution difficult, for we only know what we have lost, not what
we will gain. We have a very precise image — an image at times
shameless — of what we have lost, but we are ignorant of what may
follow or replace it. — Jorge Luis Borges, &lt;em&gt;Seven Nights&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
I wrote previously of success or Fruition, and tried to give a sense
of the excitement of putting a capstone on a body of work, related not
just to this two-week trip but to a decade or even half a lifetime of
work. Now I want to think for a moment about more mundane challenges
of the trip.&lt;/p&gt;
&lt;p&gt;
Towards the end of last year I got onto a sort of minimalism kick,
reading books and blogs on living simply and thinking about what sorts
of things I could give away or live without. The idea of paring down,
eliminating distractions and noise, multitasking less, and focusing
more on what matters, appeals lately. Of course traveling always helps
to encourage a certain minimalism. Going to the actual Ends of the
Earth, living out of two bags in a room no wider than my wingspan and
not a lot longer, living with four minutes of shower time a week, not
having to (or being able to) cook for myself, having no Internet for
most of the day … this level of enforced minimalism is something I
have enjoyed in the past, but it seemed this time to throw into relief
the three choices available at any given time. These were: to distract
myself with work (for there was always more work to do, always someone
to help or a question to answer or a test to run, even before
considering the ever-present backlog of pending software fixes and
upgrades); to distract myself with play (movies, books, socializing,
blogging, photography, games, …) or, often less appealing, to just
stop and be where I was: at the Pole; short of sleep; too hot or too
cold; irritated by all the noise; worried about this or that; chapped
or bleeding in various places because of the dryness; bad hair;
missing fresh fruit and veggies; and generally being out of sorts at
the Bottom of the World.&lt;/p&gt;
&lt;p&gt;
“This year I would like to set one goal, which is to be as fully awake
and alert to the entire experience as I can.” Though there vivid and
joyful moments, many of which involved stopping and just looking out
at the lovely white waste, or moments of fellowship with colleagues, a
shared laugh or the ordinary pleasure of lining up for food in the
Galley, being awake often meant taking stock of just how uncomfortable
I was and how I was searching for the next distraction. Having “awake”
as a goal meant bumping against that over and over again, and
confronting my resistance to whatever was going on. Perhaps by
occasionally noticing, I wore a small nub off of that great ball of
resistance.&lt;/p&gt;
&lt;p&gt;
My Antarctica has been:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The first acid bite of wind on my face after getting out of the
plane after the flight to the South Pole&lt;/li&gt;
&lt;li&gt;The smell of SimpleGreen™ used to mop the floors and clean the
waterless urinals&lt;/li&gt;
&lt;li&gt;Workouts in various gyms in the old and new stations&lt;/li&gt;
&lt;li&gt;The hisses and rumbles of a hundred invisible machines inside and
outside — heaters, generators, snow tractors, skidoos, Hercs&lt;/li&gt;
&lt;li&gt;The metallic crunch of half-ton doors closing, and steps on metal
stairs&lt;/li&gt;
&lt;li&gt;Stash tea: licorice spice&lt;/li&gt;
&lt;li&gt;The sound of the flags flapping from the platform above Destination
Alpha&lt;/li&gt;
&lt;li&gt;Having noisy neighbors, and (probably) being one&lt;/li&gt;
&lt;li&gt;Carrying a radio instead of a cell phone&lt;/li&gt;
&lt;li&gt;Music: David Bowie, “Outside” (1998); Soundtrack to “Pi” (2000);
Kris’s 7-CD mix (2009); the fellow playing guitar down by the gym
(2011).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;“Everybody has his own Antarctica.” —Thomas Pynchon, &lt;em&gt;V&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
I say goodbye to mine.&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5407966865_cdca1db8c6_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5407966865_cdca1db8c6_o_hu_c4e0e9014631e417.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Thanks again for reading. I plan to keep &lt;a href=&#34;http://flickr.com/eigenhombre&#34;&gt;posting pictures&lt;/a&gt; for awhile
since I haven’t gone through all 2500 of them and because I’m still
taking a lot here in New Zealand.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Takeoff</title>
      <link>http://johnj.com/posts/takeoff/</link>
      <pubDate>Sun, 23 Jan 2011 22:09:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/takeoff/</guid>
      <description>&lt;p&gt;
Yesterday’s post was a bit of a tome and I am using today to do some
shopping. Heading up to Wellington tomorrow by train + ferry. So I
will leave you with a short post today consisting mainly of a link to
the video I took taking off in the C-130 from South Pole:&lt;/p&gt;
&lt;p&gt;

&lt;iframe src=&#34;http://player.vimeo.com/video/19102744?byline=0&amp;amp;portrait=0&#34; width=&#34;512&#34; height=&#34;288&#34; frameborder=&#34;0&#34; webkitAllowFullScreen allowFullScreen&gt;&lt;/iframe&gt;
&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Mummification</title>
      <link>http://johnj.com/posts/mummification/</link>
      <pubDate>Sun, 23 Jan 2011 11:18:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/mummification/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5378107113_62775b6b01_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5378107113_62775b6b01_o_hu_dbb600ba1a12e9ae.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
A full day in Christchurch, a Pole month’s worth of showers, sushi,
photos of graffiti, walking around, going to the Christchurch art
gallery, good conversations, and a nap have all helped get me back
into the Real World™. I would like to try and remember the trail of
events that led here from the last long blog post, because if I wait
another day they will be gone down whatever tunnel of emptiness my
leaky memory feeds into. They are gone already, of course, but I
perhaps I can share bits and pieces with you nonetheless.&lt;/p&gt;
&lt;p&gt;
My last day at Pole was good. I disengaged with work long enough to
wander the Station quite a bit, shooting videos of the place and the
people and savoring and digesting the smells and the sights and the
low, thrumming vibrations of the place. One nice thing about having
the camera which does stereo video is that it captures the sounds
almost adequately (I have long dreamed of bringing enough equipment to
the Ice to do really good audio recordings of very banal things like
wind and machinery and radio traffic and the ebb and flow of
conversations in the Galley — the Canon S-95 let me do that with the
video well enough as an approximation without having to haul a lot of
gear all over the place).&lt;/p&gt;
&lt;p&gt;
Friday morning I got up as usual, skipped my gym workout, meditated,
had breakfast in the Galley, did the 0800 and 0830h meetings, had a
good talk w/ our cadre of Polies about software development within
IceCube, then did the final packing and cleaning up of my room. There
was a lot of discussion about whether we would actually go that day —
there had been a lot of delays due to weather, people were delayed
Southbound into McMurdo and the forecast for Pole hadn’t been great
the previous day, but it cleared up to be fairly nice (partly sunny
and -18 F or so, which was the coldest it ever got for me this trip —
quite a bit warmer than previous trips, though I came midsummer rather
than the usual end-of-season). Also the northbound Polies from a few
days previous were all stuck in McMurdo, including a bunch of “DV“s
(distinguished visitors) who I’m sure had to get back home for Various
Important Things. It wasn’t at all clear whether we would get stuck in
McMurdo with them or whether the logjam would break with our arrival.&lt;/p&gt;
&lt;p&gt;
The day you leave, the cadence and excitement builds, starting, if the
weather and mechanical gods allow, with an all-call announcement
around 9AM of your plane taking off from McMurdo (“Attention South
Pole… we have our first off-deck of the day, skier 93 arriving South
Pole at 12:10 PM… this is our inbound/outbound passenger
flight…”). Comms tells everyone your flight “has reached Pole-3”
(about 25 minutes away) and then “the flight is 10 minutes out… the
crossing beacon is on… please stay clear of the skiway…” and then
“aircraft is on deck… crossing beacon is off” and finally, “passengers
please proceed to the flight deck.”&lt;/p&gt;
&lt;p&gt;
We were four &amp;#39;Cubers and one radio guy, and a few people I didn’t
know. It was nice to have several of those who were staying come to
see us to the plane — a sort of karmic reward for having greeted
several of them, I suppose. We all made our way out, took the
obligatory group photos, and killed time while Cargo unloaded and
loaded the plane and the fuels person sucked AN-8 fuel out of the Herc
to add one more increment to the winter’s fuel supply. Some over-eager
passengers headed to the plane a few seconds early and had to wait
until the Air Guard gave the all-clear; I was the last person to the
plane, waved a final goodbye to the remaining IceCubers out on the
snow, and then piled into the Herc after everyone else. As soon as
they closed up the hatches the flight crew blasted the heat and it
went from -18F to probably 60F in about 5 minutes, and people shed
various hats and gloves (the parkas, though warm, are excellent to nap
in, since you can pull your hood over your head to shut out light and
some sound and sort of self-mummify yourself to sleep). We all
juddered in our seats as the plane literally skated down the skiway,
gradually gaining speed… it takes a good bit of time for the C-130s to
actually get airborne and I cheered the plane on, twisting around in
my seat to film my goodbye takeoff video from the window behind
me. Then we were in the air and past the last skiway flags and over
the great white void that is the polar ice cap.&lt;/p&gt;
&lt;p&gt;
The cabin pressurized almost immediately and I happily sucked down the
extra oxygen. I spent the flight writing a bit and photographing the
&lt;a href=&#34;http://www.flickr.com/photos/eigenhombre/sets/72157625758147573/&#34;&gt;Transantarctic Mountains&lt;/a&gt;. Though I thought I recognized some of the
places, it is scenery one doesn’t tire of. Then I dozed a bit and
before I knew it we were descending down to Pegasus field. When we got
out it was nearly 60 degrees F warmer than when we left — above
freezing, not quite slushy but definitely a different character of
snow. We snapped a few pix and then got a brief van ride to a much
larger Delta transport vehicle, the least comfortable transportation I
know of (the passengers rattle around in a compartment completely
separate from the driver, so she tosses in a radio after loading them
in so they can call her in case of emergency).&lt;/p&gt;
&lt;p&gt;
It was ironic to have to take the hour-plus journey into McMurdo,
knowing that the plan was to have us back out there for a night flight
in just a few hours. I took it as a sign that they didn’t actually
expect the C-17 to arrive from Christchurch, and that we would be
stuck in Mac Town for several days. But, whatever, I was at low
altitude, with warm air, in a place with actual landforms. We jostled
and jolted into town and immediately bag-dragged for
Christchurch. Afterwards it was nearly dinner time so we headed
towards “building 155” which is the main hive of activity in town…
Sebastian and Andrew in T-shirts, all of us skipping down the wooden
steps and crossing actual an actual stream of water, then headed down
the road and kicking at rocks and watching dust blow hither and yon.&lt;/p&gt;
&lt;p&gt;
When Shackleton’s crew, having survived a desperate winter and the
crushing of their vessel in the sea ice, reached Elephant Island, the
men were delirious with joy to tread upon something other than
ice. “They were laughing uproariously, picking up stones and letting
handfuls of pebbles trickle through their fingers like misers gloating
over hoarded gold,” he wrote. Though McMurdo is quite an ugly place by
most peoples’ standards, to see actual dirt, rocks, and running water
in McMurdo is quite a pleasure after the Pole, a pleasure I wasn’t
immune to this trip despite my relatively short stay at the Pole.&lt;/p&gt;
&lt;p&gt;
At dinner we ran into the other &amp;#39;Cubers who were stuck in town waiting
to go North, and I saw several other people I recognized from other
Pole seasons. The consensus was that there was no way we were going to
get out that day; the next day was Sunday (no flights) and the rumor
was that no flights had gone on Monday either for several weeks. So I
basically was preparing to have to completely rethink my New Zealand
plans. Afterwards we headed to &lt;a href=&#34;http://en.wikipedia.org/wiki/Discovery_Hut&#34;&gt;Discovery Hut&lt;/a&gt; and saw the lone Adelie
penguin which has apparently been hanging around for several days or
more. Colleague Mike came out with us in just a thin shirt and in fact
all of us were a bit underdressed; the wind started picking up quite
quickly and we hurried back and then headed to the Coffee House (which
is really more like a bar) and killed time waiting for news of the
flight from Christchurch. Again the consensus was that there was no
way, we were all going to be stuck there for days.&lt;/p&gt;
&lt;p&gt;
Finally, two bottles of wine later, around 11 PM someone came in and
gave us the news: the C-17 had taken off from Christchurch and was en
route; we were to report at 1 AM for transport to the airfield. At
this point I began to simultaneously get optimistic that we would go,
and very tired (I typically went to bed around 10 PM at Pole). From
then on things gradually became more and more dreamlike, as we headed
back to Pegasus (this time in Ivan the Terra Bus, a step up from the
Deltas but still a long ride in the middle of the “night”… though we
did see five emperor penguins!!!), rattled around the “terminal” (a
square orange trailer on skis with chairs for maybe 80 people) while
the C-17 was unloaded, then, finally, about 45 minutes standing around
the snow watching while they filled the C-17 with our bags, a bunch of
retrograde waste cargo, and, oddly, the propellor of an airplane. We
left the Ice around 4 AM as I sunk into a slightly delirious cycle of
half-sleep, dreaming for a few minutes, blearily waking up and
fidgeting and then sleeping a bit more. As in all long distance
flights, it took forever and was over before I knew it.&lt;/p&gt;
&lt;p&gt;
When we arrived it was raining. People even complained.&lt;/p&gt;
&lt;p&gt;
I was happy to be back in New Zealand, to have a full week of rest and
creativity and the pleasures of summer, and to go home after
that. Immigration and customs took only a few minutes (“Did you leave
for the Ice from Christchurch? OK, thanks very much.”). I have no idea
how they de-palletized our bags and got them to the terminal so
quickly. Before I knew it I was shedding 40 pounds of gear (it is
always SUCH a relief to give it back) and heading to my hotel. By 10
AM I was at the Grange B&amp;amp;B waiting for my room to be readied (I had
expected to have to go nap by the river since check-in time is usually
late afternoon, so this was a big relief as well). While waiting I
talked to another guy from the C-17 — he had spent two months in the
Dry Valleys, a helicopter ride away from McMurdo, with NO SHOWERS,
sleeping in constant daylight, drilling ice cores. He spoke of
2000-year-old mummified seals and penguins (the air is so cold and dry
that normal decay is essentially stopped).&lt;/p&gt;
&lt;p&gt;
Since arriving I have basically sleeping, showering, eating and
walking around. And speaking of sleep, it is time to do that. I was
going to add a bunch of photos and videos to make this a very
multimedia post but it is too late… perhaps tomorrow will be an
all-media day. Good night to all.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5379302962_3ef79337ec_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5379302962_3ef79337ec_o_hu_bb31956ea5a5ca4e.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
McMurdo: Actual dirt (and water!)
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5377163133_5a5df79e9c_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5377163133_5a5df79e9c_o_hu_c0ba8f5fa0a6bbfd.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
New Zealand, Summer, the Real World
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Eleventh Hour</title>
      <link>http://johnj.com/posts/eleventh-hour/</link>
      <pubDate>Sat, 22 Jan 2011 10:44:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/eleventh-hour/</guid>
      <description>&lt;p&gt;
Just a few more minutes to get this post in for January 22. This will
be very brief since I need to catch up on sleep. The short summary is
that we arrived safely in Christchurch this morning after a very
eventful 24 hrs. It is great to be back in the real world but our
night flight was quite exhausting and it will be a day or so before I
feel rested. I will try to write much more in length tomorrow and post
a lot of photos (and maybe even a video or three).&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Diamond</title>
      <link>http://johnj.com/posts/diamond/</link>
      <pubDate>Thu, 20 Jan 2011 18:57:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/diamond/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5372762927_3e6652648d_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5372762927_3e6652648d_o_hu_2b033e09c5b928bc.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Morning on my last day (hopefully) and, like a kid on the night before
Christmas, I’m excited and nervous. But in some way it feels like my
&lt;em&gt;last&lt;/em&gt; Christmas. I have been a bit sad off and on. Not a bad sad, but
I’ve spent so much time absorbing the peculiarities of this place that
it is a bit hard to say goodbye to them, and to it. Last night I spent
quite awhile in Comms, the place with the best view on the station,
looking out over the skiway and the Dark Sector. While listening to
the radio traffic from McMurdo flight control, the attendant static
pops and hisses and beeps, and the occasional words from the woman on
shift, I looked out across the skiway at IceCube a kilometer
away. From Comms one can see the extent of the entire hexagonal
IceCube array, 1 km on a side — each of the 86 strings marked with a
large red or orange flag, with the ICL building in the middle; and,
surrounding this enormity, the much vaster enormity of the wide,
white, expanse of the ice shelf we are on, flat as glass and encrusted
with powdered diamond, textured with a million tracks of wind,
vehicles, and footprints. There are so many beautiful vistas in the
world, but that particular view is entangled with my life in myriad
and deep ways, from the words on this page to the code I wrote which
is running as you read this in 5500 computers deep in the ice, from
the lines on my face from the years I have spent working on this, to
the relationships (ranging from passing greetings to deeply
challenging to strong affection) with so many people in the project…
to the artwork I have made, to the artwork I want to make… all these
ties and tangles feel, to some extent, a bit more exposed in these
final moments.&lt;/p&gt;
&lt;p&gt;
The weather forecast last night predicted low visibility, which often
means canceled flights. But today the forecast looks better and there
are four flights scheduled. I expect this chapter does in fact get to
close today. With any luck I won’t get stuck in McMurdo. Time for
breakfast, two meetings, then clean my room and sail on outta here.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5373357712_4c5c997780_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5373357712_4c5c997780_o_hu_907a4a9b3d19c4b4.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Late season rush of activity begins
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5373367464_e44f7f2801_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5373367464_e44f7f2801_o_hu_f696395c98fe2579.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Antarctic footwear: flip-flops for shower, boots for normal walking around, Baffin boots for major work outside
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5373368928_29b88faae6_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5373368928_29b88faae6_o_hu_21d813d3d5c5a419.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
View in B2 with emergency sleds
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Baby, It&#39;s Cold Outside</title>
      <link>http://johnj.com/posts/baby-its-cold-outside/</link>
      <pubDate>Wed, 19 Jan 2011 18:12:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/baby-its-cold-outside/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5358823996_bae88f92c4_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5358823996_bae88f92c4_o_hu_fbe3283d6ae2b8fb.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Holy frozen Batman, I’m leaving tomorrow! I still have a lot I want to
do! I was just getting into the swing of things! But I am also excited
to leave. A colleague always says, “the best days at the South Pole
are the day you arrive and the day you leave.” After all these years,
that feels as true as ever.&lt;/p&gt;
&lt;p&gt;
I know my time is short today because I have to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pack (bags out by the station door known as “Destination Zulu” by 7
pm)&lt;/li&gt;
&lt;li&gt;Sort my garbage (the US Antarctic program has an extensive recycling
and waste management program, and I have two weeks of trash in the
can in my room)&lt;/li&gt;
&lt;li&gt;Finish editing documentation for our Winter-Overs&lt;/li&gt;
&lt;li&gt;Help the new arrivals get set up for their work&lt;/li&gt;
&lt;li&gt;Possibly, hopefully, visit the antenna fields with Marco, the second
of the four marathon finishers here. His site is a few km from the
station and will present a view of the South Pole I’ve never seen
before.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That will be a very full day even assuming nothing else comes up. But
24 hours from now I will be listening intently to the flight
announcements. I just got email from Northbound colleagues in McMurdo
saying there are flight delays today due to fog (dang) but that they
saw penguins (cool!) — the ever-present uncertainties of travel in
Antarctica start to kick in for me now.&lt;/p&gt;
&lt;p&gt;
But I’m going home soon!&lt;/p&gt;
&lt;div class=&#34;verse-block&#34;&gt;
&lt;p&gt;I really can’t stay
(but baby it’s cold outside)
I’ve got to go away
(but baby it’s cold outside)
This evening has been
(been hoping that you’d drop in)
So very nice
… So really i’d better scurry
(beautiful please don’t hurry)
but maybe just a half a drink more
(put some records on while i pour)&lt;/p&gt;
&lt;p&gt;
Ooooo Baby it’s cold… out…. side!&lt;/p&gt;
&lt;p&gt;
– &lt;em&gt;Lyrics and melody by Frank Loesser … shout-out to E&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5365805196_3bfb512187_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5365805196_3bfb512187_o_hu_b26b97e274ff5385.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Cargo berms
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5368605740_ee105b55f1_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5368605740_ee105b55f1_o_hu_9fb80ba2ab130e2d.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Warming my hands in the GOES antenna shack (a tiny plywood room inside the antenna dome; photo by M. Dierckxsens)
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Fruition</title>
      <link>http://johnj.com/posts/fruition/</link>
      <pubDate>Tue, 18 Jan 2011 23:25:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/fruition/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5368589094_9b5a8035f2_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5368589094_9b5a8035f2_o_hu_e64483443afea5f6.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Back in the Galley again, the smell of dozens of lunch burgers
grilling and the very same licorice spice Stash tea I always drink
here setting the olfactory tones for this post.&lt;/p&gt;
&lt;p&gt;
Almost exactly twenty years ago, when I was working at CERN in Geneva,
Switzerland, I was preparing to return to Madison to take some art
classes and I emailed some physics colleagues there to see if there
was any student work to be had. Colleagues Bob Morse and Francis
Halzen replied that there was a new project under way, which was to
build a neutrino detector in the Ice in Antarctica. Bob had done an
experiment at the Pole to detect cosmic rays, and Francis was a
particle theorist who specialized increasingly in astro-particle
physics, and neutrinos in particular. Computer simulations were needed
to see how effective light sensors, placed deep in the ice, might be
at detecting neutrinos.&lt;/p&gt;
&lt;p&gt;
What started as an art-school day-job turned into a doctorate in
physics as the Antarctic Muon and Neutrino Detector Array (AMANDA)
became a reality and the computer simulations I and other students
wrote became important tools for the understanding of the data from
the first instruments deployed by the growing collaboration in the
polar ice cap. But in the very earliest years, it was understood even
by using back-of-the-envelope calculations that a much larger detector
would be needed… a Cubic kilometer of Ice, in fact … an Ice
Cube. AMANDA paved the way by detecting high-energy neutrinos, by
setting limits on astrophysical sources, and, perhaps most crucially,
by providing technological prototypes for the hot water drilling which
would be needed to deploy the sensors, and for the design of the
sensors themselves which evolved from simple photomultiplier tubes at
the ends of long coaxial cables to sophisticated computers in their
own right which would provide the maximum signal quality by digitizing
the light down in the ice and sending them to the surface with no loss
of signal quality.&lt;/p&gt;
&lt;p&gt;
The difficulties faced by AMANDA were daunting. The drilling in
particular was an immense engineering challenge, requiring a kind of
specialized expertise found in only a handful of individuals (if that
many) worldwide. One man in particular, the late Bruce Koci, brought a
kind of preternatural understanding, intuition and tenacity to the
task which allowed the 2-km holes for the AMANDA instrument to be
drilled successfully, though not without delays, logistical and
engineering nightmares, burst hoses, and endless worry
Collaboration-wide. After the holes were drilled, deployments of the
“strings” of sensors themselves were an ordeal in their own right,
sometimes involving &amp;#39;stuck’ strings, free-falling cables, injuries
and, in the best of times, 20-hour deployments out-of-doors in a
single shift (one of my most vivid memories of these deployments was
the enormous amounts of food one could eat during the breaks, and the
utter contentment of exhaustion when the task was done).&lt;/p&gt;
&lt;p&gt;
Handling the data in AMANDA times was a challenge in and of
itself. The data volume and mathematical complexity of the analysis
strained the computing resources available at the time; crunching the
numbers to find the first neutrino candidates required time on Cray
supercomputers and a scrum of dedicated grad students and postdocs
working at the limits of their programming abilities.&lt;/p&gt;
&lt;p&gt;
Since it was understood that AMANDA would eventually give way to a
larger instrument, work began well before the final stages of AMANDA
to design the IceCube detector and to procure funding. Several
competing prototype designs for a next-generation sensor were created
and tested in later AMANDA deployments, including a design created
while I was at LBNL in Berkeley. The LBNL “Digital Optical Module”
(DOM) took some of the signal processing computations down into the
ice itself in order to get the maximum signal quality. Though more
sophisticated (and expensive) than the usual AMANDA modules, the
interface to the surface required only the usual copper coaxial
cables, with far better quality of data. A test AMANDA “string” (#18)
deployed in 2000 worked well enough (barely!) to show that the DOM
technology was workable and could be used to detect particles in the
ice. The early LBNL prototype would be extensively improved for
IceCube.&lt;/p&gt;
&lt;p&gt;
IceCube itself received a first real jolt of funding in 2002 and work
began to quickly implement the vision of a kilometer-cubed detector. I
was put to work on the communications interface which would connect
the deployed DOMs down in the ice to a network of off-the-shelf
computers running on the surface, a design which would make IceCube an
experiment with relatively little custom-built electronics from a
high-energy physics standpoint (the DOMs, cables, and a computer
interface card plugged into a commodity chassis are the only hardware
we had to design ourselves… the rest of the experiment looks like a
data center you’d find at any medium-sized Internet company).&lt;/p&gt;
&lt;p&gt;
The first three IceCube holes were planned for early 2005, but the
first version of the new drilling equipment (an enormous engineering
task in and of itself) proved exceptionally challenging, and after an
injury in the drill camp and many other difficulties, the first
IceCube string was deployed in early January. After freeze-in, the
DOMs were powered on for the first time by National Science Foundation
Representative Jerry Marty and Station Manager BK Grant, with all of
us watching with bated breath to see if the DOMs communicated. They
did.&lt;/p&gt;
&lt;p&gt;
The following seasons were all very challenging. Drilling improved
substantially with experience, with 8, 12, 19, 19, 20 and 7 strings
deployed in the following years, respectively. Software was written,
and rewritten, to read out the data generated by 5500 DOMs and to
progressively reduce the huge volume of noise to a size small enough
to be sent over the satellites to the North. Tasks such as writing the
embedded software for the DOMs themselves, to the system which sifts
through the detected light to “trigger” on signals from real particles
traveling through the Ice, to the filtering of these particles for
neutrinos, to the overall control and monitoring of the system, to the
simulation of the entire process to be able to make firm quantitative
statements about what we are seeing — all this has taken a tremendous
amount of effort, collaboration, acquisition of knowledge and skill,
political struggles, failures and triumphs.&lt;/p&gt;
&lt;p&gt;
It has seemed that since we started this project, there has been
barely enough time to catch one’s breath. Now we are at the end of the
construction of this utterly strange device. I have put nearly a
decade of my life into this project alone. If you count AMANDA, I have
spent almost half my life in this field.&lt;/p&gt;
&lt;p&gt;
Last night we took the first runs with the completed IceCube detector
— all 86 strings. Though hopefully the experiment will run for
decades, in some sense last night’s runs were for me the fruition of
years of effort, since I have been more a builder than a user of this
instrument. I was going to write more about how it feels to hit this
milestone (one which I was never at all certain we would reach), and
less about the history… but how I feel seems somehow not that
important right now. We built it. Many of us. It is good. May it run
long and see deep into the fabric of things. May it teach all of us
about many new and beautiful things. May we all benefit from working
together and take the knowledge gained, from the trivial to the
profound, out into the world to do good things.&lt;/p&gt;
&lt;p&gt;
Time to greet the dozen or so of new IceCube arrivals from the flight
landing now — the last big batch of &amp;#39;Cubers for the season… maybe the
last big batch ever.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5368589556_99e1380a8c_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5368589556_99e1380a8c_o_hu_41b0b0a780d637e8.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
IceCube on-Ice lead Greg Sullivan starts the first 86-string run using IceCube Live
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5368605334_d21905313a_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5368605334_d21905313a_o_hu_6caa07aa879f3261.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Celebrating the run
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Friendly Radiation</title>
      <link>http://johnj.com/posts/friendly-radiation/</link>
      <pubDate>Tue, 18 Jan 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/friendly-radiation/</guid>
      <description>&lt;p&gt;
Tuesday, Jan. 18 2011 1:14 a.m. UTC&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5365801396_ea55563463_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5365801396_ea55563463_o_hu_e25e82e28328da57.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5365799904_c8b367d4d4_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5365799904_c8b367d4d4_o_hu_5a8155f7738ffebe.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Running out of time on this satellite pass for a blog post. Took tons
of photos today… this morning we had a tour of the satellite antennas
at the very end of Summer Camp. The weather was fantastic, maybe -15F
with no wind and high clouds which shed a magic crystalline light on
everything. Satellite technician James and his winter-over colleague
Glen showed us around, with some of the best views of the Station I’ve
ever had.&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5365195533_dbd3a29fd6_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5365195533_dbd3a29fd6_o_hu_a2b249714e518d15.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
The satellite stations and the Hercules flights are our ONLY regular
link to the outside world. So aside from the inherent technical
interest (what geek doesn’t like large satellite dishes and racks of
hyper-specialized electronics), there is also an emotional impact to
seeing the intricate fragility of our communications uplinks. Every
bit of data I’ve sent off station (or sent from various offices in
Chicago, Madison or elsewhere TO the Pole) has passed through these
humble structures and the networks that connect them to the rest of
the Station.&lt;/p&gt;
&lt;p&gt;
One of our tour guides spent three years in Tikrit, Iraq. Now he is
wintering at the Pole — from +130 F to -100 F. I expect his situation
to be safer here.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5365798182_4b96299cc6_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5365798182_4b96299cc6_o_hu_59bacc765aad69c7.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Satellite Uplinks
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5365194393_4fe034e423_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5365194393_4fe034e423_o_hu_12cba0515dbd920f.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
John and James approach the SPTR Dome
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5365802770_b112e31af7_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5365802770_b112e31af7_o_hu_1e34bca935d6662f.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
John Vader
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>A Place That Wants You Dead</title>
      <link>http://johnj.com/posts/a-place-that-wants-you-dead/</link>
      <pubDate>Mon, 17 Jan 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/a-place-that-wants-you-dead/</guid>
      <description>&lt;p&gt;
Sunday, Jan. 16 2011 11:32 p.m. UTC&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5361440207_200b747959_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5361440207_200b747959_o_hu_cf547ebe4bbcc724.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Marathon finish line at the Geographic Pole
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
It’s a little before the lunch rush here in the galley and I’m using a
bit of the quiet time here to write today’s post. From where I sit I
can see nearly half the entire horizon — as close to a completely flat
line as you can get, apart from being on an ocean-going boat, I
suppose. There is a meditation technique in which one raises one eyes
to whatever horizon, real or imaginary, is in front of one, and one
simply watches thoughts arise and fall away. That horizon is nowhere
more perfect than here.&lt;/p&gt;
&lt;p&gt;
The minimalism of the view means that any human construction (antenna,
caterpillar tractor, futuristic building, or any of the many thousands
of flag markers), no matter how distant, stands out in relief. That
visual fact underscores a notion I have about this place. Except for
featureless plains of snow, a wide-open sky, wind, and extreme cold,
one’s experience of this place is almost exclusively that of humans
and human-made things. No trees, no terrain, no insects or animals, no
smells, nothing — except what we have brought here. In this way, this
alien location is perhaps the most &lt;em&gt;human&lt;/em&gt; place I will ever
visit. Music in the galley, jokes over email and posted on the
corridor walls, footsteps in the hallway outside your room while
you’re trying to sleep, the fuel smells mixing with food cooking in
the galley, one’s own body odors and those of one’s colleagues, and,
most of all, one’s own mundane or esoterically technical work — these
are the parameters of life here. The strange irony of this place is
that it is all fellowship and craft, in one of the harshest spots on
Earth.&lt;/p&gt;
&lt;p&gt;
There is &lt;a href=&#34;http://www.nytimes.com/2011/01/16/world/16pole.html?_r%3D1&amp;amp;scp%3D2&amp;amp;sq%3Dsouth%2520pole&amp;amp;st%3Dcse&#34;&gt;a New York Times article&lt;/a&gt; today about Antarctic tourism
commemorating Scott’s and Amundsen’s expeditions here:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Despite the potential circus atmosphere, some veterans insist that
Antarctica is not for novices.&lt;/p&gt;
&lt;p&gt;
“It’s a place that wants you dead,” said Robert Swan, an
environmentalist who walked Scott’s route to the South Pole
in 1985. “Scott found that out 100 years ago.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
True enough — particularly for tourists who try to walk, ski, or drive
here (yes, people do drive to the South Pole from time to time). But
for us, ensconced relatively comfortably in this space station /
aircraft carrier / submarine, it is certainly less hazardous than it
was for Amundsen and Scott, and nothing more than human. When we visit
the stars, we will take everything about ourselves with us… and that
may provide the biggest challenge, and the biggest joy.&lt;/p&gt;
&lt;p&gt;
Yesterday after dinner I took a turn in the dish pit washing
dishes. The galley serves 200 people for dinner and so there is a real
after-dinner rush for the dishwashers; they rely partly on volunteers
on Sunday (and Ricky, one of the dishwashers, had just finished
winning the marathon). It was a pleasure to work fast, with my body
and hands, to feel warm water and the spray of errant droplets on my
face. Computer work is exceptionally hard to do with full-body
awareness, but when washing dishes that awareness is an easy
pleasure. Fleetwood Mac off of someone’s iPod kept the beat. The
gratitude of the galley staff was palpable. It was a high point of
this trip, simply to turn dirty dishes into clean ones.&lt;/p&gt;
&lt;p&gt;
The lunch crowd is building. Time to eat.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Marathon</title>
      <link>http://johnj.com/posts/marathon/</link>
      <pubDate>Sun, 16 Jan 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/marathon/</guid>
      <description>&lt;p&gt;
Sunday, Jan. 16 2011 1:11 a.m. UTC&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5358823504_5c890c647f_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5358823504_5c890c647f_o_hu_d91bc2be5c73ef91.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
I just got back from running in/photographing my first South Pole
marathon: temperature -18F, windchill -41F. Every year there is a
Christmas Day race here called the Race Around the World. The winner
gets to go to McMurdo and run in a marathon there (and usually wins,
since they are trained at high altitude). But flights yesterday got
cancelled because all the Hercules C-130s had to go out to field
camps. Since “our” runner couldn’t get to McMurdo, South Pole is
having its own marathon right now… outside. Starting gun was an hour
ago and they are still out running. I ran the first mile or so (lungs
still hurt!) and then cut across the course to photograph the leaders
and, well, everyone else — there were only ten or so of us.&lt;/p&gt;
&lt;p&gt;
It was so fun! Probably not the safest or sanest thing I’ve ever done,
but I’m very glad I did it. It was made even more exciting by the fact
that we raced the clock to get the first 84-string IceCube run going
just before the marathon. I literally had to run to my room to get
dressed and then out to the Geographic Pole marker to make it in time
for the start. The Station doctor gave a short exhortation to stay
safe before we started… hopefully the people still out there are being
careful! The station turned out to provide water stops, sleeping bags,
toilets, aid stations, cheering and photography.&lt;/p&gt;
&lt;p&gt;
There is a lot more I want to write about but I need to use the rest
of the satellite pass for other things, so hello to everyone and good
luck to the runners!&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5358210337_e1ed8d33e7_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5358210337_e1ed8d33e7_o_hu_b4dc69aa8f6e4df3.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Yours truly after 1/26th of the maraton
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Deep Fried Macaroni and Cheese Balls</title>
      <link>http://johnj.com/posts/deep-fried-macaroni-and-cheese-balls/</link>
      <pubDate>Sat, 15 Jan 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/deep-fried-macaroni-and-cheese-balls/</guid>
      <description>&lt;p&gt;
Friday, Jan. 14 2011 11:22 p.m. UTC&lt;/p&gt;
&lt;p&gt;

&lt;iframe src=&#34;http://player.vimeo.com/video/18768574?byline=0&amp;amp;portrait=0&#34; width=&#34;512&#34; height=&#34;288&#34; frameborder=&#34;0&#34; webkitAllowFullScreen allowFullScreen&gt;&lt;/iframe&gt;
&lt;/p&gt;
&lt;p&gt;
Today is showtime, with several special calibration runs happening, so
I leave you with this video taken yesterday of the flight taking the
IceCube drillers back to McMurdo Station (best in HD).&lt;/p&gt;
&lt;p&gt;
Today’s cool song in the galley: Curtis Mayfield, “Pusher man.”&lt;/p&gt;
&lt;p&gt;
Today’s lunch highlight: deep fried macaroni and cheese balls.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5403780992_829ee33f2d_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403780992_829ee33f2d_o_hu_aa08156fb969ea30.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Sebastian grapples with some analysis code.
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5355244505_381eae3f08_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5355244505_381eae3f08_o_hu_d255689c58c0f0e8.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Would you buy a used, cubic-kilometer, high energy neutrino detector from this man? (Photo: Mark Diercksens)
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Retrograde</title>
      <link>http://johnj.com/posts/retrograde/</link>
      <pubDate>Thu, 13 Jan 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/retrograde/</guid>
      <description>&lt;p&gt;
Thursday, Jan. 13 2011 12:59 a.m. UTC&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5350701784_b7a59e51cd_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5350701784_b7a59e51cd_o_hu_4805405468493939.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Retrograde cargo as seen from the roof of the ICL
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
I have been here a week and my trip is half over! The trip is actually
going quite quickly. One big mercy compared to previous years is that
I have slept relatively well, 7 hours of sleep a night which is better
than usual for me here.&lt;/p&gt;
&lt;p&gt;
Went out to the IceCube Lab this morning to show new arrival Mark D.
around. From the roof of the ICL one can see orange flags, spread
out over 250 acres, indicating the position of each of the 86 IceCube
strings. Until you survey the scene that way it is difficult to get an
adequate sense of the scale and strangeness of this whole endeavor.&lt;/p&gt;
&lt;p&gt;
Tomorrow we may already be able to attempt runs with the complete
86-string IceCube detector, which will be a pretty exciting
milestone. Other than that there is not too much to report, so I will
keep today’s entry brief and catch up with you again tomorrow.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5350084953_63cc2f322b_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5350084953_63cc2f322b_o_hu_8156151ee0caee78.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Mark D. and South Pole Telescope/Dark Sector Lab. Note position of IceCube Strings as marked by orange flags.
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5350700870_ce4a531a47_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5350700870_ce4a531a47_o_hu_a7503cba11716184.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
The author posing as an alien from Planet Earth
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Three</title>
      <link>http://johnj.com/posts/three/</link>
      <pubDate>Wed, 12 Jan 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/three/</guid>
      <description>&lt;p&gt;
Wednesday, Jan. 12 2011 1:12 a.m. UTC&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5347330755_5d2b451b41_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5347330755_5d2b451b41_o_hu_f038ce05f0d9c532.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Geographic South Pole
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Today will probably be another short post since it’s getting late in
the satellite pass. I’ve been outside three times already today —
first for a morning jog out to the IceCube laboratory (ICL), then to
take the obligatory “hero shots” out at the Pole markers (there is a
geographic pole marker, which moves every year as the ice, with the
Station and everything else, gradually glides towards some distant
oblivion in the Southern Ocean; and the Ceremonial Pole a few dozen
meters away which is ringed with the flags of signatories of the
Antarctic Treaty). Finally, I went out to meet Mark D., a new
collaborator from Belgium who I hadn’t met before. On his plane were
half a dozen “DVs” — Distinguished Visitors, which in this case
included reporters from the National Science Foundation and National
Geographic, which may stroll by here any moment.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5347936276_39dff315b8_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5347936276_39dff315b8_o_hu_e35f4e0e639178d3.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
IceCube Laboratory
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
It was interesting going out to the ICL and seeing all of the strings
cabled to computers there. It looks quite well organized and
impressive to me, very 21st Century, and I thought of how far we’ve
come since the AMANDA days in the 1990s when we ran everything off of
a Macintosh desktop computer. We have perhaps several thousand times
as much computing power on the Ice now, and though there are plenty of
loose ends and improvements to be made, I think the overall design is
correspondingly more advanced, robust and complete.&lt;/p&gt;
&lt;p&gt;
Yesterday we collected some test data to pave the way for the first
runs of the full 86-string detector, which required some trial and
error but which were ultimately successful. Progress is being made,
though schedules might be a bit tight if we are going to get the first
full runs in before I leave in little over a week (!).&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5347938956_8712a11555_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5347938956_8712a11555_o_hu_51881bf7ba3a17db.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
South Pole Architecture (Jamesways)
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Transitions</title>
      <link>http://johnj.com/posts/transitions/</link>
      <pubDate>Tue, 11 Jan 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/transitions/</guid>
      <description>&lt;p&gt;
Tuesday, Jan. 11 2011 12:44 a.m. UTC&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5344704898_0a729a27d6_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5344704898_0a729a27d6_o_hu_caaaa3ec97b79b5d.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Scoop and Polie
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Things are starting to get more hectic here for me, with various
special runs, feature requests, new arrivals (including some
journalists arriving tomorrow), not to mention “House Mouse” duties
(station cleaning duties which we all share in addition to our normal
“jobs,” whatever they may be). I am trying to stick to a schedule,
which so far seems to be working: wake at 6:30 or so, go for a walk
OUTSIDE, stretch and light weights in the gym, sitting meditation,
followed by a quick breakfast and the 0800 IceCube meeting, after
which I start on whatever items take the highest priority of the day
(I am not getting to the medium or low priority items very often).&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5344095015_86c5437246_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5344095015_86c5437246_o_hu_a31c2a29e5da81ab.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Ben and Hutch say goodbye before the passenger flight departs.
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
The morning walks are quite nice, a sort of continuation of what I do
some mornings in Hyde Park, though I should wake up a bit earlier here
so they aren’t rushed. It is very quiet outside that time of day (I
suppose that might be strange to hear given the remote location, but
there are times when the flurry of C-130 flights, snowmobiles,
caterpillar tractors, pedestrians, adventurers on skis, etc. make the
place almost seem crowded), and there is a lot to see. If you keep
moving and don’t stop TOO often for pictures, it can be warm enough
that you keep your parka unzipped (it’s still quite warm here, just
below -10F or so). Since my own work here doesn’t require me to work
outside much, it’s good to have a habit of going outside — otherwise,
it can start to feel like living in a submarine or an aircraft
carrier.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5344099661_25eb5dc204_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5344099661_25eb5dc204_o_hu_a420b65f9748fe60.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Spoolhenge
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>The Future</title>
      <link>http://johnj.com/posts/the-future/</link>
      <pubDate>Mon, 10 Jan 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/the-future/</guid>
      <description>&lt;p&gt;
Monday, Jan. 10 2011 12:05 a.m. UTC&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5340553129_1848504cf2_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5340553129_1848504cf2_o_hu_8a607f806df3de2e.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Destination Alpha
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
I have a few minutes before today’s passenger flight arrives. Several
&amp;#39;Cubers are leaving on this flight and are very excited to go (some
have been here since November). One colleague says the last thing he
does on the last day is strip the linens off his bed — and only when
the flight is 20 minutes out and there is no danger of it going back
to McMurdo without landing and picking up passengers. Some new people
are arriving too and I will go out to meet them.&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5340551951_50bd87d933_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5340551951_50bd87d933_o_hu_dc05243281fba5e4.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Work has been going reasonably well from my standpoint. Until the last
seven strings are handed over, I am basically supporting the WOs [winter-overs] and
others and trying to catch up with my backlog of programming
tasks. Once the final set of strings is tested, then it will be my job
(with one other fellow and the winter-overs) to bring those new
strings in with the other 79 and to test the completed detector for
the first time. Jim H. gave us a bottle of champagne to celebrate the
first 86-string IceCube test run — this will be a real milestone and
I’m excited to get there, having worked on this project for many
years.&lt;/p&gt;
&lt;p&gt;
Last night some colleagues gave the Sunday Science Lecture in the
Galley and described a new neutrino telescope in the very early stages
of construction here at the Pole. It will use radio frequencies rather
than light to detect the very highest energy neutrinos. Since the
target neutrino energies are so large (and the particles themselves
are correspondingly so rare), the radio detector will be 80 square
kilometers in size — which makes IceCube (at 1 km squared) look like a
potato chip. The technologies differ in many ways from how IceCube was
built and is operated; hey are exploring the use of solar and wind
power to energize the stations, since it will be very difficult to
supply power over such a wide area. It was neat to get a glimpse of
the future.&lt;/p&gt;
&lt;p&gt;
Talking to the drillers and other IceCube folks I can sense a slightly
bittersweet feeling in the air. The task of drilling and deploying all
of IceCube, which seemed extremely daunting in 2005, is now done
successfully, with a remarkable safety record, on schedule and on
budget. It is a big victory, but we will all be doing other things
sooner or later, and as with all accomplishments I think that along
with the sense of victory there is a small sense of loss in completion
of the task. This enterprise which consumed so much of the attention
of so many of us for nearly a decade is entering a very different
phase. The completed experiment will continue to run for the next
10-20 years and will continue to measure some of the most esoteric and
mysterious fluxes of energy detectable by current methods, in the
hopes of discovering new sources of neutrinos, and possibly stranger
kinds of matter as well (supersymmetric particles, monopoles,
…). Meanwhile, many of us who are not as concerned with the actual
analysis per se will be moving on to other pastures. (As someone
active in the actual operation of the detector, I currently still have
a lot to do, but this, too, will eventually change, as things become
more streamlined.)&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5340556717_3ed06e0480_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5340556717_3ed06e0480_o_hu_5c7dc42c0d6b1db9.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Sunday</title>
      <link>http://johnj.com/posts/sunday/</link>
      <pubDate>Sun, 09 Jan 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/sunday/</guid>
      <description>&lt;p&gt;
Sunday, Jan. 9 2011 1:50 a.m. UTC&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5337086857_16b7103924_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5337086857_16b7103924_o_hu_6a3cd0cfb5d73760.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Fire Sleds
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Today most people on station have the day off; some &amp;#39;Cubers are
working, though — I’m taking it a bit easy to try to finally overcome
the twin poisons of altitude sickness and paucity of sleep caused by
the usual jet lag, lack of nighttime, noise on station, exhaustion, &lt;em&gt;et cetera&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;
Yesterday a large group of us had snowmobile training, focused largely
on the rules (helmets for all drivers &amp;amp; passengers always; 10 mph
speed limit), how to inspect the machine before driving it, and how to
start two different kinds of snowmobiles (pull-starters only —
batteries really don’t work well down here, and you have to leave the
machine idling when you get where you’re going, or you might not get
it started again).&lt;/p&gt;
&lt;p&gt;
Hmm, something has come up which needs my attention, so today’s post
will be short (I have to post it now before we lose satellite
connectivity). Talk to you tomorrow.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Radio Waves</title>
      <link>http://johnj.com/posts/radio-waves/</link>
      <pubDate>Sat, 08 Jan 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/radio-waves/</guid>
      <description>
&lt;p&gt;
Friday, Jan. 7 2011 6:12 p.m. UTC&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5403748408_a2c6c3ccca_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403748408_a2c6c3ccca_o_hu_226305f57823d6cd.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Radio measurement
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Woke up before 0500h to do some work on the detector and get caught up
on emails &amp;amp; such. Today’s post is going to be brief since it is almost
time for breakfast and the morning meeting.&lt;/p&gt;
&lt;p&gt;
Last night was the first time I’ve worked (or even gone) outside since
arriving the day before. Sebastian and I did some radio noise
measurements out in Summer Camp (a collection of Korean-War-era
Jamesways, wood-frame-and-canvas buildings, caterpillars rattling to
and fro around us). It was fun to be out there but yikes, COLD since
I’m not used to it (about -40C/-40F right now with wind chill). Eyes
tearing, struggling with 4 different head coverings, multiple glove
layers, taking pictures, working with equipment — it’s a matter of
reacquiring simple motor skills with new parameters before you can do
anything efficiently out there on the snow. I just spoke to our drill
manager, who runs 4 miles outside here regularly… I’ll be quite lucky
if I can get that far on the treadmill in the gym by the time I leave.&lt;/p&gt;
&lt;p&gt;
Yesterday afternoon I headed through the lounge to the
bathrooms. There was a thing floating in the air, like a soft white
spider or some kind of pale insect. I watched it for a second with two
other guys, and realized it was a down feather, probably from some
pillow somewhere. We all chuckled, and one of the guys said, “I wish
it was alive — I’d capture it and put it in my room.” Sort of sums it
up. I saw a few baby plants in the greenhouse, but other than that,
it’s just us humans down here.&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-1&#34;&gt;
More pictures from the trip out to Pole
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-3&#34;&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-4&#34;&gt;
&lt;h4 id=&#34;headline-2&#34;&gt;
To the plane
&lt;/h4&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-4&#34;&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5403619074_3bf0e66d40_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403619074_3bf0e66d40_o_hu_543613595c71f50c.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Ivan the Terra Bus
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5403004429_a20e188967_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403004429_a20e188967_o_hu_1804832e3d38795c.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-4&#34;&gt;
&lt;h4 id=&#34;headline-3&#34;&gt;
From the air
&lt;/h4&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-4&#34;&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5403188143_f835463586_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403188143_f835463586_o_hu_744d1ad4b16fe132.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5378700943_805910a102_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5378700943_805910a102_o_hu_115084c2c76283ae.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5403751170_acecce77a5_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403751170_acecce77a5_o_hu_a8f95b291340e240.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5403617630_b10c2cc28f_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403617630_b10c2cc28f_o_hu_b0d5e836fdcf48c2.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5403612432_f23fea2cde_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403612432_f23fea2cde_o_hu_1b5d0a956397cd22.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5403001261_bce8a7ca9f_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403001261_bce8a7ca9f_o_hu_75d604367ffdb40d.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Settling In</title>
      <link>http://johnj.com/posts/settling-in-2011/</link>
      <pubDate>Thu, 06 Jan 2011 17:59:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/settling-in-2011/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5403774998_7ab04070cf_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403774998_7ab04070cf_o_hu_bbd028137fd8597c.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Been here about nineteen hours and am settling in, though I have yet
to do any real work. The current barometer reads 10,369 feet and,
while I really felt the altitude last night, today I feel almost
normal. My dorm room is noisy as usual, and not light-tight (recall
that it is always daylight outside), but somehow I managed to sleep 6
hours or so, without earplugs.&lt;/p&gt;
&lt;p&gt;
The first couple of days you are supposed to take it real easy and I
know from experience that I need to do that. Headaches, dizziness and
shortness of breath are common (I always seem to get the headaches,
though “vitamin I,” aka Advil, has been my friend so far); less common
are more serious forms of pulmonary or cerebral edema which we won’t
get into here but which we’re all taught to be on the lookout for
symptoms of so they can put us on oxygen if need be.&lt;/p&gt;
&lt;p&gt;
But, happily, so far so good. The first hour or so is exhilarating —
to get off the plane and see the wild stark alienness of this place
(but so familiar, too!) is such a joy and a thrill — to be met by
colleagues is also very nice (thanks Jim H. and everyone else who came
out to meet us) — then to be handed my packet inside the station and
sent off to settle into my room (I am in the station again, which does
make life easier — some people have to stay out in “Summer Camp,” a
few hundred meters away, where the toilets are in separate
buildings. Done that, don’t need to do it again).&lt;/p&gt;
&lt;p&gt;
Many familiar faces here — people I have seen for years but whose
names I don’t know, plus of course my colleagues from
IceCube. Winter-over Freija exclaimed with relief, “we’re so glad
you’re here!” which was gratifying. It’s great to see people in
Madison when I get up there a few days a month, but here it’s a real
treat to see familiar friends and faces.&lt;/p&gt;
&lt;p&gt;
After a few hours, the altitude really starts to hit. After dinner in
the galley, I holed up in my tiny room with a copy of “Iron Man II”
and went to bed.&lt;/p&gt;
&lt;p&gt;
Given the recent days of travel, I have a long backlog of things to
do, and some preparations to make for the work at hand which I will
try to detail in a future post. Now I need to do my morning routine
and get ready for the morning meetings.&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5403610596_ec4acce7fb_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403610596_ec4acce7fb_o_hu_e0a6d20cb44dab07.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5403601918_5238173f08_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403601918_5238173f08_o_hu_c366d64e87cdfeb9.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5403626290_e66443e874_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403626290_e66443e874_o_hu_881fe765802208fa.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5403624220_07485fc848_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403624220_07485fc848_o_hu_d9d1236e51a2356e.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5403603006_bd7defc363_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403603006_bd7defc363_o_hu_59727e6c5c3cd614.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5403023267_d86f07cfb0_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403023267_d86f07cfb0_o_hu_7b5a078f0a4df9a2.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5403029029_563ba6498a_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403029029_563ba6498a_o_hu_ea065f2b56c0613.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5403024925_265e382309_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403024925_265e382309_o_hu_d5c0c501b9a717fe.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5403003729_55715e373c_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403003729_55715e373c_o_hu_4dfe6a53f9018a7a.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5403620964_85dd853574_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403620964_85dd853574_o_hu_4fe04158180388cb.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5403022587_5d98a1882a_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403022587_5d98a1882a_o_hu_c62cabc9bd7d5913.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;figure&gt;

&lt;iframe src=&#34;http://player.vimeo.com/video/18449151?byline=0&amp;amp;portrait=0&#34; width=&#34;512&#34; height=&#34;288&#34; frameborder=&#34;0&#34; webkitAllowFullScreen allowFullScreen&gt;&lt;/iframe&gt;

&lt;figcaption&gt;
Another video from the C17 flight to McMurdo
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Revolution Number Nine</title>
      <link>http://johnj.com/posts/revolution-number-nine/</link>
      <pubDate>Thu, 06 Jan 2011 00:46:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/revolution-number-nine/</guid>
      <description>&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5403596908_021836421a_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403596908_021836421a_o_hu_b4083b19787f4637.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
The Emperor and I
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
If you are reading this post, then we have made it to the South Pole.&lt;/p&gt;
&lt;p&gt;
At the moment we are airborne on Flight P-106. There are 17 of us
today plus a palette or so of cargo, with plenty of room on the C-130
to spread out. I, for one, am standing in the middle of the plane,
with the laptop perched atop some bags. A few others have found spots
on the floor or are checking out the flight deck one by one.&lt;/p&gt;
&lt;p&gt;
Yesterday’s blog post was written in Crary Lab, still one of my
favorite places on the Ice. A building in multiple wings or “Stages”
which reminds me of the architecture from “Space, 1999” (now you know
how old I am if you didn’t already), the lab is Ground Zero for much
of the science carried out in Antarctica, with dozens of different
rooms, each serving various support roles for biology, physics,
astronomy, meteorology, geology, vulcanology and probably even
sociology. Stuffed penguins, seal skulls, fish in formaldehyde jars,
dried sea sponges, alternately shiny and encrusted instruments from
days of Antarctic yore, and similar artifacts are on display at
various locations, as are posters from dozens of science projects and
even a few lovely oil paintings of landscapes which can be reached by
helicopter from McMurdo.&lt;/p&gt;
&lt;p&gt;
The top floor of Crary has enormous picture windows looking out over
the nearby mountains — Black Island, White Island, Mount
Discovery. This is a great place to sit and work if you get stuck in
McMurdo for a few days.&lt;/p&gt;
&lt;p&gt;
One of my favorite labs in Crary is the aquarium, where there is a
“touch tank” containing sea creatures such as anemones, small fish,
sea stars, something which looks like an ocean cockroach larger than a
sparrow, and extremely alien-looking orange sea spiders, things which
are all legs, very creepy and fascinating.&lt;/p&gt;
&lt;p&gt;
After exploring Crary and touching the sea monsters, we headed off to
the cafeteria for a dinner of butter chicken, dal, and various vegan
salads — I am trying to eat healthy this trip, and I think so far it
has paid off in terms of overall energy and fitness despite the truly
whacked sleep schedule. Following dinner was Bag Drag, which is an
extremely aptly-named procedure (it involves schlepping all your Bags
and is a Drag) which is more or less the equivalent of what you do
when you check in your bags at any commercial airline, except that
they weigh you with your Extremely Cold Weather (ECW) gear as well.&lt;/p&gt;
&lt;p&gt;
After Bag Drag, Sebastian and I hiked up Observation Hill to see what
could be seen. The town below was stretched out in all its glory like
an Alaskan stevedore’s acid-trip version of a malignant model train
layout, a matrix of pale oranges, greens and dusty browns spattering
the basin between Arrival Heights and Ob hill, the distant sounds of
construction equipment competing with the wind and our conversation as
we slowly climbed, shooting lots of pictures on the way. We talked
about the early Arctic and Antarctic explorers and the race to be “the
first,” and how those missions (and, in smaller ways, the current
expeditions across the Ice, which strive to be the first person or
group of category X or nation Y to traverse such-and-such piece of
Antarctica) are similar to the field of High Energy Physics, where the
first person (or, almost always, group) to discover a new particle or
breakthrough result, gets the “prize” — the prize being all the
credit, or in rare cases the actual Nobel Prize. The drive to be the
first seems to be a key driving factor in both science and
exploration, but seems to me actually somewhat antithetical to the
true collaborative nature of each (collaborative in that the teams
involve several or many people, but also in that multiple teams have
to try in order to reach the extremely challenging goal, since some
teams will fail). IceCube is a collaboration of a few hundred people,
and, having experienced both collaboration and competition in spades,
I have found, perhaps as a result of getting older, collaboration to
be a much more satisfying mode.&lt;/p&gt;
&lt;p&gt;
We also considered the difficult question, what is the intrinsic value
of large science projects in Antarctica (or elsewhere)? IceCube cost
upwards of $270 million US to build (not including future operations),
which could have been used for other science projects, or, say, for
several schools on the South Side of Chicago — or for a small fraction
of a new fighter jet. Comparing schools with neutrino detectors is
difficult, not just because they are so different from each other, but
because the things they attempt to do are, as they say on the Master
Card ads, truly priceless. What would you pay to give your child a
safe and good education and prepare them for a good life? What would
you pay to allow humanity to understand the intricate and gorgeous
workings of the universe? What would you pay for peace (for I do think
that cooperative, international ventures such as science in Antarctica
are conducive to world peace)? What would you pay to own a piece of
artwork you fall in love with… or to create it? For your own spiritual
awakening or that of others? In today’s world, these things all take
money, and it boggles my mind somewhat to contemplate such costs… but
as I approach the work site for the project I have so long been a part
of, supported by taxpayer money and the hard work of thousands of
people, it feels appropriate, somehow, to contemplate the matter, even
if there are no easy answers.&lt;/p&gt;
&lt;p&gt;
Returned back to our dorm in Building 155 to sleep early prior to our
transport for our flight at 0645h. Around 0200 our roommate came in an
promptly began snoring. I have never heard snoring so loud — it was
like listening to the vivisection of a dying bull. Real nice guy,
though (awake). Up and at &amp;#39;em at 0530 with breakfast and then packing
up to catch the van for the hour-long ride to Williams Field.&lt;/p&gt;
&lt;p&gt;
I’m excited to see the Pole, to unpack and have a place to call home
for a few weeks, and to take a 20 second shower.&lt;/p&gt;
&lt;p&gt;
Update: just arrived safe and sound and it is good to be back! Will
post more news and pictures when I can.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Red Eye to McMurdo</title>
      <link>http://johnj.com/posts/red-eye-to-mcmurdo/</link>
      <pubDate>Wed, 05 Jan 2011 03:14:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/red-eye-to-mcmurdo/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5403027095_8d84c81039_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403027095_8d84c81039_o_hu_89b80d19200b4fe6.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
As we began our descent to Pegasus Airfield, it finally came to me,
bleary-eyed after a brief but intense bout with REM sleep, why we had
left Christchurch at the unholy hour of 11 PM rather than something
more civilized. I had chalked it up to the whimsical vagaries of
military flight schedules (picturing some tough hombre of a McMurdo
Ops flight sergeant displaying active and deliberate lack of
consideration for everyone’s sleep schedule). The clue, though, was
that the previous day’s flight also left at the same time — I realized
that they were probably putting us down when the runway would be
hardest, most frozen. The reason for the 10-day delay for the previous
groups going in was a soft ice runway. In other words, by scheduling
us as a red-eye, they were simply keeping us safe, and indeed, we
landed just fine — though I could see the “softness” (gaping holes,
actually) in the ice just off to the side as we approached the dirt
road to Scott Base.&lt;/p&gt;
&lt;p&gt;

&lt;iframe src=&#34;http://player.vimeo.com/video/18449331?byline=0&amp;amp;portrait=0&#34; width=&#34;512&#34; height=&#34;288&#34; frameborder=&#34;0&#34; webkitAllowFullScreen allowFullScreen&gt;&lt;/iframe&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href=&#34;https://vimeo.com/18449331&#34;&gt;C-17 Flight Deck En Route to McMurdo Station, Antarctica&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
The flight had its moments, despite the increasing aches, pains and
mental fogginess caused by the sleeplessness and discomfort of
multiple transoceanic night flights. I got up to the flight deck and
talked to one of the airmen for a bit. He was clearly excited to be
flying this particular mission; postings to Antarctica are apparently
highly sought after and this was the 7th continent he had flown a C17
to — repeated deployments to Iraq and Afghanistan being the norm.&lt;/p&gt;
&lt;p&gt;
McMurdo seems (in what little I have seen of it — I slept for five
hours after breakfast) exactly like I left it in 2009. After dinner
and “bag drag” (carrying ourselves and our gear up the hill to the
Movement Control Center for weighing and palletization of the cargo),
I hope to walk around and take some more pictures.&lt;/p&gt;
&lt;p&gt;
In short, we are here, safe, even slightly rested, and ready to fly to
the South Pole tomorrow.&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5402998685_8e6b60b87b_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5402998685_8e6b60b87b_o_hu_4b88a394531447ba.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5403018393_e2828a3717_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403018393_e2828a3717_o_hu_ee71f121fb1b5b5e.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/5403595058_3a38a3fc79_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403595058_3a38a3fc79_o_hu_aecca6924ed2d68c.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
&lt;a href=&#34;http://www.flickr.com/photos/eigenhombre/sets/72157625817722195/detail/&#34;&gt;More pictures&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>That&#39;s the Way</title>
      <link>http://johnj.com/posts/thats-the-way/</link>
      <pubDate>Tue, 04 Jan 2011 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/thats-the-way/</guid>
      <description>&lt;p&gt;
Thursday, Jan. 13 2011 11:37 p.m. UTC&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5353255138_42dd2961a0_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5353255138_42dd2961a0_o_hu_5308c12d9459b471.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
ARO, antenna, geographic pole marker, and pedestrian
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Satellite is up in a few minutes so I’d better prepare today’s
post. Been jonesing for a bath the last couple of days. Those 1-2
minute showers every couple of days are getting old.&lt;/p&gt;
&lt;p&gt;
We have a massive exodus of IceCube drillers leaving in a few minutes
(all but one, 21 in all) on today’s passenger flight. Hopefully they
won’t get stuck in McMurdo — the C-17 from Christchurch has apparently
boomeranged two days in a row due to weather in Mac Town. Or rather
two nights in a row, since they are still doing night flights to
McMurdo. I feel bad for those people who have had to get up in the
middle of the night several days in a row. Unfortunately I too will
probably have a night (or early morning) flight to Christchurch in a
week, unless the weather gets a lot colder.&lt;/p&gt;
&lt;p&gt;
I had planned originally to spend some posts explaining what IceCube
was and what exactly we’re doing. I guess I haven’t really done that
yet. I apologize to any readers who haven’t already heard me babble at
length about neutrinos in person; this may seem to you like an even
more random and strange endeavor than it already is. A detailed
description of our tasks here right now would probably be too
technical anyways. But a simple explanation that might suffice for now
is that we are testing the new equipment installed this year, both
deep in the ice (the final seven “strings” of light sensors, deployed
about a mile and a half below the surface), and the new computers in
the IceCube Lab on the surface, and, most crucially, getting
everything to talk to each other and perform the initial checks that
everything is working OK. After we leave, two winter-over scientists
will remain behind to run the experiment throughout the Austral
Winter, supported by a scrum of experts in the North who will reach
down over the satellite, perform periodic calibrations and software
upgrades, and generally help if/when things break from time to time.&lt;/p&gt;
&lt;p&gt;
I had expected to use some of my time here to beat down my backlog of
features to add and bugs to fix in my primary project (“IceCube Live,”
a server used to control the experiment and a Web site used to monitor
it). I have done some of that, but in reality most of my time has been
spent helping other people here… which, I suppose, is really how it
should be.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5352644941_b505277971_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5352644941_b505277971_o_hu_4e20849132936365.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Evening game of nine-ball
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/5352646105_794538b757_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5352646105_794538b757_o_hu_c2d9335bfd06af3a.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Everybody&amp;#39;s at lunch
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Favorite tunes/bands heard in the galley here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Kruder and Dorfmeister’s K&amp;amp;D Sessions&lt;/li&gt;
&lt;li&gt;Tom Waits, intro song from “Down by Law”&lt;/li&gt;
&lt;li&gt;Led Zeppelin, “That’s the Way”&lt;/li&gt;
&lt;li&gt;Sufjian Stephens, “Come On Feel the Illinois(e)” (I miss Chicago!
Not to mention hot baths…….)&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Faults in Ice and Rock</title>
      <link>http://johnj.com/posts/faults-in-ice-and-rock/</link>
      <pubDate>Mon, 03 Jan 2011 09:35:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/faults-in-ice-and-rock/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5403518166_c4ce4036e4_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403518166_c4ce4036e4_o_hu_ec543357d82d99ef.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
My stay here in Christchurch may be a short one. Arrived yesterday
afternoon to the heat of high summer and found out directly that our
clothing date would be this evening — and that we were scheduled to
fly immediately after receiving our cold weather gear. That gives just
over a day here, which is shorter than I might have liked, but which
might result in arriving at the Pole and getting settled in sooner,
which would also be nice.&lt;/p&gt;
&lt;p&gt;
The flight schedule has been screwy, apparently because of cracks in
the ice runway at Pegasus airfield. Some folks have been here in
Christchurch for 10 days waiting for a flight (lengthy delays or even
cancelled trips are an ever-present danger when traveling to
Antarctica). Another advantage to reaching McMurdo tonight would be to
avoid such a fate. I once stayed here for a week while waiting for a
part to arrive for a C-130; it was a nice vacation, but my stay at the
Pole will be short enough that to lose 10 days would be a bit of a
setback.&lt;/p&gt;
&lt;p&gt;
Speaking of cracks, I felt a small earthquake yesterday just after
arriving (we also had one in Chicago last week, followed by a
Thunderstorm on New Year’s Eve!). Evidence of the big earthquake which
hit in September is everywhere, mostly in the form of scaffolding,
missing buildings, and friendly signs saying DO NOT APPROACH OR ENTER
THIS BUILDING.&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5403518534_a57509f3b8_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403518534_a57509f3b8_o_hu_8a65d2236cf53b41.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
It is nice to smell New Zealand again. Pictures and words can convey a
bit of the feeling of being here, but I realized yesterday after
leaving the International Terminal in Auckland how much of my
experience here is tied up in smells. Part of that may have been
reinforced by the repeated shock of going from the Pole, where smells
of burning fuel, body odors, stale beer, steel, and various synthetic
things dominate, to the opulent, moist smells of the late summer air
in Christchurch. Even my hotel, the Devon, has its own distinctive and
instantly recognizable smells, whether from the flowers outside, the
cleaning substances they use, or some combination of the two.&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5403520598_40b2f4de1a_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403520598_40b2f4de1a_o_hu_5eda22d9df142daf.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
I am a bit jet lagged, but slept well. Sleeping the whole night, with
the windows open and the breeze blowing in, with no screens and only
the occasional electric tram going by, was lovely. Tonight what little
sleep I get may be on a C-17, bundled up in my red parka with a bunch
of similarly-attired humans and God knows what sort of cargo. Or, the
schedule may slip and I may sleep in a real bed again… we shall see.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Bardo</title>
      <link>http://johnj.com/posts/bardo/</link>
      <pubDate>Mon, 03 Jan 2011 02:39:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/bardo/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5402916721_83a6e80031_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5402916721_83a6e80031_o_hu_1ee54a15ea4e8cd5.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
I didn’t get a post in yesterday, because it was only January 2 for a
few hours, just before I crossed over the International Date Line. Not
to mention the fact that there was no WiFi on the flight (though
apparently some planes have that now).&lt;/p&gt;
&lt;p&gt;
My second flight didn’t take off until nearly midnight, local time. I
dread the flight to Auckland more than any other stage of the trip; it
feels like the bardo state from Tibetan Buddhism, in which one has
died and is waiting to incarnate into one’s next form — a state of
unsettled in-between-ness, which somehow passes both quicker than
expected and with excruciating slowness (a little like some meditation
sessions, come to think of it). I did manage to sleep a bit (breathe
deeply, follow the out-breath, notice thoughts and sounds,
…. zzzzz), waking at least half a dozen times, and then watched “The
Social Network,” which I enjoyed but which I dearly hope will resemble
the coming trip not in the slightest.&lt;/p&gt;
&lt;p&gt;
One sees “Ice people” in increasing amounts as one gets closer to The
Ice (slang for Antarctica). I met an IceCube colleague from Madison in
Chicago; noticed a few others at LAX and several more in Auckland. You
can tell them by their clothes (take all the geeks or professors you
know, and all the rock climbers you know, and imagine how the
intersection of those two sets would dress) and by the little yellow
penguin tags hanging off of their luggage or the red, white and blue
US Antarctic program patches on their jackets. Often we don’t talk to
one another, but there are all sorts of interesting people with
interesting stories. For example, on the flight to Auckland I managed
to sit next to the Program Psychologist on his way to evaluate the
psyches of people staying over the winter at South Pole and at
McMurdo, but didn’t know that (or anything about him) for the 13 hours
we sat together until we landed in Auckland and finally indulged in
some small talk.&lt;/p&gt;
&lt;p&gt;
In short, the trip so far has been relatively painless — by far the
worst of it was the Mexican food (and service) I got at LAX, not
realizing that they would have dinner on the plane despite the late
departure. Now I’m waiting for my flight to Christchurch and, soon,
soon! a shower and a real bed.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Chasing the Sun</title>
      <link>http://johnj.com/posts/chasing-the-sun/</link>
      <pubDate>Sun, 02 Jan 2011 03:32:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/chasing-the-sun/</guid>
      <description>
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/5403514868_5a311173e2_o.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/5403514868_5a311173e2_o_hu_47eb93eb7f5659de.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Happy New Year to everyone from the skies somewhere over the western
USA, en route to LAX. This is my ninth and probably final trip to the
Geographic South Pole, and if you’re reading this you probably know me
and know I’ve been preparing for this trip off and on for a number of
months (and, in some ways, for decades — more on that later). Now I am
finally under way, and I’m relieved to be launched and finally headed
towards whatever this journey will bring.&lt;/p&gt;
&lt;p&gt;
I have done some writing and some photography on every trip, and
published writing or photos in some form during most of them — in some
cases just emails to friends and family; more recently, in
blogs. There are a few reasons for doing this, not the least of which
is to let loved ones know where I am and that I’m safe. I also find
that the writing process helps me to capture, absorb and explore the
experience of going somewhere few people get to go. But it is also an
opportunity to give some of that experience back to all the people who
have contributed (at least in the form of tax dollars) to support me
and my colleagues in the US Antarctic Program.&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-1&#34;&gt;
This Year’s Blog
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
My intention is to post photos and text here every day for the next 28
days or so. My entries may therefore be briefer than they have been in
past years. I will try to cover some of the the basics of the trip
(why go; logistics; etc.). I also may indulge in personal musings on
the whole process and about the overall experience over the past
fourteen years. Finally, I want to invite you to contact me and &lt;strong&gt;let me
know if there is anything you would like me to explain, describe, etc.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-2&#34;&gt;
Special Goals
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
In previous years I have tried to enumerate certain personal goals or
projects in advance (in addition to objectives for work,
obviously). These goals have been things like workouts, regular
mindfulness meditation practice, art projects, places to see, books to
read, etc. I have supplies along for all those things, but for this
year I would like to set one goal, which is to be as awake as possible
to the entire experience as I can. This may mean fewer activities than
in past years, (or shorter blog posts, except for this one!); but this
is probably my last trip down here and I’d rather enjoy the things
that come along of their own accord than to try to chase around to see
or do everything I missed on previous trips (or re-do things I’ve
already done).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-3&#34;&gt;
Why Is This The Last Trip?
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Many people have asked why this is the last trip (and have pointed out
that I’ve said that every trip would be the last). This year truly is
different in that this is the last construction season for &lt;a href=&#34;http://icecube.wisc.edu&#34;&gt;the IceCube
project&lt;/a&gt; — we have deployed the final of 86 strings just a few weeks
ago, and when these seven latest strings are brought online, the
detector (already operational in limited forms since 2005) will be
complete, so there will be very little need to send people like myself
in future years (of course who knows about future projects, etc. — but
really, folks, this probably is the last time for me).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-4&#34;&gt;
How to Get Updates
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Some people have asked how they can get notified when the blog is
updated. I would prefer not to spam people’s inboxes with
notifications, since I don’t know who really wants to get a daily
update and who would rather not. So, there are a few ways which should
all work well:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Just visit &lt;a href=&#34;http://johnj.com/&#34;&gt;http://johnj.com/&lt;/a&gt; and look at the Recently Updated links;&lt;/li&gt;
&lt;li&gt;Subscribe to the RSS feed for this site (use Google Reader or other blog reading software);&lt;/li&gt;
&lt;li&gt;Follow me as “&lt;a href=&#34;https://twitter.com/eigenhombre&#34;&gt;eigenhombre&lt;/a&gt;” on Twitter&lt;/li&gt;
&lt;li&gt;If we are Facebook friends, follow my status updates;&lt;/li&gt;
&lt;li&gt;If you want just the photos, they will be posted on Flickr, possibly a day or so before a subset of the pictures make it to the blog. There is an RSS feed for just the photos, as well.&lt;/li&gt;
&lt;li&gt;If you really want an email notification, there are free services on the Web that will notify you when an RSS feed is updated, so please use one of those.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you think of someone who would be interested in the blog and who I
am not in contact with on Facebook or Twitter, please do forward them
the link to the blog.&lt;/p&gt;
&lt;p&gt;
Many thanks, and a fruitful, peaceful and prosperous 2011 to all.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Downhole</title>
      <link>http://johnj.com/posts/downhole/</link>
      <pubDate>Mon, 13 Dec 2010 12:07:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/downhole/</guid>
      <description>&lt;p&gt;
As thoughts turn in earnest to shopping and packing to depart January
1, here is a South Pole video from old times to get one in the mood
for the coming trip. This was from my second trip, 13 years ago, taken
by a camera deployed in one of the AMANDA strings, designed by our
Stockholm collaborators.&lt;/p&gt;
&lt;p&gt;

&lt;iframe width=&#34;632&#34; height=&#34;384&#34; src=&#34;https://www.youtube.com/embed/hiJVajBA9TQ&#34; frameborder=&#34;0&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Coming Out of Hibernation</title>
      <link>http://johnj.com/posts/coming-out-of-hibernation/</link>
      <pubDate>Mon, 13 Sep 2010 16:04:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/coming-out-of-hibernation/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/AE3F3E67BAA94727.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/AE3F3E67BAA94727_hu_a3f1b83d1d716466.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
I have been moving things around a bit here in preparation for my
ninth and probably last trip. (Yes, I know, I always say it is going to
be my last trip. But this season marks the end of the construction of
&lt;a href=&#34;http://icecube.wisc.edu&#34;&gt;IceCube&lt;/a&gt;, so far fewer people will be going to Pole after this austral
summer.) I am tentatively scheduled to leave Chicago for the
South Pole on Jan. 1, 2011. After taking last season off, I’m excited
to go back for one last time.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Managing the Most Remote Data Center in the World</title>
      <link>http://johnj.com/posts/managing-the-most-remote-data-center-in-the-world/</link>
      <pubDate>Fri, 30 Jul 2010 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/managing-the-most-remote-data-center-in-the-world/</guid>
      <description>&lt;p&gt;
This video is from an interview I did with James Turner at OSCON in
July of 2010.&lt;/p&gt;
&lt;p&gt;
From &lt;a href=&#34;http://it.slashdot.org/story/10/07/23/1142249/Managing-the-Most-Remote-Data-Center-In-the-World&#34;&gt;Slashdot&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;
“Imagine that your data center was in the most geographically remote
location in the world. Now imagine that you can only get to it 4
months of the year. Just for fun, add in some of the most extreme
weather conditions in the world. That’s the challenge that faces John
Jacobsen, one of the people responsible for making sure that the data
from the IceCube Neutrino Observatory makes it all the way from the
South Pole to researchers across the world. In an interview recorded
at OSCON, Jacobsen talks about the problems that he has to face
(video), which includes (surprisingly) keeping the data center
cool. If you’re ever griped because you had to haul yourself across
town in the middle of the night to fix a server crash, this interview
should put things in perspective.”&lt;/p&gt;
&lt;p&gt;

&lt;iframe width=&#34;632&#34; height=&#34;384&#34; src=&#34;https://www.youtube.com/embed/v9VUk9xB6co&#34; frameborder=&#34;0&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Ruby Plugins for Sketchup</title>
      <link>http://johnj.com/posts/ruby-plugins-for-sketchup/</link>
      <pubDate>Sat, 03 Apr 2010 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/ruby-plugins-for-sketchup/</guid>
      <description>
&lt;p&gt;
Here are some Ruby plugins I developed recently during my experimentation with
SketchUp:&lt;/p&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Auto-reload Plugin
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
The &lt;a href=&#34;https://gist.github.com/eigenhombre/8bcaff80a9e6bc08e198260308a06bd5&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;scan_plugins&lt;/code&gt;&lt;/a&gt; plugin monitors any given directory and looks for any
changed &lt;code class=&#34;verbatim&#34;&gt;.rb&lt;/code&gt; files. When your code changes, it is reloaded into
SketchUp automatically. This means you can work in your own plugin
directory, and won’t need to restart SketchUp to test changes to your
scripts.&lt;/p&gt;
&lt;p&gt;
I found the plugin-writing process somewhat frustrating because, in
order to install a new plugin, you typically have to quit SketchUp and
restart it. This is murder if you test continuously as you develop (as
we all do… right?). &lt;code class=&#34;verbatim&#34;&gt;scan_plugins&lt;/code&gt; avoids this problem.&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Caveat: because each file will be executed as soon as it is changed&lt;/em&gt;,
&lt;em&gt;the Ruby files in the specified directory should consist ONLY of&lt;/em&gt;
&lt;em&gt;SketchUp plugins! Put your Ruby-based disk cleanup programs&lt;/em&gt;,
&lt;em&gt;WEP-cracking utilities, etc., elsewhere.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
I have found this script indispensable while developing other plugins,
by greatly reducing the turnaround time for testing.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
Crowd Plugin
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
The &lt;a href=&#34;https://gist.github.com/eigenhombre/b66534dfb9057532c0b4c8b5f98c0f26&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;crowd plugin&lt;/code&gt;&lt;/a&gt; places a selected component at random throughout an
area on the x-y (red/green) plane. This was the first plugin I wrote,
just to try out the process.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/crowd0.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/crowd0_hu_34e2ef15827d76a0.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Crowd Plugin result
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-3&#34;&gt;
Current Project
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
I have been working sporadically on a set of mesh manipulation tools
for subdividing, smoothing, joining, and sculpting polygonal
meshes. Meanwhile, Subdivide and Smooth [video no longer available] and &lt;a href=&#34;https://sketchucation.com/forums/viewtopic.php?f%3D180&amp;amp;t%3D11212&amp;amp;start%3D0&#34;&gt;Tools on
Surface&lt;/a&gt; are great plugins to get you started with advanced mesh
manipulations.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>The Cruel Stranger</title>
      <link>http://johnj.com/posts/the-cruel-stranger/</link>
      <pubDate>Tue, 10 Nov 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/the-cruel-stranger/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/planetary_convergence_iii.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/planetary_convergence_iii_hu_917664088324e131.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Came across an interesting post today by author R. Scott Bakker,
writing on &lt;a href=&#34;http://www.tor.com/index.php?option%3Dcom_content&amp;amp;view%3Dblog&amp;amp;id%3D58246&#34;&gt;Tor.com&lt;/a&gt; about his novel, “Neuropath.” He has &lt;a href=&#34;https://www.tor.com/2009/11/09/a-fact-more-indigestible-than-evolution/&#34;&gt;some
interesting things&lt;/a&gt; to say about the sometimes alien and unpalatable
conclusions provided by science, an institution which he likens to a
“cruel stranger”:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;So here’s the question: What other bitter pills does science hold in
store for us? The cruel stranger isn’t finished, you can bet the
family farm on that simply because nothing is final in science. So
what other stomach churning surprises does it hold in store for us?
And what happens if it begins telling us things that are out and out
indigestible?&lt;/p&gt;
&lt;p&gt;
What if science, the greatest institutional instrument of discovery in
history, starts telling us there’s no such thing as choices, or
stranger still, selves? What if the portrait of humanity that science
ultimately paints strikes us as immediately and obviously inhuman?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
I have been long intrigued by the ability of science to dish up
conclusions in which are difficult to accept. The obvious example is
evolution, but evolution is something I personally grew up with and
actually find comforting (our literal kinship with the rest of the
animal kingdom). However, some of science’s conclusions about the
physical world are hard to swallow. Einstein, for one, could never
accept the randomness inherent in the quantum theory (“God does not
play dice with the universe”). I, for one, am pained by notions such
as the &lt;a href=&#34;https://en.wikipedia.org/wiki/Interstellar_travel#Interstellar_distances&#34;&gt;inaccessibility of distant stars&lt;/a&gt; or the notion of &lt;a href=&#34;http://en.wikipedia.org/wiki/Heat_death_of_the_universe&#34;&gt;the end of
the universe&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
The latter idea is particularly difficult and intriguing for me. As a
&lt;del&gt;non-theist with strong&lt;/del&gt; Buddhist &lt;del&gt;leanings&lt;/del&gt;, what I &lt;em&gt;want&lt;/em&gt; to believe (so
long as I have beliefs!) is that the universe will continue to
manifest forever in a sort of infinite, awesome, endless dance of
change. However, while the cosmological picture has evolved
tremendously even in my lifetime, and will probably change more, the
dominant theory (as I understand it) currently has the universe
continually expanding at ever increasing speeds under the influence of
dark energy, as the stars gradually burn out, grow cold and
dark. Ultimately, very little can happen in such an asymptotic
universe… certainly not any form of life as we can currently imagine
it.&lt;/p&gt;
&lt;p&gt;
On the human scale, one struggles to accept one’s own mortality, but
it is a comfort to think of the world continuing on. Of course, the
eventual fate of the Earth is likely &lt;a href=&#34;http://en.wikipedia.org/wiki/Red_giant#The_Sun_as_a_red_giant&#34;&gt;evaporation as the sun
expands&lt;/a&gt;. But the cosmos will always be there, with new beings, new
civilizations, or at least, the vast beauty of astronomical
phenomena. Or will it?&lt;/p&gt;
&lt;p&gt;
Forget mortality, forget the utter insignificance of humanity in the
crushing vastness of the cosmos. If the universe itself dies (becomes
static), then &lt;em&gt;change itself&lt;/em&gt; will come to an end. Where is the comfort
in that? Fortunately, cosmology as a science is truly in its infancy
(for example the vast majority of the mass-energy in the universe, in
the form of dark energy and dark matter, are still almost completely
unknown to us), so the picture will probably continue to evolve. But
what if science tells us that the universe really has a finite (if
very very very long) life span? The Cruel Stranger will have struck
yet again… and, certainly, not for the last time.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Photoshop on a Dime</title>
      <link>http://johnj.com/posts/photoshop-on-a-dime/</link>
      <pubDate>Mon, 12 Oct 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/photoshop-on-a-dime/</guid>
      <description>&lt;p&gt;
As a side benefit of transitioning back from European time since
returning home last week, I have been waking up early most mornings
and getting in a bit of painting. Some days there is nothing like
gradually improving old paintings, scumbling, glazing and blending
with some quiet music going and the sun slowly rising outside.&lt;/p&gt;
&lt;p&gt;
As satisfying as that can be, I don’t want to only rehash the same
unfinished paintings endlessly (some may be beyond help). I keep
coming back to the problem of composing new pictures — what to put in
a piece, and where to put it. When I draw (or just close my eyes),
many images or ideas arise… not to mention the thousands of photos I
take or the images I “clip” from books and the Web. But it can be hard
to knit this slurry of ideas and source material into something which
works, which has, in other words, a unique and compelling aesthetic
logic. Painting is such a slow process (at least the way I do it) that
it can be painful to make the required compositional choices once a
piece is “launched.”&lt;/p&gt;
&lt;p&gt;
I have posted before about making studies and preliminary drawings,
but I keep tweaking my methods, looking for processes which will help
generate the most compelling images (at least to me) and will add more
momentum and fun to art making.&lt;/p&gt;
&lt;p&gt;
One thing which I’ve tried before and which I returned to this morning
is the use of transparent overlays to make preliminary studies. I
first encountered this method of drawing in slides of Eric Fischl’s
work. A few years back I tried a variant of the process for composing
pictures, using transparent sheets known as Kimodesk. While trying to
add some content to a sketchbook drawing this morning, I tried it
again, and it seemed powerful and slightly magical, as if I had a
physical version of Photoshop at my fingertips:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;One &amp;#39;composes’ multiple figures, buildings, etc. quickly, simply by
moving sheets around on top of each other;&lt;/li&gt;
&lt;li&gt;You can draw on both sides of the sheet for a greater expressive
range;&lt;/li&gt;
&lt;li&gt;The surface takes graphite like soft, black butter; gouache works
too if it’s very &amp;#39;dry’ (no washes… probably oil would be fine);&lt;/li&gt;
&lt;li&gt;Unlike a drawing in a sketchbook, where you have to erase whenever
you move or change something, there is very little penalty for
making adjustments;&lt;/li&gt;
&lt;li&gt;It is easy to duplicate a picture element or series of marks;&lt;/li&gt;
&lt;li&gt;You can trace existing drawings from sketchbooks and incorporate
found photos, etc., or just run the Kimodesk directly through a
laser printer, making a nice, rich black;&lt;/li&gt;
&lt;li&gt;You can flip your drawing and see the image in reverse at any time
(a good compositional check, essentially the same looking at your
painting in the mirror&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-1&#34; href=&#34;#footnote-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Kimodesk looks really good and can be used directly in finished works
(as &lt;a href=&#34;http://website.education.wisc.edu/jdamer/index.html&#34;&gt;Jack Damer&lt;/a&gt;, who introduced me to the material, has done), but
probably glassine or other transparent paper would work nearly as well
for the preliminary drawings I’m interested in at the
moment. Unfortunately I don’t believe anybody is making or selling the
stuff at the moment. If anybody knows otherwise, please let me know.&lt;/p&gt;
&lt;p&gt;
(Why not just use Photoshop? I like Photoshop, but the lack of
physicality is offputting at times, and you have to get the images
into the computer and back out again. Plus, I already spend 99.9% of my
time in front of a computer.)&lt;/p&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr class=&#34;footnotes-separatator&#34;&gt;
&lt;div class=&#34;footnote-definitions&#34;&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-1&#34;&gt;&lt;a href=&#34;#footnote-reference-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;The eye gets used to flaws in a work-in-progress. To counter that problem, in addition to the mirror trick, some people turn their work upside down, or use a convex lens to make it look farther away. Salvador Dalí used to have his wife Gala place his paintings at surprise locations around the house where he could bump into them unexpectedly and be struck by things he hadn’t noticed about them… lacking Gala, most of the rest of us use other tricks.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Man on Wire</title>
      <link>http://johnj.com/posts/man-on-wire/</link>
      <pubDate>Fri, 09 Oct 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/man-on-wire/</guid>
      <description>&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/man-on-wire.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/man-on-wire_hu_1632932ce7641cd8.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Still from James March&amp;#39;s &amp;#34;Man on Wire&amp;#34;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Growing up in the Midwest speaking English like everyone else around
me, I always thought my native tongue was somewhat ordinary, even
ugly. In high school and beyond, I loved studying French for the
glimpses it afforded into other ways of thinking, ways which I may
have presumed were more culturally sophisticated. French was the
language of Baudelaire, of wine and cuisine, of Louis XIV and
Napoléon; of Monet, Delacroix, Ingres.&lt;/p&gt;
&lt;p&gt;
I think it took me many years of reading English prose and making
small forays into other languages (something I still enjoy) to truly
appreciate how marvelous a language English really is. For one thing,
at roughly 1 million words, it far outstrips most other languages in
terms of vocabulary (though perhaps half of those are technical
terms). The sheer lexicographic heft of English provides enormous
expressive power — when several similar words exist for the same
thing, one can choose the one with exactly the right associations or
poetic impact.&lt;/p&gt;
&lt;p&gt;
Yet, as with any language, English has words whose equivalents in
other languages are more beautiful. “Beautiful,” for example, is not a
beautiful word. It sounds a bit prim, or prissy. “Beau,” on the other
hand, is such a simple word, barely an exhale, or a sigh. It is far
superior to its English cousin, in my opinion.&lt;/p&gt;
&lt;p&gt;
“Beau” is a word you hear a lot towards the end of &lt;a href=&#34;http://en.wikipedia.org/wiki/Man_on_Wire&#34;&gt;Man on Wire&lt;/a&gt;, a
film by James March which portrays the efforts of Frenchman &lt;a href=&#34;http://en.wikipedia.org/wiki/Philippe_Petit&#34;&gt;Philippe
Petit&lt;/a&gt;, in 1974, to cross between the Twin Towers of the World Trade
Center on a tightrope. While the film itself is very well made, what
is particularly captivating is the story — how Petit and his friends
combined vision and inspiration, careful planning, stealth, stamina
and, above all, courage, to stage an act which transformed not just
themselves, but also the public’s view of the Towers.&lt;/p&gt;
&lt;p&gt;
I was somewhat incredulous to hear, years after the fact (I was only
eight years old at the time of the stunt) that someone had tightroped
between the two buildings. Now, of course, the imagery in the film is
amped and torqued in gut-wrenching ways by the ghastly absence of the
Towers themselves and the collective memory of their destruction,
burned on the retinas and the psyches on so many of us who remember
seeing them fall on live television. Yet the tears shed by the
participants in the film, interviewed decades after the fact, do not
seem to be about the fallen towers themselves, but about the purity
and intensity of the moments before, during, and after Petit’s walk,
and the beauty created, however briefly, on that day — August 7, 1974.&lt;/p&gt;
&lt;p&gt;
Seeing the film (made just last year) transforms the memory of the
Towers from one of trauma to something more like transcendence. One of
the film’s ironies is that it invites comparison between the
clandestine, overseas preparations of the youthful Petit and his
friends to what one imagines the nineteen hijackers’ final months and
days were like (it would make an interesting film to try to capture
their point of view honestly, but I doubt the world is ready for such
a film). The contrast, very vivid, and never stated in any form in the
film itself, is an obvious one: the sheer horror of Sept. 11, versus
the joy and amazement generated by the simple feat of walking between
the two buildings, more than 400 meters above the streets below. Yet
perhaps it shows the power of art that such comparisons fade when one
is shown Petit’s feat on its own terms. In the space left behind by
the towers, one imagines the space between them — and the courage
required to face imprisonment by a foreign police force or, equally
likely, death at the hands of high winds and gravity. To achieve the
impossible — not for the sake of destruction, but for beauty.
&lt;em&gt;Comme c’est beau.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>South Pole Videos</title>
      <link>http://johnj.com/posts/pole-videos/</link>
      <pubDate>Fri, 01 May 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/pole-videos/</guid>
      <description>&lt;p&gt;
For your enjoyment: YouTube videos from the last two trips to
Antarctica.&lt;/p&gt;
&lt;p&gt;

&lt;iframe width=&#34;632&#34; height=&#34;384&#34; src=&#34;https://www.youtube.com/embed/9-FNmqlttJs&#34; frameborder=&#34;0&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/p&gt;
&lt;p&gt;

&lt;iframe width=&#34;632&#34; height=&#34;384&#34; src=&#34;https://www.youtube.com/embed/Ai3FxOg3Zt4&#34; frameborder=&#34;0&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/p&gt;
&lt;p&gt;

&lt;iframe width=&#34;632&#34; height=&#34;384&#34; src=&#34;https://www.youtube.com/embed/U4qkxM4YPow&#34; frameborder=&#34;0&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/p&gt;
&lt;p&gt;

&lt;iframe width=&#34;632&#34; height=&#34;384&#34; src=&#34;https://www.youtube.com/embed/2dEmXOCGFy4&#34; frameborder=&#34;0&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Posing Rigs</title>
      <link>http://johnj.com/posts/posing-rigs/</link>
      <pubDate>Sun, 05 Apr 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/posing-rigs/</guid>
      <description>&lt;p&gt;
Been following along with &lt;a href=&#34;http://www.giantmonster.tv/giant/?p%3D425#content&#34;&gt;Justin Chin&lt;/a&gt; about how to create posing rigs
with SketchUp. Whereas he is using it to pose detailed 3D models (with
an eye to making a comic and/or film using SketchUp), my interest
relates more to orienting figures in space for paintings — placing the
masses, in perspective. So far it seems promising, though I have yet
to carry it through to a real painting.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/3guys.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/3guys_hu_a29d2ebf67ba48f6.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Posing rig example
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Though the tools are contemporary, the approach
dates at least to the 16th Century:&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/cambiaso.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/cambiaso_hu_bdc958d40bc7d1e5.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Drawing by Luca Cambiaso
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Metric</title>
      <link>http://johnj.com/posts/metric/</link>
      <pubDate>Mon, 02 Mar 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/metric/</guid>
      <description>&lt;p&gt;
Being a geek, I’ve always liked the word &amp;#39;metric.’ A metric is a
number or other quantitative object (physicists like &amp;#39;metric tensors’)
which measures something.&lt;/p&gt;
&lt;p&gt;
I have three paintings drying right now (i.e., too wet to work into
without screwing up areas). A thought occurred to me as I was
thinking about what to work on next, that the number of drying
paintings could be a metric of how artistically busy you happen to be
at the moment. Call that number of drying paintings the &amp;#39;D-number.’
If I start working on another, it would make a &amp;#39;D-number’ of four. A
moderately busy period, by my standards.&lt;/p&gt;
&lt;p&gt;
I wonder what my highest D-number has been. Seven? Surely not ten.&lt;/p&gt;
&lt;p&gt;
I like working on lots of pieces at once. When you get bored or
stuck, just pick up another. It’s especially nice if your paintings take a long
time to finish, because you might be in the wrong mood for one particular painting, 
but in the right mood for another. If you glaze a lot, you have to wait for
layers to dry (I don’t use resins because of the fumes), which artificially 
inflates your D-number.&lt;/p&gt;
&lt;p&gt;
Other painters just pick up a panel and don’t touch anything else
until it’s done. Their D-numbers are always equal to one (that is, if
they paint in oils — acrylic painting makes your D-number usually zero,
due to the quick drying times).&lt;/p&gt;
&lt;p&gt;
Then there is the U-number — the number of paintings which are
unfinished, kicking around the studio, that you hope to get around to
sometime. Mine’s probably about 15 or 20. A recent goal of mine is
to make U=0, though probably that’s a fool’s hope.&lt;/p&gt;
&lt;p&gt;
Finally, there is the I-number, which counts the paintings you plan to
do next, or sometime soon, or in a future lifetime. As Van Gogh quoted to
Emile Bernard, “the most beautiful pictures are those one dreams about
when smoking pipes in bed, but which one will never paint.”
I like to keep my I-number as high as possible — it means I’m feeling
especially inspired.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Cuba</title>
      <link>http://johnj.com/posts/cuba/</link>
      <pubDate>Sun, 22 Feb 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/cuba/</guid>
      <description>&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_3774.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_3774_hu_f541479ec82dc304.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Cuba Street Fair, Wellington
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
At the end of a few days here in Wellington, I am flying home today.&lt;/p&gt;
&lt;p&gt;
This is one of my favorite cities in the world. It has been fabulous
to see Neil and Amelia again, to go shopping (the US dollar is finally
stronger after several years in the gutter), to go to art galleries
and to walk up and down &lt;a href=&#34;http://en.wikipedia.org/wiki/Cuba_Street,_Wellington&#34;&gt;Cuba Street&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Yesterday we braved the crowds at the Cuba Street Carnival, then came
home and made dinner for some of N&amp;amp;A’s friends, including &lt;a href=&#34;https://en.wikipedia.org/wiki/S%C3%A9raphine_Pick&#34;&gt;one of my
favorite New Zealand painters&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
Friday, I met Amelia’s mum and dad and uncle. Uncle lives in US and
goes to McMurdo every year to lead expeditions on Mt. Erebus. Dad is
an amazing architect. They have a full acre quite close to Wellington,
with a garden full to bursting with strawberries and corn, and
chickens aka &amp;#39;chooks’ (your Kiwi word of the day). Mom, sure wish you
could have seen their garden.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_3778.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_3778_hu_20dfef97ff48ab74.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Cuba St. Store Display
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_3796.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_3796_hu_cbcd545fcc549b21.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Cuba St. Carnival Garlic Seller
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_3777.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_3777_hu_d3753c24a2690bf0.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Cuba St. Carnival Vendors
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_3684.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_3684_hu_bc91ca359931f221.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Cuba St. Doorway
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_3678.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_3678_hu_1426f716364c0ec0.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Cuba St. Doorway
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_3675.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_3675_hu_d63a49fc97f6b70d.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Olive Cafe
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_3752.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_3752_hu_3032b97ddf5d60dc.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Wellington Alcove
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_3733.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_3733_hu_92204599a0551f58.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Minty Chook
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_3819.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_3819_hu_df4cd72673df1452.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Neil and Amelia
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
&lt;a href=&#34;./galleries/postpole09/index.html&#34;&gt;More pictures&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
Every year at the end of my South Pole trip, primed by a bit of rest
following weeks of unceasing mental effort, and stimulated by the
intoxicating beauty of this country, I get inspired to put more effort
into my art. This year has been no exception and I’m excited to get
back into the studio.&lt;/p&gt;
&lt;p&gt;
This will be my last post of the year on this blog, but I will
continue blogging on my art blog as time and energy allow. Thanks to
everyone who followed along.&lt;/p&gt;
&lt;p&gt;
Peace!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Wickets</title>
      <link>http://johnj.com/posts/wickets/</link>
      <pubDate>Mon, 16 Feb 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/wickets/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/IMG_2964.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2964_hu_b463273201261ba7.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Monday morning and Jan, Timo and I are on the Northbound train from
Christchurch to Picton. Outside, greens and browns of grasses, dry
scrub, and trees blur together with grey skies, rain and the dun coats
of sheep. It always seems to rain during my train trips here. It’s
hard to believe that just Friday morning we were at the South Pole.&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/IMG_2983.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2983_hu_ab1f7a0f93895b82.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Thursday night, having Bag Dragged and then sweated in the sauna
(&amp;#39;Epic’ was how colleague Stephanie described that last, crowded,
lengthy steam-bath — with multiple trips outside to Destination Zulu
to photograph the steam rising off our bodies, trips which were
surprisingly pleasant despite the 260 degree Fahrenheit temperature
transitions involved), the younger crowd stayed up partying all night,
while comparatively &amp;#39;old’ folks like myself turned in for a few hours
of sleep. Friday &amp;#39;dawned’ (not a word which applies literally at South
Pole for more than one long week per year) abruptly, with the
announcement of the early off-deck of our plane from McMurdo… an
announcement which I missed somehow, but caught on the online
&amp;#39;scroll.’ Given that the flight was going to arrive, and therefore
leave, early, I spent a few minutes tracking everyone down so that
nobody would miss the flight.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2704.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2704_hu_4cc558a45ea742b1.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Anna at Bag Drag
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2720.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2720_hu_214a6abd26cb8686.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Waiting for the flight
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
The last few summer flights from Pole are somewhat bittersweet for all
concerned. The winter folks are glad to have the Station to themselves
at last, but of course it marks the beginning of eight and a half
months of isolation. The Summer crew eagerly await oxygen, moisture,
&amp;#39;freshies,’ night, family, vacation and sleep. But many of us will
never return to the Pole.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2734.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2734_hu_49ca06996ef5e74d.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Erik documents the departure
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2747.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2747_hu_ec0bde9646ffb65c.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Boarding the flight North
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Winter-overs Camille and Erik came out to say goodbye to the last ten
or so of us &amp;#39;Cubers to leave. The flight came and we huddled around in
the -50F air like a bunch of penguins until we were signaled to
approach the plane. Awash in the deafening roar of the props near the
nose of the aircraft, I turned and waved to Erik and saw his wave in
response. Then it was climb the stairway, stuff myself and my bags
into the nearest available seat, and buckle in. There actually weren’t
enough seats for the available passengers, so Stephanie, who got on
last, was pulled aside and got to experience take-off from South Pole
with the flight crew in the cockpit. After takeoff the pilots
pressurized the cabin to more atmospheres than I’d had since Jan. 20.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2766.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2766_hu_1869405dcfe9532e.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Timo takes one last picture of the South Pole
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2811.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2811_hu_71bf1a622d53b37b.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
LC-130 Flight Deck
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2815.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2815_hu_cb651599d60d411f.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Stephanie and Anna
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
We arrived at the Pegasus ice runway to overcast weather, with Castle
Rock and Ob. Hill barely visible, Mt. Erebus not at all. The Herc
disgorged us and our bags and immediately took to the air again to
land at Williams field, a mere handful of miles away. We had our
choice of rattling around on the ice outside (the weather was
certainly warmer than Pole, with Real Snow™ but rather windy) or the
&amp;#39;pax terminal,’ a grungy orange box on skis, big enough to hold fifty
or so people. After taking the obligatory photos of the various
firefighting vehicles nearby, we packed inside and settled in for the
two hour wait for the C-17 from Christchurch.&lt;/p&gt;
&lt;p&gt;
We debated whether we could feel the difference in the
altitude. Stephanie was the only one who said she felt nothing at
all. I could, as usual: I find the sensation of returning to sea level
to be a vertiginous cross between a caffeine dose, a feeling of having
come in from the rain and changed clothes, and, paradoxically, being
so relaxed I feel like taking a nap (though that last part could have
more to do with shifting from night shift to days in less than 48
hours).&lt;/p&gt;
&lt;p&gt;
To kill time we set up my laptop and fired up The Incredibles (with
subtitles, because of the noise of other people talking), the audience
eventually expanding to include a couple of non-Cubers. The C-17
arrived just after Helen and the kids were shot down in their aircraft
and &amp;#39;paddled’ to shore. The plane’s arrival meant we all felt we had
to suit up and watch the unloading and loading of cargo despite the
fact that it clearly would be a full hour before we were waved onto
the plane.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2940.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2940_hu_da93be8ac01d5e47.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Waiting to board the C-17
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
At some point each of us started to remember that it doesn’t have to
be -50F to feel extremely cold (it was probably about 20F but much
more humid than at Pole). But soon enough we were packing into the
C-17. Just before I entered the plane, I turned around and took what
may have been my last look at Antarctica: a panorama of whites and
subtle, pale grays… a few distant mountains shrouded by low-hanging
clouds, outcroppings of rock, and a handful of human artifacts out on
the airfield. Not much to look at, but special somehow in some way I
have never quite been able to articulate.&lt;/p&gt;
&lt;p&gt;
One’s first look at Antarctica is thrilling: here you are in a place
most people will never see except in pictures or on film or TV. It is
an otherworldly place whose few native inhabitants, while familiar
through media and popular culture, are quite alien up
close. (Penguins, for example, are somehow much odder &amp;#39;in the flesh’
than one would expect). The people, too, tend to be a breed apart
somehow. Many of them young, most of them white and lower to middle
class, they come from all over the world but often hail from the US
Midwest or mountain states; are often better educated than their
on-Ice job descriptions would suggest; and have robust senses of humor
and very tight social ties with one another. &amp;#39;Repeat offenders’ such
as myself tend to be both specialists who have niched themselves so
tightly into their work that they are hard to replace, and people who
cherish the sense of community that exists on the Ice. In addition to
the colleagues you know and don’t get to see except on the Ice, it is
somehow reassuring to see all those other familiar faces season after
season, even when you don’t know their names. One feels like one is
part of something, though it is hard to say what that something
is. Surely, we are there to do or to support science… but there are
geopolitical angles as well, a fact which adds a slight tinge of
artificiality to the whole enterprise. And then there is the fact that
one reason we are there is … because it is there. Antarctica is a
mountain to be climbed, a planet to visit, a river to cross.&lt;/p&gt;
&lt;p&gt;
In November, an expeditioner named &lt;a href=&#34;https://en.wikipedia.org/wiki/Todd_Carmichael#Adventure_Travel&#34;&gt;Todd Carmichael&lt;/a&gt; set off from a
coastal location called Hercules Inlet and broke the world’s speed
record for unassisted traverse to the Pole. His ski bindings broke
soon after beginning his trip, so he proceeded the rest of the way on
foot. By the time he reached the Pole he was so disoriented that he
talked to his sled and had trouble finding the station even when it
was right in front of him. A colleague interviewed him on video while
he was recovering in the medical clinic at the Pole. At the other end
of what had turned out to be a near-death experience, Carmichael
talked about endurance not just as a means to reach a goal but as a
value in itself. “Hard things are good for you too.” That value
resonates for me, and I suspect it does as well for other travellers
to the Ice.&lt;/p&gt;
&lt;p&gt;
Sometimes, after sweating through my daily session in the station’s
gym, I’d step directly outside into the cold air on the upper level
deck outside the Station. With nothing on but running shoes, shorts
and a t-shirt, someone who is warmed up can last up to a minute or two
outside without even getting particularly cold. It’s enough time to
reestablish the sense of where you are: the incredible brightness; the
view of the experimental buildings in the Dark Sector; the crossing
beacon for the skiway; a thousand half-buried flags indicating buried
cables, buildings, fuel lines; the view, off to one’s left, of Summer
Camp and the cargo berms. The cold so sharp it makes your lungs ache
to take a deep breath. A momentary flash of the South Pole, of the
diamond-crisp beauty of the place, the infinitely flat wisps of clouds
on the rim of the sky at the very edge of the world. No longer novel,
Antarctica, but personal, and deadly, and dear.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2943.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2943_hu_ac0a287c1cef5a36.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Boarding the last flight
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
The C-17 flight back to New Zealand seemed short thanks to my having
slept, sitting up, through most of it… waking often, sore, desperately
wishing for a bed, and then falling unconscious again. By the time I
woke completely we were readying for our descent into
Christchurch. People stripped out of their gear and emerged as
individuals, with long hair, piercings, tattoos, shorts, sandals. You
have to go through customs again before they’ll let you back into New
Zealand. The customs officials ask, “Did you fly to the Ice from
Christchurch?” Not being Todd Carmichael, the answer, of course, is
always yes. Night time, humidity, wait for a shuttle, then back at the
Devon, were the beckoning of the bed trumps even that first, long
shower.&lt;/p&gt;
&lt;p&gt;
The weekend was spent shopping for gifts from home, delighting in real
food (bananas, beer, fish, salads, Banoffee Pie from the Dux again!)
and, Sunday, watching a four hour cricket match at a park on the
outskirts of town. Stephanie and Suruj, both colleagues from
Canterbury University in Christchurch, were there to teach the rules
and the finer points of strategy and culture (trivia question: Who
played the first international cricket game? Answer: the United States
vs. Canada). I would always rather watch a sporting match in person
than on TV, and would rather play than watch. Suruj presciently
obliged by bringing a cricket bat and ball: at half time we took to
the field with about a thousand underage Kiwis and he taught us how to
bowl and to bat.&lt;/p&gt;
&lt;p&gt;
Now it is Tuesday and I am perched in the top floor of a house looking
out over the Queen Charlotte Sound, about twenty minutes by boat from
Picton. My gracious hosts at the Fern Ridge Homestay are Nicki and
Neil. I spent the morning walking a four-hour portion of the Queen
Charlotte Track, similar to what I did last year. Nicki took me by
boat to Torea Bay and picked me up at Mistletoe Bay. As I walked along
the Track, cicadas as large as small hummingbirds thudded against my
hat, their collective cries throughout the bush loud enough to drown
out a C-130. I also passed a six hundred year old rimu tree, a
specimen of the kind that used to cover much of New Zealand, a tree
similar in size, age and kind to the redwoods of California. On our
way back, after picking me up, Nicki stopped the boat in a small
harbor along the way to feed breadcrumbs to the herring and mackerel,
which swarmed so thick to the food that I could feel their slimy,
wriggling bodies as I swept my hand through the water.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_3102.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_3102_hu_edf6f53c3b5b094a.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Queen Charlotte Sound
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_3127.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_3127_hu_7d4c767e34f8c226.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
View from Queen Charlotte Track
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_3135.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_3135_hu_67b0e10b78abab12.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
View from Queen Charlotte Track
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_3139.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_3139_hu_824baa707802ab96.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
View from Queen Charlotte Track
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_3225.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_3225_hu_28bb523c18087f3d.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Fern Ridge still life
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
I have another night here and another day on the Sounds; then a night
in Picton, after which I take the ferry to Wellington to see Neil and
Amelia. The it’s back to winter in Chicago, which will hopefully be
almost over. I am looking forward to seeing Eden, family, friends, to
being in my studio, and to being in one place again for awhile.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_3226.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_3226_hu_85a01b7469ac786a.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Night view from Fern Ridge Homestay
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
&lt;a href=&#34;./galleries/pole09/index.html&#34;&gt;More pictures, from the Pole&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
&lt;a href=&#34;./galleries/postpole09/index.html&#34;&gt;More pictures, Post Pole&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Safe</title>
      <link>http://johnj.com/posts/safe/</link>
      <pubDate>Sun, 15 Feb 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/safe/</guid>
      <description>&lt;p&gt;
Just a quick one-liner to let everyone know I’m safely in New Zealand
enjoying oxygen- and moisture-rich air. Will post photos and more
details tomorrow or as time allows.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Broken Glasses</title>
      <link>http://johnj.com/posts/broken-glasses/</link>
      <pubDate>Thu, 12 Feb 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/broken-glasses/</guid>
      <description>&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2684.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2684_hu_782936056cd3dadb.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
South Pole Telescope
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Less than 30 hours to go before we leave, and time is whipping by so
fast my ears are starting to ring. As always, the last few days are
the big crunch time due to the fact that we have to wait for our holes
to freeze completely before turning on new strings.&lt;/p&gt;
&lt;p&gt;
Just a few hours ago we ran the first successful test with all 59
deployed strings. It was very touch and go for awhile since several
things didn’t work properly at first, but now it looks good and it’s a
big relief – the climax of the third act.&lt;/p&gt;
&lt;p&gt;
As our test was running, we traipsed out in -50F (-75F windchill) to
the Dark Sector for a tour of the South Pole Telescope. IceCube and
SPT are the &amp;#39;big two’ at South Pole and it was very cool to see the
other one. Like IceCube, SPT is a simple device by the standards of
modern physics (compared with detectors at CERN’s Large Hadron
Collider, for example) but the SPT folks are doing very exciting,
fundamental physics, using galactic clusters to probe the role of Dark
Energy in the evolution of the Universe. (Not only is the science
exciting, but their device makes a cool sound while it’s running,
unlike the IceCube counting house which just sounds like any old data
center.)&lt;/p&gt;
&lt;p&gt;
Back in the station and running our final tests now. There is enough
time to finish our tests, sleep a bit, pack and get out of here —
barely. A great season, though. If it’s the last time I come here I
will feel good about it, even though I haven’t gotten out of doors
much, at least in comparison with my earlier seasons.&lt;/p&gt;
&lt;p&gt;
The biggest technical glitch of the summer seems to have been the
breaking of my glasses this morning out at SPT. I have a spare pair,
but they are too geeky even for me. But, if looking like an uber-geek
is the sacrifice to be paid for getting 19 new IceCube strings
commissioned and running, I guess I’m willing to pay it.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2535.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2535_hu_8fccc915084ecdef.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Home Sweet Home
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2559.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2559_hu_4bfad506ff09258a.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Heading out to SPT
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2576.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2576_hu_fddb50e533bfdc6b.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Tilo
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2584.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2584_hu_2f7d35eae01d5081.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
SPT and the Dark Sector Lab
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2586.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2586_hu_44a3bfe6cd22f37b.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Martin A. Pomerantz Observatory
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2610.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2610_hu_9e4ef69a2b9ca03e.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Timo and Tilo during the tour
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2617.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2617_hu_5cb8642005792a3e.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Doin’ the SPT Shuffle
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2632.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2632_hu_54967720d7a4ba41.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
The Roof Opens
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2667.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2667_hu_1deaa042ecf03c03.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Winter-over Erik Descends from the roof of the DSL
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2694.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2694_hu_906a19f32eed91c4.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Night shift on top of the Dark Sector Lab
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2487_2.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2487_2_hu_feb0e7dd7cc84ab.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Night shift at the South Pole.
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
&lt;a href=&#34;./galleries/pole09/index.html&#34;&gt;More pictures&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>End of the Second Act</title>
      <link>http://johnj.com/posts/end-of-the-second-act/</link>
      <pubDate>Fri, 06 Feb 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/end-of-the-second-act/</guid>
      <description>&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2388.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2388_hu_a62ad5f9a0de7304.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Station as seen through the window of IceCube&amp;#39;s Ford &amp;#34;Gran Neutrino&amp;#34; truck
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Almost exactly one week to go, for me. It is sort of the end of the
second act, when you think you know what is going to happen, but
surprises can still occur, and the final conflict has yet to sort
itself out.&lt;/p&gt;
&lt;p&gt;
Things are going smoothly enough that we (the night crew) were able to
watch “The Big Lebowski” in the B1 lounge after midnight. Those who
got up early were able to see the Super Bowl (at breakfast, I caught
the amazing play just before half-time, which was enough football for
me, and got to watch all the Springsteen-style Americana with my
German, Dutch and New Zealand colleagues). I cannot actually remember
the last time I saw a Super Bowl in the US… but they are entertaining
to see here, because of all the Armed Forces Network commercials in
between plays, tempting people to reinlist. Hmmm…. Army, Navy or
Marines? So many choices….&lt;/p&gt;
&lt;p&gt;
Actually, it really is like being on a very roomy and safe aircraft
carrier in some ways. I haven’t been outside except to poke my head
out on the upper deck for a couple of days. When planes land here,
comms broadcasts the announcement that “the aircraft is on-deck.” And
then there are the two-minute &amp;#39;Navy’ showers, which I am actually
feeling used to. Though I could get used to a hot bath pretty
quickly. Fortunately nobody is shooting at us, the pay is better (for
some of us, anyways), we don’t have to salute, and, for us summer
folks, the tour of duty is mercifully short.&lt;/p&gt;
&lt;p&gt;
Though at times uncomfortable and stressful, this trip has been quite
vivid in a way, with almost a sort of real-time nostalgic feel to
it. I feel peaceful about the likelihood that it’s the last time I’ll
be here, and I find myself noticing the texture of the station floor,
the views out the windows, the galley food, the unwashed heads of
hair, the grumbling in my stomach and the smiles in the hallways of
people I’ve seen year after year, whose names I have never learned.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Pigs and Fish</title>
      <link>http://johnj.com/posts/pigs-and-fish/</link>
      <pubDate>Wed, 04 Feb 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/pigs-and-fish/</guid>
      <description>&lt;p&gt;
There is a short list of adventures one can have in the US Antarctic
program. You can experience landing in the cockpit of a C-130 (done
it). You can fly over the crater of Mt. Erebus (done it). You can go
to &amp;#39;Happy Camper’ school and learn how to sleep in your own snow- or
ice-shelter (never done it). Here at Pole you can ski out to the &amp;#39;Love
Shack’ a few miles from the Station (never done it). You can do an
outdoor hot tub in -30F and feel your hair freeze solid (done it). One
thing I’d never done until tonight was go down into the utility
tunnels underneath the station. I’ll let the pictures tell most of the
story, including the temperature (-60F). It was really cool! (And
cold.) Afterwards we had a sauna, followed by the Midrats Season
Finale with Filet Mignon, seafood skewers, stuffed portabella
mushrooms, sushi, chocalate chip cookie chocolate sandwiches, and
upside down peach cherry pie.&lt;/p&gt;
&lt;p&gt;
Life isn’t all bad at the South Pole.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2401.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2401_hu_2cb219902f4d231e.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Suiting up to hit the tunnels
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2410.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2410_hu_4cc4a0c6c489626e.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Tunnel crew
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2414.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2414_hu_c3837b585b8d38ba.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
I wish I owned this sign
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2418.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2418_hu_42526fda1fae3825.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
A half-mile long tunnel 60 feet below the snow surface
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2421.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2421_hu_3d69727ffaeeff41.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Dead end
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2427.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2427_hu_f0943422599a7601.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Stephanie &amp;amp;co.
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2430.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2430_hu_353b40a155b13a59.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Timo Griesel
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2437.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2437_hu_1fe38e2425061f58.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Deep Enough
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2454.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2454_hu_9e9a6e586962e582.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Jan Luneman
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2458.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2458_hu_ad22642b1fded3dd.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Pig shrine (yes, it’s a real pig’s head)
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2460.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2460_hu_2916ed64f5c0f3da.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
-60 F
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_7475.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_7475_hu_53cd7ef8fbf01044.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
17-year-old sturgeon with caviar: gift of the Russian base (I seem to have lost the hi-res version of this picture :-( )
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Yesterday I headed out to the IceCube Laboratory (ICL) with Thorsten
from LBNL to debug a nasty little low-level problem. We made some
progress and I took some more pictures in and around the ICL:&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2361.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2361_hu_243b352dbf6830b7.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Back of &amp;#39;DOM Hubs’ where strings are plugged into the computers, for which I had the privilege of writing a device driver
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2366.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2366_hu_6f57a1c4ea6bf19f.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Winterized &amp;#39;Seasonal Equipment Site’ (Drill Camp)
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2368.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2368_hu_449570ec9bc8aad9.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Cable conduits into IceCube Laboratory
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2370.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2370_hu_4ca7149236036b11.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Our neighbor: the South Pole Telescope (whose principle investigator lives near me in Hyde Park)
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Last Arrivals</title>
      <link>http://johnj.com/posts/last-arrivals/</link>
      <pubDate>Sat, 31 Jan 2009 07:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/last-arrivals/</guid>
      <description>&lt;p&gt;
Timo and Jan arrived from Mainz today — the last arrivals for IceCube
this season. They are working on a system within IceCube to detect
stars which explode in or near our galaxy. Our nightshift roster is
now complete.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2288.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2288_hu_59f475c963735669.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Night shift serenade
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2299.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2299_hu_4065f87d7e06367b.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
The flight arrives
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2311.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2311_hu_5142a5bdec04599b.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
OK, you can stop taxiing now (IceCube Laboratory in the background)
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2346.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2346_hu_f4560f2999dd43ea.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Passengers from the Plane
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Lily White</title>
      <link>http://johnj.com/posts/lily-white/</link>
      <pubDate>Sat, 31 Jan 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/lily-white/</guid>
      <description>&lt;p&gt;
Followup to yesterday’s post: then there are the times when you are
quietly pedaling the stationary bike in the gym while your iPod plays
your favorite audiobook, and a couple of lily-white guys
(did I mention it’s mostly lily-white guys here?) come in and crank up some
of the more vulgar and un-musical hip-hop on the gym stereo.&lt;/p&gt;
&lt;p&gt;
This is a place of compromises.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>In a Dry and Waterless Place</title>
      <link>http://johnj.com/posts/in-a-dry-and-waterless-place/</link>
      <pubDate>Fri, 30 Jan 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/in-a-dry-and-waterless-place/</guid>
      <description>&lt;p&gt;
I’ve had some of my most intense music experiences in this place,
often while working out. (Anyone else had similar experiences at high
altitude?)&lt;/p&gt;
&lt;p&gt;
Just got back from my daily workout in the darkened aerie above the
gymnasium where they were playing the U2 concert film “Live in Paris:
The Joshua Tree.” Songs from &lt;em&gt;The Unforgettable Fire&lt;/em&gt; taking me straight
back to freshman year, 1985: friendships and first loves… my
incense-filled room across the street from the hospital where I was
born; learning to program on a 256k IBM PCjr… taking my first steps on
the long, strange trajectory that lead me to this work, in this place.&lt;/p&gt;
&lt;p&gt;
Music has the power to reach across time and space, to cement and
trigger memory and to connect people, all in ways that film,
literature and visual art cannot. I wonder if Bono &amp;amp; co. could have
imagined during their concert in 1988 that their music would fuel the
workouts of a few South Polies twenty years later. That’s the way it
works, I guess… most of the time we swim in a sea of ignorance about
the effects we have on each other and the world.&lt;/p&gt;
&lt;p&gt;
Time for a 20 second shower before today’s first meetings.&lt;/p&gt;
&lt;p&gt;
And who are you that reads this? In what day / year / millenium? And
in what strange place?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Immortality</title>
      <link>http://johnj.com/posts/immortality/</link>
      <pubDate>Thu, 29 Jan 2009 07:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/immortality/</guid>
      <description>&lt;p&gt;
Despite the morning’s wind and low visibility, colleague Joanna just
arrived from Berkeley hand-carrying some cables and a special surprise
from Jerry at LBNL, carefully packaged in anti-static plastic and
bubble wrap.&lt;/p&gt;
&lt;p&gt;
It’s the printed circuit board from one of our Digital Optical
Modules, one which failed visual inspection and is therefore scrap for
engineering purposes. I.e., a nice, flat, attractive paperweight. I’m
touched, particularly because it has my name etched on it along with
those of several of my current and former LBNL colleagues, and because
I have just been told that all the the DOMs deployed in IceCube are
thus enscribed.&lt;/p&gt;
&lt;p&gt;
Though it’s not quite a burial fit for a king (not to mention the fact
that I’m still alive and kicking), our names entombed inside the polar
ice cap will endure for many millennia, far beyond the current age of
the Pyramids of the pharaohs. When some future civilization visits the
barren ruins of earth and goes prospecting for technological artifacts
in the polar ice, they will find the sigils which make up our names
and wonder at their significance. Or, in a hundred thousand years,
when the flowing river of ice finally reaches the ocean, they may rust
free of their mutual tethers and drift the ocean currents… five
thousand messages in spherical glass bottles to be found by whatever
forms of life might remain to roam the seas or shores of future Earth.&lt;/p&gt;
&lt;p&gt;
Thanks Jerry and Joanna.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Routine</title>
      <link>http://johnj.com/posts/routine/</link>
      <pubDate>Thu, 29 Jan 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/routine/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/IMG_2270.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2270_hu_d356fb14d39d0ff8.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
It’s 10:05 AM and getting close to bed time. The weather today is
strange – quite warm (almost minus 10F) but with 21 knot winds, making
the wind chill about 50 below. The snow is blowing high and visibility
is poor at times. But it’s quite beautiful.&lt;/p&gt;
&lt;p&gt;
Life is settling down into a routine, of sorts. Wake up as late as
possible, usually before dinner. Clean up room, go to gym, meditate,
have breakfast. Start work when satellite rises around 11:30 PM. Work
until mid-morning, and then wind down until I have to do it again.&lt;/p&gt;
&lt;p&gt;
Most of the other late-season &amp;#39;Cubers are on night shift. Our &amp;#39;days’
consist of testing new pieces of the detector and new bits of code,
troubleshooting, adding features, all somewhat endlessly. We have
regular consultations with colleagues up North via phone meetings and
instant messaging; and a daily 8 AM face-to-face meeting here just to
check in and make sure everyone has what they need to get things
done. There are a lot of things happening at once and it turns out I
have to orchestrate and schedule quite a bit. But, so far it’s going
ok. We have tested an additional 9 strings combined with the 40 we ran
throughout 2008. If we can get the remaining 10 more strings added in
and calibrated, that will be a good start to the winter season. In
addition, the experiment control software I wrote throughout 2008 is
starting to come together and be fully operational here.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2215.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2215_hu_c743ee93428c0639.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
IceCube Laboratory
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
One strange feature about being here is that current and past summer
seasons blend together into a sort of day-lit constancy, where the
real world up North seems not exactly unreal, but somehow parallel and
separate in both space and time. The sameness of the surroundings, the
work, and, to some extent, the people (many of the denizens here are
&amp;#39;repeat offenders’ like me) all contribute to this. Lots of people
have a summer home… mine seems to be a January slot in a late-season
population of 250 or so people dreaming of Christchurch and points
beyond. Part of the strange timelessness of this place is also the
absence of people who have been here before, never to return, and
whose spirits somehow knock about the place still.  What part of me
will be left behind when I get on that northbound plane for the last
time?&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/IMG_2161.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2161_hu_817b9c81c33d8e68.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Last night I dreamt a great rainstorm fell here. It was delightful at
first, but quickly turned terrifying because everything started to
melt and submerge. I knew that when the cold came back everything
would be frozen in place. I have no idea what that means, but images
of liquid water are powerful in a place where showers are tightly
rationed and the daily per-person water consumption is flashed up on
the video scroll in the galley.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Tourists</title>
      <link>http://johnj.com/posts/tourists/</link>
      <pubDate>Wed, 28 Jan 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/tourists/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/IMG_2196.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2196_hu_2123cbdbf5966002.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
In the next few days, the last few &amp;#39;Cubers are arriving on Station to
help us with end-of-season commissioning of the new strings. Many more
IceCube people are leaving, however… most of them drillers. It will be
nice to be here when things are a bit quieter. The winter-overs are
already talking about how great it will be when we summer folk are
gone.&lt;/p&gt;
&lt;p&gt;
Some people pay a fair chunk of change to fly here for an hour or two,
look around, and leave. Tourists, we call them. Others fly in for
McMurdo (&amp;#39;sleigh rides’) to see the place, or to work for a day. Still
others ski here from various points remote, and camp a few hundred
yards from the Station (I’ve already given a few impromptu tours to
various frost-bitten groups). Those of us here for the Summer are
called &amp;#39;tourists’ by the winter crew.&lt;/p&gt;
&lt;p&gt;
Of course, everyone is a tourist in Antarctica. Despite what repeat
winter-overs may sometimes feel, there are no true Antarcticans. We
are as much visitors here as we would be to Mars. Take away the
airplanes, and we all perish.&lt;/p&gt;
&lt;p&gt;
I have posted a video of the last string deployment.&lt;/p&gt;
&lt;p&gt;

&lt;iframe width=&#34;632&#34; height=&#34;384&#34; src=&#34;https://www.youtube.com/embed/U4qkxM4YPow&#34; frameborder=&#34;0&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/p&gt;
&lt;p&gt;
Meanwhile, a group of five or so of us are up all night, every night,
fussing with software to read out the newly-deployed strings as they
freeze in. We still have two weeks but it will go very quickly, and we
tourists will redeploy to various points North.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Passing Notes</title>
      <link>http://johnj.com/posts/passing-notes/</link>
      <pubDate>Thu, 22 Jan 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/passing-notes/</guid>
      <description>&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2268.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2268_hu_3b1591e26a8e108a.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
My room in the A4 wing of the Elevated Station
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Been here about 58 hours so far and the reason I am counting in hours
instead of days is that my sense of days is pretty shot. I have a
screwy sleep routine: 10 hours awake, 3 hours asleep. Lather, rinse
repeat. I am trying to be up at night (we keep New Zealand time here)
for the satellite hours but usually that entails a long nap in the
middle, which curtails my sleep during the day. I’ll figure it out.&lt;/p&gt;
&lt;p&gt;
Despite the goofy schedule and the altitude, last night I felt well
enough to walk with Dave out to drill camp and watch the nineteenth
and final IceCube string deployment. Being outside reminded me of how
beautiful it is here and how hard that is to see until you are
actually out in it, seeing the changing sky, the sastrugi, the myriad
structures scattered about the snow, structures which do not qualify
as architecture but are solely and completely engineering.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2213.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2213_hu_36591abb61557eb2.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Ryan takes a well depth measurement during deployment.
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Seeing the last deployment was a real pleasure, partly because I
didn’t have to work it — I was a tourist, a real treat after having
worked on perhaps a dozen or so deployments myself. It was also sweet
because the drilling and deployment went so well this year… and also
bittersweet, perhaps, because it was the last deployment I’m likely to
see. I took photos and some video which I will post as soon as I can.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2217.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2217_hu_67a4cc6b02174d47.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Heading back from the Dark Sector
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Around midnight we decided to head back. A bunch of the drillers were
driving back in the “Ford Gran Neutrino” (the modified van which
IceCube uses to shuttle back and forth to the Dark Sector), and Dave
and I squeezed in. After we crossed the skiway, the van stopped and
the drillers started discussing the expedition which was camped near
the station. A small handful of jacked-up and modified Toyota trucks
have driven here from a Russian base in support of a ski race across
Antarctica. It was decided to pay the campers a visit, so we drove the
van over there and piled out, admired their trucks, and started
talking with a member of the expedition.&lt;/p&gt;
&lt;p&gt;
Apparently about 300 people have skied, walked, or driven to South
Pole this Summer. These people live in a sort of parallel universe
which is disconnected with that of the station. They are allowed a cup
of coffee inside and not much else; and few people walk over to their
makeshift camps near the Pole marker. So it was a treat to talk to
this fellow who has had a pretty different experience in
Antarctica. After a few minutes of conversation he pointed to Sven and
said, “Hey, you’re Sven!” Then he handed him a note written on a scrap
of paper from a case of beer. It was given to him by a member of yet
another expedition which he encountered during his trip, to give to
Sven at the South Pole! We all laughed. Even though it is nearly as
empty as Mars (i.e. nearly zero people per square kilometer),
Antarctica is a small place!&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2242.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2242_hu_77c6e08a1e8e4a27.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Sven greets an expeditioner
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
After delicious burgers at Midrats, we started work. There is ever so
much to do and I am starting to get acclimated enough to be able to
focus on it. The task at hand is to connect the nineteen new IceCube
strings to the rest of the detector, and to calibrate them to prepare
for the new physics run starting April 1. Also to carry out a variety
of software upgrades and make sure everything works correctly. Also,
to report progress to the north and to coordinate all the activities
to minimize conflicts.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2263.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2263_hu_37710f15bc9b153.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Watching the Obama Inauguration
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
This evening, after another short sleep, we watched highlights of the
Obama inauguration, hand-carried on a DVD on today’s flight. (The CBS
news clips carried over the Armed Forces network carried the word
“Live!” at lower right, which was certainly ironic in this setting,
days after the fact.) It was pretty amazing to see our Hyde Park
neighbor take the oath for the Oval Office.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2265.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2265_hu_b7c010359fab1612.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
A solemn moment
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Now for a first foray to the gym, and to start into work again.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Translation</title>
      <link>http://johnj.com/posts/translation/</link>
      <pubDate>Tue, 20 Jan 2009 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/translation/</guid>
      <description>&lt;p&gt;
10:07 PM New Zealand Daylight Time and I am well-socketed into my room
in the station at the South Pole, watching videos, napping when I can,
drinking as much water as I can stomach and waiting for my body’s
chemistry to adjust to a physiological altitude of… let me check…
10,455 feet (the local air density here depends on the weather, and is
displayed continuously on the monitors and the local Web site).&lt;/p&gt;
&lt;p&gt;
To kill time while I acclimate, I just watched “Lost in Translation”
which, with its parables of jet lag and alienation, seem somehow
appropriate even for this very different destination. “Translation” in
physics means moving from one place to another. I have definitely
undergone some serious translation.&lt;/p&gt;
&lt;p&gt;
My stay in McMurdo was very short for a southbound trip — less than
twelve hours. Which suited me fine. We arrived after 10PM, fairly
exhausted from the long and crowded flight, had the usual (relatively
extraneous) briefing, and then immediately bag-dragged for the Pole
flight. The weather was pleasant and sunny, with a small stream of
water flowing downhill past the Movement Control Center (MCC) where we
weighed in.&lt;/p&gt;
&lt;p&gt;
After a brief midrats (midnight meal) we turned in for a few hours of
sleep in the dorms. Then we trudged back up the hill at 0645h to the
MCC for transportation to Williams Field our flight South. The air had
chilled quite a bit during the &amp;#39;night’ and the stream had frozen.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2034.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2034_hu_f7721650399ba8ed.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Willi Field Air Control Structures
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2036.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2036_hu_4c72190d862e60e2.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Main Street at Willi Field
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Today’s flight was quite a bit easier than yesterday’s. Two of the Air
Guard loadmasters hung out and chatted with us in the airfield cafe
while we waited for our plane to be readied, and then rode out in the
van with us. There was no briefing, just &amp;#39;get in and go.’ There were
only 7 passengers this time, so there was room to spread out after
take-off (I even got to lie down for awhile).&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2055.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2055_hu_ca122e794826ea5f.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Our ride
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
The scenery was lovely, as in previous years, but another veteran and
I compared notes and we were certain that today’s flight took a
different route up to the Polar Plateau than in the past. (I think
it’s fun to be able to know the route well enough to be able to tell
the difference with no map and no human landmarks.) Low clouds
obscured some of the terrain which made it both harder to see anything
and more beautiful, as sky and ice merged into one milky mixture
punctuated by craggy, chocolate-colored rock.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2128.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2128_hu_f8ef80ff698eeb78.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Watching the Scenery
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/IMG_2102.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2102_hu_f20df15d13791ae4.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/IMG_2078.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2078_hu_5d916ccbceb57957.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/IMG_2099.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2099_hu_124a8936ace8fe55.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

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





&lt;a href=&#34;http://johnj.com/IMG_2070.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2070_hu_b16921d3be813566.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Before we knew it the plane began its landing approach and we suited
up, goggles, balaclavas, neck gaiters, boots, glove liners, mittens,
fleece, and Big Reds (the ubiquitous parkas). Always a student of
economy of means, I enjoyed watching the senior loadmaster giving the
order to his subordinate across the plane to put on her gloves, by
wagging his leg at her and raising one (gloved) hand.&lt;/p&gt;
&lt;p&gt;
And then we were down, out, breathing those first breaths of cold,
rarefied air (an experience I will miss, assuming this is my last
trip) and looking out at the minimal snowscape punctuated by the
hyper-functional structures of South Pole Station.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2149.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2149_hu_e78d27977e03681e.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Our flight
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2150.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2150_hu_38b2f58a1386c094.jpg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Arrival at South Pole
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_1603_2.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_1603_2_hu_b98135f6a08a2fb5.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Yours truly arriving – Photo by Mark Krasberg
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Mark and Dave came out in the -21F cold to meet us, which is always
such a nice thing — to come to the end of the Earth, and see friends
and colleagues, familiar faces, to have someone carry your carry-on
while you suck your first breaths of high-altitude air, to make your
way to your room and start the slow process of unpacking and settling
in. I am here until February 13… long enough that I have to think of
it as home-away-from-home. After seven times already it should be
pretty easy.&lt;/p&gt;
&lt;p&gt;
I will post more drawings and photos soon, and will back-populate some
of the posts with pictures, so check back for updates.&lt;/p&gt;
&lt;p&gt;
Soon the satellite will be up!&lt;/p&gt;
&lt;p&gt;
&lt;a href=&#34;./galleries/topole/index.html&#34;&gt;More pictures from the flight to the Pole&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Gouache, and a new system for conquering the world</title>
      <link>http://johnj.com/posts/gouache-and-a-new-system/</link>
      <pubDate>Sun, 30 Nov 2008 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/gouache-and-a-new-system/</guid>
      <description>&lt;p&gt;





&lt;a href=&#34;http://johnj.com/gouache-redux.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/gouache-redux_hu_65eb4be3e6e0498a.png&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
Here’s my new system for conquering the world. It will solve all my
problems, at least the artistic ones.&lt;/p&gt;
&lt;p&gt;
Ingredients:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;sketchbook&lt;/li&gt;
&lt;li&gt;pencils of various hardness/thickness/sharpness&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;white gouache paint&lt;/strong&gt;, water and brushes&lt;/li&gt;
&lt;li&gt;Uni-ball micro pen&lt;/li&gt;
&lt;li&gt;Mitsubishi 0.28 micro pen&lt;/li&gt;
&lt;li&gt;2-3 &lt;a href=&#34;http://gurneyjourney.blogspot.com/2008/06/water-soluble-pencil.html&#34;&gt;Kuretake brush pens&lt;/a&gt; filled with black ink, and diluted ink&lt;/li&gt;
&lt;li&gt;Kneadable erasers&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.dickblick.com/zz215/54/&#34;&gt;Helix battery-powered electric eraser&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Presto correction pen&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.dickblick.com/zz103/16/&#34;&gt;My standard sketchbook&lt;/a&gt; (I go through several of these a year).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The system is simple. With this extremely portable set of tools I can
capture and &lt;em&gt;eliminate&lt;/em&gt; ideas freely and quickly and iterate until I
have a drawing that is worth making a painting of (or at least not
want to rip out of the sketchbook and toss into the fireplace).&lt;/p&gt;
&lt;p&gt;
In the past, what was missing was the &amp;#39;iteration’ part, especially
while working in ink. Although I sometimes lay in material in pencil
before going to ink, I find that I &amp;#39;think better’ in ink much of the
time… also, pencil drawings tend to get muddy if erased too much.&lt;/p&gt;
&lt;p&gt;
The gouache solves that by allowing you to quickly obliterate a part
of the drawing. And, unlike acrylic or white-out types of liquid, it
is easy to erase and takes graphite and brushed ink nicely.&lt;/p&gt;
&lt;p&gt;
I guess I’ve steered clear of gouache and watercolor because I like
the rich, layered textures of oil and acrylic. But I know that comic
book inkers use gouache frequently, and I’ve had fun playing with it
today.&lt;/p&gt;
&lt;p&gt;
Yesterday, at the &lt;a href=&#34;http://chicagohistory.org/&#34;&gt;Chicago History Museum&lt;/a&gt;, I saw an aerial rendering of
the 1933 World’s Fair, likely done completely in gouache. Perhaps
72“x30”, it was my favorite thing out of few thousand artifacts there
— utterly photographic from far away, delightfully graphic when viewed
close up.&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_20161217_0002sm.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_20161217_0002sm_hu_ebcde5751e707c86.jpg&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Recent drawing: gouache, ink and graphite.
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>Settling In</title>
      <link>http://johnj.com/posts/settling-in/</link>
      <pubDate>Tue, 30 Jan 2007 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/settling-in/</guid>
      <description>&lt;p&gt;
Been here a bit more than 24 hours, and I&amp;#39;m settling in. Mostly I&amp;#39;ve
been preoccupied with debugging a particularly nasty system error in
our device driver; hopefully I&amp;#39;ll have that wrapped up soon and can
join Kael, Keith and Dave in higher-level deployment and testing of
DAQ (the data acquisition software).&lt;/p&gt;
&lt;p&gt;
Once I get acclimated to the altitude I&amp;#39;ll be much happier. It&amp;#39;s been
hitting a bit harder than last year, though I took the diamox they
encouraged us to take in McMurdo. Unfortunately the diamox makes my
hands and feet and face feel like they&amp;#39;re buzzing, which is
irritating. And I&amp;#39;m generally out of breath, and have to pee
constantly (apparently the body adjusts its pH to the new altitude
this way). Out in the Dark Sector (the radio-quiet area where our
experiment is) the facilities consist of a &amp;#34;solar&amp;#34; (i.e., painted
black) toilet; the solar toilet is essentially an otherwise unheated
outhouse with a styrofoam toilet seat built over a half-buried waste
barrel. Ah, the life of luxury.&lt;/p&gt;
&lt;p&gt;
All is pretty good, though, and it&amp;#39;s fun to see familiar, sunburnt
faces with unwashed hair (remember, 2 showers per week, 2 minutes
each, folks!), and the same old tracked vehicles and space-age
buildings and the endless horizon and the great big open sky with long
simple cloud shapes a seemingly infinite distance away. I&amp;#39;m settling
in and with any luck we can start to get stuff done quickly.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Batteries and Sheep</title>
      <link>http://johnj.com/posts/batteries-and-sheep/</link>
      <pubDate>Wed, 24 Jan 2007 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/batteries-and-sheep/</guid>
      <description>&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/john-and-dave-on-anaconda-MTB-path.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/john-and-dave-on-anaconda-MTB-path_hu_d59e9c254b974474.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
John and Dave on the Anaconda MTB Path
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Photo courtesy and © Kael Hanson&lt;/p&gt;
&lt;p&gt;
With a day to kill yesterday, Dave, Kael and I put our heads together
with Sandy, our proprietress at the Devon, and decided to rent
bicycles for a trip to the ocean. Sandy said that there were a bunch
of WWII gun batteries worth seeing near the entrance to the harbor
where Lyttleton lies, south of Christchurch. That sounded pretty good
to us. Within 20 minutes the bike rental guy was there, providing us
with mountain bikes, helmets, locks, and a suggested route and we were
off, pedaling furiously first through Christchurch traffic, then up a
fairly wicked mountain grade, past residential zones at first and then
just trees, rocks, wet clouds and, when the clouds parted, amazing
views.&lt;/p&gt;
&lt;p&gt;
&lt;a href=&#34;./static/jacobsen_pole07_set1/index.html&#34;&gt;The first photo set for this trip&lt;/a&gt; will tell the story better than any
writing I can come up with - suffice it to say I was pretty astonished
that such rugged beauty lay within a vigorous pedal of
Christchurch. And, that we were all thoroughly wasted after more than
eight hours of biking up and down the mountains south of CHC
(sometimes on paths as challenging as a BMX bike course). At one
point, as we juddered down an especially challenging path, I jokingly
asked Kael if this wasn&amp;#39;t one of those team-building exercises to get
us ready for the Pole.&lt;/p&gt;
&lt;p&gt;
Of course, no blog about New Zealand would be complete without a
picture of a sheep:&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/texted_IMG_2761.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/texted_IMG_2761_hu_e76cadd7c0ad9806.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
A Sheep
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
The gun emplacements were also amazing. For reference, they are at
Godley Head south and east of Christchurch. We had to get the bikes
back by 1830h so we could only see half of what was there. I&amp;#39;ve seen
WWII defensive emplacements in southern France, on Corsica, and in
California, and these were much better preserved and much more
extensive than any I&amp;#39;d ever seen. The coolest part was a set of
underground rooms and tunnels, completely dark (Kael&amp;#39;s flashlight and
my camera focus-flash kept us oriented). Here&amp;#39;s a teaser, but do see
&lt;a href=&#34;./static/jacobsen_pole07_set1/index.html&#34;&gt;the complete set&lt;/a&gt;:&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/texted_IMG_2789.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/texted_IMG_2789_hu_8ba9e8d3297d2bd5.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Kael descending into a bunker
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Today we get our clothing, if I can actually get my battered carcass
going…. Breakfast may help.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>All for McNaught</title>
      <link>http://johnj.com/posts/all-for-mcnaught/</link>
      <pubDate>Tue, 23 Jan 2007 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/all-for-mcnaught/</guid>
      <description>&lt;p&gt;
Since its swing through &lt;a href=&#34;https://simple.wikipedia.org/wiki/Perihelion&#34;&gt;perihelion&lt;/a&gt; a few days ago, we should be able
to see &lt;a href=&#34;https://apod.nasa.gov/apod/ap070122.html&#34;&gt;Comet McNaught&lt;/a&gt; from here. Last night, a decent meal of sushi
(punctuated by green tea ice cream to die for), we went looking for
the comet in Hagley Park, a large open area ringed by trees not far
from the Arts Centre and our B&amp;amp;Bs. As the hot winds from the north
buffeted us, we saw Venus, a lovely sunset, and amazing,
hurricane-like clouds of the sort I suppose you only get to see in the
middle of the Pacific Ocean – but no comet. We&amp;#39;re going to try again
tonight. No other plans yet.&lt;/p&gt;
&lt;p&gt;
It&amp;#39;s strange to have summer, an 80 F January thaw… but nice. I&amp;#39;m
already starting to get used to it, which is a very bad idea.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Descent</title>
      <link>http://johnj.com/posts/descent/</link>
      <pubDate>Mon, 22 Jan 2007 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/descent/</guid>
      <description>&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/IMG_2680.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_2680_hu_c21c17e2e9ba770a.jpg&#34; style=&#34;width:500px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
Dawn over the Pacific
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
Dawn over the Pacific, and 30 minutes left in the Big Flight from LA
to Auckland. The first couple of hours were the worst. We had to wait
for luggage at the gate for almost an hour and I was already sore and
restless before we took off. But I managed to distract myself with
&amp;#34;Gravity&amp;#39;s Rainbow,&amp;#34; songs on the iPod, a decent dinner, a glass of
Australian chardonnay, and, most helpfully, Gregory&amp;#39;s suggested
Tylenol PM which put me out while trying to focus on the first few
minutes of &amp;#34;Miami Vice.&amp;#34;&lt;/p&gt;
&lt;p&gt;
So the upshot is that I managed to sack out for at least 1/3 of the
flight….&lt;/p&gt;
&lt;p&gt;
… now I&amp;#39;m safe in Christchurch having landed perhaps 30 minutes
ago. Staying at my favorite hotel, the Devon, and not flying until
Thursday. So it&amp;#39;s time to relax and enjoy summer for a few days (it
was rainy in Auckland, but it&amp;#39;s hot and sunny here).&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Giacometti</title>
      <link>http://johnj.com/posts/giacometti/</link>
      <pubDate>Mon, 22 Jan 2007 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/giacometti/</guid>
      <description>&lt;p&gt;
Just got back from a tasty lunch at the Dux De Lux followed by a visit
to the Christchurch Art Gallery, an attractive little museum a block
from the Devon.&lt;/p&gt;
&lt;p&gt;
They had a lovely show of Giacometti prints, drawings and
sculptures. Giacometti and I share a birthday (Oct. 10) and he died
the year I was born (1966). His sculptures are haunting and
deceptively simple-looking - tall and thin figures standing rigidly
erect, features all but obliterated in a field of surface
vibration. But I found his drawings and prints even more
attractive. Very simple subject matter again: a head, a chair, a small
group of figures. But rendered loosely as spare lattices of visceral
response to…. something, seen in the few models he employed over and
over again (his mother, his brother, his wife, his mistress). Made me
want to make etchings again, and lithographs.&lt;/p&gt;
&lt;p&gt;
Also a wonderful set of small rooms filled with drawings and paintings
by the spookily gifted 19th c. New Zealand/Dutch artist Petrus Van Der
Velden - in particular, a series of sketchbooks and studies for a
painting called the Dutch Funeral. Gorgeous drawings à la Rembrandt or
certain 19th c. Russian artists like Ilya Repin, but moodier, darker,
quieter, seemingly obsessed with beauty in death and suffering. Some
of the sketches were tiny, no more than a couple of inches on a side,
brown pages taken from battered sketchbooks… haunting, inspiring,
and very humbling.&lt;/p&gt;
&lt;p&gt;
Tomorrow we have the day off; Wednesday we get our cold weather gear,
and Thursday we fly to McMurdo.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>t=0</title>
      <link>http://johnj.com/posts/t-equals-zero/</link>
      <pubDate>Mon, 22 Jan 2007 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/t-equals-zero/</guid>
      <description>&lt;p&gt;
Under way at last.&lt;/p&gt;
&lt;p&gt;
My flight to LA leaves in 40 minutes - the first of five flights, a
migration of sorts. Flying south for the winter. Well, summer…&lt;/p&gt;
&lt;p&gt;
This is trip number six; as such, what I write about won&amp;#39;t be a
complete blow-by-blow as I have done in earlier years &lt;del&gt;(see the links
to previous years on the sidebar)&lt;/del&gt;, but you will get to see the trip
digested through the eyes of an &amp;#34;old hand.&amp;#34; To get in the mood, let&amp;#39;s
start with a few excerpts from my first trip, ten years ago…&lt;/p&gt;
&lt;blockquote&gt;
&lt;hr&gt;
&lt;p&gt;
December, 1996.&lt;/p&gt;
&lt;p&gt;
FLYING TO NEW ZEALAND&lt;/p&gt;
&lt;p&gt;
8:47 AM New Zealand time, Aukland airport.&lt;/p&gt;
&lt;p&gt;
New Zealand is cool!!!!&lt;/p&gt;
&lt;p&gt;
Everyone drives on the wrong side of the road. It&amp;#39;s green and wet.&lt;/p&gt;
&lt;p&gt;
A cyclone is expected to hit tonight. I totally love this place
already.  Gotta go, we&amp;#39;re taking off.&lt;/p&gt;
&lt;p&gt;
[…]&lt;/p&gt;
&lt;p&gt;
I think I have found the one place in the world more beautiful than
Wisconsin. Way better than Hawaii, California, Switzerland… we&amp;#39;ll
have to see about France.&lt;/p&gt;
&lt;p&gt;
On the coast near the Aukland airport, tiny green trees stick out of
the shallow water like little puffballs. Everything is green and lush,
a shock after Wisconsin. Apparently it frosts only a few times a year,
and those are the bad winters. Lots of tiny roads and houses scattered
about on irregularly-shaped land. Impending cyclones with 150 km/hr
winds provide added excitement. I believe our aircraft took off just
ahead of the storm.&lt;/p&gt;
&lt;p&gt;
Before takeoff, I thought we had a problem–smoke or steam was
drifting into the cabin above our heads through long slits. No one
else seemed to mind, so this is apparently normal. Maybe they want to
keep people from drying out. I sure could use a hot bath, come to
think of it.&lt;/p&gt;
&lt;p&gt;
Horse racing and cricket figure predominantly in sports news in the
New Zealand Herald.&lt;/p&gt;
&lt;p&gt;
On the airplane telly last night (gotta start talking like the locals)
there was a blurb on some sport that looked like it might be rugby,
but I couldn&amp;#39;t tell. It was total mayhem–people running and kicking a
football-like thing, catching it, tossing it around. Pure action but
much more three-dimensional than soccer or football; it looked more
like the pure hand-to-hand combat that all sports must have arisen
from. [It was Australian Rules Football.]&lt;/p&gt;
&lt;p&gt;
Time for the second airplane breakfast of the day. I&amp;#39;m having fun!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;
4:45 PM, Jan 1, 1997, Hotel California, McMurdo Base, Antarctica
Temperature, about 30 degrees F.&lt;/p&gt;
&lt;p&gt;
[…]&lt;/p&gt;
&lt;p&gt;
FLYING TO MCMURDO&lt;/p&gt;
&lt;p&gt;
&amp;#34;Few people have ever seen this,&amp;#34; said Neck [our pilot]. I felt amazed
that I had ever doubted that I would want to make this trip.&lt;/p&gt;
&lt;p&gt;
What began as a faint line of mountains gradually became a spectacular
view. As we approached, I studied the approaching topography on the
navigation chart, noticing the special symbol for crashed aircraft,
and finding where one lay on the map not all that far from where we
were flying. But the view soon overwhelmed my interest in the chart. I
took many pictures which I hope will mitigate my inability to describe
the mountains and long, winding glaciers. I [tried to see] the aerial
view with both scientific and artistic eyes. Looking at rivers of ice
and the clouds that flowed around them, I could see that ice and
clouds/air have a lot in common in appearance and underlying
form. Both flow through available channels, though on different
timescales, and reflect the light hitting them with so much purity
that one is not distracted by color, and can appreciate the near-still
dance of pure form.&lt;/p&gt;
&lt;p&gt;
Especially beautiful were the contrasts between the raw, jagged faces
of exposed rock and the breathlessly smooth contours of white, flowing
ice, occasionally ripped in striations caused by sudden shifts of
inclination in flow.&lt;/p&gt;
&lt;p&gt;
[…]&lt;/p&gt;
&lt;p&gt;
We passed close by town before landing on the skiway on the ice sheet
beyond. From the air (and from the ground too), the town itself looks
more like a collection of industrial freight boxes on black dirt and
rock than a real town. It is, however, an actual town, with a peak
summer population of 1200, a post office, a bank, a chapel, bars,
apartments and dorms, laboratories, &amp;#34;roads&amp;#34; (stretches of dirt that
people drive on, as opposed to stretches of dirt people don&amp;#39;t drive
on), a hospital, and a power plant. As far as I know, the only thing
McMurdo lacks is a cemetery. None of this is really apparent to the
new observer from the air, cockpit view notwithstanding.&lt;/p&gt;
&lt;p&gt;
We passed the town and the rocky point it is on, and descended to the
runway just behind it. All this while the crew was going through their
landing checklist, acting very efficiently and professionally. I
always like to see people do something they&amp;#39;re good at. And it was of
course a tremendous thrill to see the runway rise up to greet the
aircraft with a soft thud. Suddenly we were sliding down the ice,
slowing down with reverse thrust, watching odd, orange tracked
vehicles and equipment slide past. We went to the end of the skiway,
turned 180 degrees, and parked. Not long after, I thanked the crew,
and the other &amp;#34;beakers&amp;#34; [scientists] and I were led out on the ice
towards a van with big tires and high suspension (like most McMurdo
vehicles). It was quite warm, warmer than the Wisconsin I had left
just a few days ago. I looked around. There was a great expanse of
ice, and then mountains across the bay; nearby, the black hills hiding
McMurdo from us jutted into the white plain. A single seagull or skua
stood not far away. I was very excited. I had landed on The Ice.&lt;/p&gt;
&lt;p&gt;
[…]&lt;/p&gt;
&lt;p&gt;
AT THE POLE&lt;/p&gt;
&lt;p&gt;
I dozed and listened to music for a few hours, unpacked a few things,
and pondered my situation while taking several trips in the snow out
to the toilet and shower shack. It was there I met the guy who told me
about the piss cans [makeshift chamber pots]. We also talked about
other things about the Ice in general. I told him my impression of
McMurdo was better because there was scenery there. He replied,
&amp;#34;There&amp;#39;s scenery here, too. All you have to do is close your eyes.&amp;#34;
Words to live by.&lt;/p&gt;
&lt;p&gt;
There really is no scenery here. It&amp;#39;s like being out in the middle of
a frozen lake, except there is no end to it! The dome, various
buildings, odd tracked vehicles known as &amp;#34;sprytes&amp;#34; as well as other
trucks and construction equipment, the runway, and the ceremonial and
true geographic poles, are it. They are within about a mile of each
other. This is a small speck on an immense plain of ice. To think that
Scott and his men made it here on foot boggles the mind. (Amundsen,
who beat Scott by a few weeks, used sled dogs both to move men and
gear, and to feed the men as well towards the end of the
expedition. Amundsen made it back alive. Scott didn&amp;#39;t. The station is
named after both of them.)&lt;/p&gt;
&lt;hr&gt;
&lt;/blockquote&gt;
&lt;p&gt;
Fast-forward to 2007.&lt;/p&gt;
&lt;p&gt;
Airborne now en route to LAX, listening to &amp;#34;Dub Side of the Moon,&amp;#34; a
thoroughly postmodern Reggae-Floyd mash-up (thanks, Todd) on the new
red Nano courtesy of Santa Jobs and the Apple-cheeked elves of
Cupertino. Fell asleep already before takeoff, and realized as I awoke
to the trill of the engines that I could happily stay asleep until
magically waking up in my small room in the A wing of the station, go
for a quick jog on the treadmill, take my 2 minute shower, and start
working. Sad, eh? I&amp;#39;m ready to be there before the trip has even
gotten under way. I may think I know what to expect, but I know enough
to know that there can be surprises&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-1&#34; href=&#34;#footnote-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; good and bad when traveling to
the Ice. If nothing worse than previous years occurs, I&amp;#39;ll be
perfectly content. Once I get to Christchurch I&amp;#39;ll be in good
shape. The concatenated series of three flights (4+13+2 hrs) is the
hardest part of the trip.&lt;/p&gt;
&lt;p&gt;
For newcomers to the blog, the flight sequence is
ORD-&amp;gt;LAX-&amp;gt;CHC-&amp;gt;MCM-&amp;gt;NPX: Chicago to LA to Auckland, NZ to
Christchurch, NZ; get extreme cold weather (ECW) gear, fly to McMurdo
station on the edge of Ross Island, then to South Pole. Acclimate to
the altitude, then accomplish miracles.&lt;/p&gt;
&lt;p&gt;
A suitcase, a small backpack and a manly-purse are my only luggage
items. Packing light is a challenge and a pleasure. Most of the way I
won&amp;#39;t have to schlepp the big bag, but a long schlepp it is indeed,
and I know what not to take now. Colleague Bob Morse told me, &amp;#34;all you
really need is a toothbrush and some underwear.&amp;#34; He&amp;#39;s not far off. A
laptop and a towel are the other necessities, though some people
manage to do without the laptop (how?) and one colleague I know forgot
his towel and had to suffer through until a fellow South-bound
traveler could liberate one from a hotel in Christchurch for him. Some
things I do take I wouldn&amp;#39;t have thought of on the first trip: spray
bottle for extra humidity, clothesline for same (most clothes hang dry
in &amp;lt;8 hrs in the driest, highest desert in the world). An extra bag to
store summer clothes and other stuff I won&amp;#39;t need in Christchurch, and
for gifts on the way home. Similarly, I give back perhaps 1/3 of the
ECW gear in Christchurch, since I know I won&amp;#39;t wear it.&lt;/p&gt;
&lt;p&gt;
As the engines gunned for takeoff from Chicago I thought of the
software tests on &amp;#34;new DAQ&amp;#34; we have been running for the past few
weeks. Three or more of us in separate offices, separate cities,
tethered together by online chat and daily conference calls, putting
the software out on the &amp;#34;runway&amp;#34; (a bunch of networked computers),
giving it lots of gas, and watching with bated breath to see if it
took off. Cheering when it did, sighing when it crashed and burned,
sending us back to the proverbial (digital) drawing board. It&amp;#39;s not
exactly the way you build jet engines – thankfully, I thought, as we
soared into the skies above O&amp;#39;Hare.&lt;/p&gt;
&lt;p&gt;
Or is it?&lt;/p&gt;
&lt;p&gt;
A few small personal and work goals for the trip:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Help to achieve and maintain hitherto-unseen stability and elegance
in the data acquisition (DAQ) software;&lt;/li&gt;
&lt;li&gt;Stick to a routine of sleep, meditative stretching, and running that
keeps me healthy and positive. Keep up my running conditioning for
Shamrock Shuffle and &amp;#39;07 Chicago Marathon;&lt;/li&gt;
&lt;li&gt;Maintain good-natured and constructive dialogue with
colleagues. Steer as clear as possible of any of the ugly politics
that tend to crop up during summers at Pole;&lt;/li&gt;
&lt;li&gt;Finish or at least take a good whack at Pynchon&amp;#39;s &amp;#34;Gravity&amp;#39;s
Rainbow,&amp;#34; a brown-paged paperback copy of which I &amp;#34;borrowed&amp;#34; from
the AMANDA lab in MAPO in the Dark Sector at Pole in 1998. I&amp;#39;ll be
leaving the book (sans overdue book fines) behind in the library in
the new station. I like Pynchon but have had trouble finishing
anything except &amp;#34;The Crying of Lot 49.&amp;#34; But I&amp;#39;ve beaten Stephenson&amp;#39;s
amazing Baroque Cycle (almost 3000 pages) twice now, so I may be
ready for the &amp;#34;&amp;#39;Rainbow,&amp;#34; and if I can finish that maybe I&amp;#39;ll try
&amp;#34;V&amp;#34; again or his latest brain-bashing brick of a novel;&lt;/li&gt;
&lt;li&gt;Keep moving my drawing forward in bits and pieces. It has been a
real source of pleasure of late to return to drawing. My focus has
been on figurative drawing from life and from imagination, steered
by a measure of storytelling or narrative intent. Originally I was
going to make this a blog of drawings, and I may post some drawings
if they &amp;#34;work,&amp;#34; but I&amp;#39;m going to leave it open-ended for the
moment. But I have four sketchbooks and plenty of implements to play
with;&lt;/li&gt;
&lt;li&gt;Get completely caught up on episodes of Battlestar Galactica (my new
favorite guilty pleasure);&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course, the first goal (doing the actual work) will probably take
up 99% of my time and energy.&lt;/p&gt;
&lt;p&gt;
Other differences between this trip and last year:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I&amp;#39;m supposedly lodging in the A wing rather than the B wing of the
station - which may mean a larger, or at least a quieter, room.&lt;/li&gt;
&lt;li&gt;The new gym (and, in fact, the remaining half of the
newly-constructed station) is available.&lt;/li&gt;
&lt;li&gt;I have no management responsibilities, since Kael (IceCube DAQ
software lead) is coming at the same time - whew!&lt;/li&gt;
&lt;li&gt;This trip is shorter by a week - also a good thing. Anything shorter
than three weeks is perhaps not worth the long slog to the
Ice. Anything longer starts to feel too long, though I&amp;#39;ve done six
weeks and, of course, some people go for a year or more….&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;About this blog: apologies in advance if things are not explained
enough or background details (such as what we&amp;#39;re building) go
missing - if people have specific questions, they&amp;#39;re more than welcome
to write – I&amp;#39;ll try to answer them here. Check out the old blogs too.&lt;/p&gt;
&lt;p&gt;
Later!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr class=&#34;footnotes-separatator&#34;&gt;
&lt;div class=&#34;footnote-definitions&#34;&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-1&#34;&gt;&lt;a href=&#34;#footnote-reference-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;Surprises I or other colleagues have experienced en-route:
wandering herds of penguins; tours of Scott&amp;#39;s Hutt; unexpected cabin
depressurizations; being invited to sit in the cockpit during
landings; flights &amp;#34;boomeranging&amp;#34; (having to turn back due to weather
or mechanical issues); scenic flights over active volcanoes or through
canyons; and, of course, sitting around Christchurch or McMurdo for
hours to dozens of days, waiting for the weather to clear or for a
needed replacement aircraft part to arrive from somewhere in the US
military&amp;#39;s global infrastructure.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>The Big (Really really big...) Picture</title>
      <link>http://johnj.com/posts/the-really-really-big-picture/</link>
      <pubDate>Mon, 22 Jan 2007 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/the-really-really-big-picture/</guid>
      <description>&lt;p&gt;
In case I don&amp;#39;t get to it any time soon, Keith has done a decent
enough job &lt;a href=&#34;http://ksblog.wordpress.com/2007/01/22/icecube/&#34;&gt;explaining the big picture&lt;/a&gt; of Icecube on &lt;a href=&#34;http://ksblog.wordpress.com/&#34;&gt;his blog&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>How to subscribe to blog updates</title>
      <link>http://johnj.com/posts/how-to-subscribe-to-blog-updates/</link>
      <pubDate>Mon, 11 Dec 2006 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/how-to-subscribe-to-blog-updates/</guid>
      <description>&lt;p&gt;
This year I will be posting directly to the blog, rather than sending
out e-mails to everyone like I&amp;#39;ve done in previous years.&lt;/p&gt;
&lt;p&gt;
The easiest way to get notified of updates is via a &lt;em&gt;news aggregator&lt;/em&gt;. A
news aggregator is similar to your Web browser, but with the added
feature that it lets you know when new posts have appeared. This saves
you the chore of having to check the Websites you are interested in
&amp;#34;by hand.&amp;#34; In other words, it&amp;#39;s sort of like an e-mail inbox for the
Web.&lt;/p&gt;
&lt;p&gt;
It&amp;#39;s a big advantage for the blogger too, because he or she doesn&amp;#39;t
have to collect e-mail addresses from everyone or send out daily
e-mails to hundreds of people (this is especially nice when posting
from a remote site like the South Pole). Anyone can subscribe or
unsubscribe at any time without the blogger having to do anything.&lt;/p&gt;
&lt;p&gt;
In order to set up your news aggregator, first you&amp;#39;ll have to install
some software. &lt;del&gt;I recommend FeedReader for Windows, and NetNewsWire for
Mac (free version available here)&lt;/del&gt; [Feedly is what I use these days].&lt;/p&gt;
&lt;p&gt;
Once you have your news aggregator installed you &amp;#34;subscribe&amp;#34; to a blog
by giving your news aggregator software the URL for the blog. This
will be something called an &amp;#34;Atom feed&amp;#34; or an &amp;#34;RSS feed.&amp;#34; Use &lt;del&gt;this
link&lt;/del&gt; as the feed for this blog (right-click or, on the Mac,
option-click on the link and say &amp;#34;Copy link location&amp;#34; to capture the
URL). The exact method of &amp;#34;subscribing&amp;#34; depends on the software, but
should be fairly obvious once you have the software installed – on
NetNewsWire Lite, I use &amp;#34;File-&amp;gt;New Subscription&amp;#34; and paste the URL in.&lt;/p&gt;
&lt;p&gt;
Many of you already look at blogs - most newspapers have RSS feeds
too. It&amp;#39;s a really nice way to get fun stuff off the Web (cuts down on
the advertising, too!).&lt;/p&gt;
&lt;p&gt;
Happy reading!&lt;/p&gt;
&lt;p&gt;
p.s. to colleagues, friends and family - If you have a blog you&amp;#39;d like
me to link to, please drop me a line.&lt;/p&gt;
&lt;p&gt;
Example news aggregator:&lt;/p&gt;
&lt;figure&gt;





&lt;a href=&#34;http://johnj.com/rss-example.png&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/rss-example_hu_77e3b3829812d830.png&#34; style=&#34;width:400px; border:0px solid black;&#34;/&gt;&lt;/a&gt;


&lt;figcaption&gt;
example news aggregator
&lt;/figcaption&gt;
&lt;/figure&gt;
</description>
    </item>
    
    <item>
      <title>What The Blog is For</title>
      <link>http://johnj.com/posts/what-the-blog-is-for/</link>
      <pubDate>Sun, 10 Dec 2006 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/what-the-blog-is-for/</guid>
      <description>&lt;p&gt;
On my sixth trip to the South Pole, I will try to publish at least one
drawing or photo each day, possibly including some text.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Auckland; Leaving Already?</title>
      <link>http://johnj.com/posts/auckland/</link>
      <pubDate>Tue, 11 Jan 2005 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/auckland/</guid>
      <description>
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Europe in Miniature
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
09:00h&lt;/p&gt;
&lt;p&gt;
Made it back to the Midwest of the South Pacific, where the most
threatening thing is the drug dog that will point you out to Customs
if you have had any fruit (or drugs) in your backpack at any time in
the last 10,000 years.&lt;/p&gt;
&lt;p&gt;
How is it that a 12 hour transpacific flight can seem to take forever,
and yet when it&amp;#39;s over it&amp;#39;s hard to say what exactly happened during
those 12 hours? The memory of too-small seats and futile attempts to
sleep sitting up is imprinted more on my body, which feels like the
747 actually rolled over it, than in my mind. The in-flight film
&amp;#34;Collateral&amp;#34; made more of a mental impression (Tom Cruise blowing away
various people on the LA streets I just went jogging on
&amp;#34;yesterday&amp;#34;). But the silent view from the back of the darkened plane
of hundreds of personal LCD screens embedded in the back of every
seat, all tuned to different movies, TV shows, games, etc. was
lovely… something straight out of a contemporary art gallery. In the
21st Century, apparently, everyone gets their own in-flight media
smorgasbord.&lt;/p&gt;
&lt;p&gt;
At any rate, though I missed my flight to Christchurch, I&amp;#39;m on the 10
AM flight, just an hour or so away. All I hope is that I don&amp;#39;t have to
show up at the CDC to get my Ice clothing TODAY. I&amp;#39;m hoping for a hot
bath and a nap at the Devon.&lt;/p&gt;
&lt;p&gt;
Everything is exactly as I remembered it so far.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
Leaving Already?
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
12:43h&lt;/p&gt;
&lt;p&gt;
Arrived in Christchurch just a short while ago and I have to get my
Extreme Cold Weather Gear in 15 minutes…. may leave for McMurdo at 6
AM tomorrow; no rest for the weary….&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Halfway Around the World; Dragging the Soul Behind</title>
      <link>http://johnj.com/posts/halfway-around-the-world/</link>
      <pubDate>Mon, 10 Jan 2005 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/halfway-around-the-world/</guid>
      <description>
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Halfway Around the World
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
09:14h&lt;/p&gt;
&lt;p&gt;
I&amp;#39;m still stuck in LA but feel as if I&amp;#39;m already halfway around the
world. Went out for a jog, just around the block, smelling forgotten,
friendly smells, but somehow got stuck in a run down neighborhood and
had to jump two fences just to get back to my hotel, which was within
line-of-sight the whole time. As everyone knows, this place is not set
up for pedestrians. All the trees here third-world-nation different
and people drive gleamingly new cars but live in shabby
apartments… I love California but even after living here for five
years it feels more like a tourist destination than Home.&lt;/p&gt;
&lt;p&gt;
I&amp;#39;m on the same flight to Auckland tonight so I still have 8.5 hours
to kill. Time for a nap.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
Dragging the Soul Behind
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
12:13h&lt;/p&gt;
&lt;p&gt;
I&amp;#39;m listening to an audio book on my iPod: William Gibson&amp;#39;s &amp;#34;Pattern
Recognition.&amp;#34; The main character is in London with major jet lag. I&amp;#39;m
not officially too jet lagged yet but am tired from being
airport-bound until 3 AM this morning. Gibson&amp;#39;s protagonist describes
jet lag as your soul being reeled in from whatever far away place you
came from, drifting like a kite through the troposphere, slower than
the trans-oceanic jet you came in on. I&amp;#39;m trying to reel in my soul
just as quick as can be, &amp;#39;cause soon he&amp;#39;ll have a long distance to
make up.&lt;/p&gt;
&lt;p&gt;
When you&amp;#39;re tired but in your normal routine, you&amp;#39;ve still got the
glue of that routine keeping you together and productive. When you&amp;#39;re
in a new place, with time to kill, but alert and rested, you can
happily go exploring, or, if you&amp;#39;re a mobile tech warrior,
productively tick items off your lists of things to do. But one of the
paradoxes of killing time while on travel is that you&amp;#39;re both uprooted
and exhausted, so you live moment to moment, in a kind of blurry fog,
not sure what to do next, and too tired to care very much.&lt;/p&gt;
&lt;p&gt;
Time to repack, head to LAX and take another stab at Aotearoa, the
Land of the Long White Cloud (New Zealand).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Launched</title>
      <link>http://johnj.com/posts/launched/</link>
      <pubDate>Sun, 09 Jan 2005 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/launched/</guid>
      <description>
&lt;p&gt;
GPS: N40d00.000&amp;#39; W88d35.625&amp;#39; (but, bad signal in O&amp;#39;Hare)&lt;/p&gt;
&lt;p&gt;
13:01h&lt;/p&gt;
&lt;p&gt;
Well, I&amp;#39;m underway, waiting for my flight to LAX. Managed to get my
form stamped at customs, and found a seat near my gate with a power
outlet.&lt;/p&gt;
&lt;p&gt;
Itinerary: Chicago -&amp;gt; Los Angeles -&amp;gt; Auckland, NZ -&amp;gt; Christchurch, NZ
-&amp;gt; McMurdo Station -&amp;gt; South Pole Station. Five plane rides, something
like 30 hours in the air.&lt;/p&gt;
&lt;p&gt;
This is my fourth trip but it&amp;#39;s been a five year wait and enough time
has gone by that I am not 100% sure what to expect. Will I get a few
days to unwind in Christchurch? Will I get to stay at my favorite
place, the Devon Private Hotel? Is Gloria still the inkeeper, will I
get to eat her tasty if fattening breakfasts? Will I get to go jogging
along the tiny river Avon?&lt;/p&gt;
&lt;p&gt;
Is the Clothing Distribution Center (CDC) still the same? Is all the
gear they give you the same? Will I have room to stretch out on my
flight to the ice? Will I get to see the view from the cockpit?&lt;/p&gt;
&lt;p&gt;
I&amp;#39;m hoping to have a few days to walk around in McMurdo and take
pictures. McMurdo and the South Pole are very different, but both are
dead ringers for sets for the game Traveller, a game I played when I
was a rather younger man, a sci-fi role-playing game where you travel
from one world to another and have adventures in dusty, desolate and
desperate places.&lt;/p&gt;
&lt;div class=&#34;src src-text&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             McMurdo vs Pole
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             -------    ----
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    Dirt, rock &amp;amp; Ice    Ice
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;           Sea Level    10,000 ft
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Skuas, orcas, seals,    People
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; penguins and people
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Pop.: a few thousand    Pop.: a few hundred (summer)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       24/7 internet    ~8hrs/day internet
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Get money from ATM    Can cash checks
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;#34;Chapel of the snows&amp;#34;   Meditate on makeshift zafu
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    Shared bunkrooms    Private, closet sized room in
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                        wood+canvas &amp;#34;Jamesway&amp;#34; building
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      Summer weather    Summer weather like a
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         like a nice    really, really bad winter
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       winter day in    day in Minneapolis
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             Chicago
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     Short stroll to    Half-mile walk across skiway
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Crary Lab to check    to Dark Sector to work on
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              e-mail    experiment
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; Jog up &amp;#34;Observation    Run on treadmill, lift weights,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Hill&amp;#34; to catch the    bake in sauna.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                view
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   4 cafeteria-style    4 home-cooked, delicious
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  meals/day in huge,    meals/day in cozy
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;multi-room meal hall    galley
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   2 minute showers,    2 minute showers,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         twice/week.    twice/week.  :-(&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Stymied, Just Out of the Gate
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
19:14h&lt;/p&gt;
&lt;p&gt;
Thanks to a broken de-icer (actually a faulty computer circuit board)
we are still at our gate in Chicago, so I may get stuck overnight in
LA.&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Why am I doing this?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
When I describe trips to the South Pole, people tend to split into two
camps: those who think it&amp;#39;s very cool and would love to go, and those
who think it&amp;#39;s utterly crazy and wouldn&amp;#39;t dream of doing such a thing.&lt;/p&gt;
&lt;p&gt;
There are some good reasons (and maybe a few not-so-good reasons) for
doing a high energy neutrino astrophysics neutrino experiment at the
South Pole. Rather than go into the why&amp;#39;s and how&amp;#39;s of the project, I
will refer you for the moment to the IceCube Web Site.&lt;/p&gt;
&lt;p&gt;
But as to me personally, there are several reasons why &lt;strong&gt;I&lt;/strong&gt; wanted to
make this fourth trip. Professionally, I have worked on IceCube and
it&amp;#39;s predecessor AMANDA for over 13 years. This is the first season
when IceCube will put sensors (&amp;#34;DOMs&amp;#34;) in the ice. It is a crucial
season for this reason and I want to do whatever I can to help ensure
the successful deployment and operation of the instrument. My work on
IceCube in the last two years has been to write the software for
communicating with the DOMs in the ice, and I hope to help debug any
problems that may arise in the communications. I also wrote some of
the software that runs inside the DOMs themselves, so it will be good
to be &amp;#34;on hand&amp;#34; when we shake out the DOMs deployed in their proper
environment (a few kilometers below the surface of the ice). Also to
help with the actual deployments if need be, helping with other parts
of the software, or troublshooting anything that comes up.&lt;/p&gt;
&lt;p&gt;
Personally, I get to indulge my thirst for barren, strange places (a
taste acquired, no doubt in part, on my previous trips to the
Pole…. I love the idea of doing systems software for other projects
in similarly remote places – the ocean floor, the desert, down in a
mine, or in deep space). And after painting seriously for several
years in the Bay Area I have been pretty caught up in photography in
the last year or two, and I hope to take advantage of the trip to
capture some of the otherworldly imagery which abounds in
Antarctica. On previous trips I fantasized about taking pictures with
a medium or large format camera to show the kind of vivid texture and
detail that make the otherwise very minimal ice-scapes so compelling
when seen in person. So I have brought my Dad&amp;#39;s old Horseman 6x7
camera and a &amp;#39;50s era Russian folding camera along to try to capture
some of this detail, along with a Canon 20D digital camera for the
flexibility to shoot absolutely any number of pictures of absolutely
anything that catches my eye. I have no idea if any of this will be at
all successful, but it&amp;#39;s worth a try.&lt;/p&gt;
&lt;p&gt;
Finally, it&amp;#39;s another chance to re-connect with colleagues (since I
telecommute from Chicago most of the time I feel like &amp;#34;the ghost in
the machine&amp;#34; too often) and hopefully get back into shape after the
long holiday season (in past trips South, exercise has kept me sane
and happy).&lt;/p&gt;
&lt;p&gt;
Best wishes to all, Happy Birthday to Pete, and thanks again to
Gregory for the GPS receiver.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
Camping Out in LA
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
19:19h&lt;/p&gt;
&lt;p&gt;
Ugh. Finally airborne after about 7 hours on the plane parked at the
gate. They finally switched us to another plane. Fortunately I get to
rest in a hotel at LAX before doing it all again tomorrow
night. Blech. Next time I&amp;#39;m taking a cruise ship to the ice.&lt;/p&gt;
&lt;p&gt;
Anyways, I hear folks are very backed up in Christchurch as it is
because of bad weather on the ice, so maybe it&amp;#39;s just as well if I get
delayed a day or so going into New Zealand.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Getting Ready (t minus 2 days)</title>
      <link>http://johnj.com/posts/getting-ready/</link>
      <pubDate>Fri, 07 Jan 2005 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/posts/getting-ready/</guid>
      <description>&lt;p&gt;
Last latched GPS: N41d59.099&amp;#39; W87d39.934&amp;#39;&lt;/p&gt;
&lt;p&gt;
T minus 2 days. Biggest snow storm in 2 years getting me warmed up for
the Pole. I&amp;#39;ve gone out each morning for the past few days on &amp;#34;trial
runs&amp;#34; with Dad&amp;#39;s old Horseman camera and tripod. Yesterday, by the
time I got to Lake Michigan, the shutter cock had frozen (not a good
sign) and I only got half a roll. But the film grain looks very fine
(APX-100) and today the shutter worked ok.&lt;/p&gt;
&lt;p&gt;
On the beach everything was pure white except the lake itself (still a
stormy dark grey), two men out exercising their dogs, and a snowbreak
fence winding along the beach. I got some good photos of that and
finished up my roll. After that I decided to get up close to the water
and noticed many shapes bobbing up and down in the water. At first I
thought it was some sort of clot of weeds, but then my head flashed
grimly to the image of tsunami victims washing up.&lt;/p&gt;
&lt;p&gt;
What it actually turned out to be was quite beautiful and mysterious
– thousands of basketball-sized, weed-covered snowballs (iceballs?)
washed up on the water&amp;#39;s edge. One of the dogs attacked them one after
another and pulverised them for fun. It was an amazing thing to see
and got me in the mood for the trip. After a few weeks at the Pole,
even a few weeds on snowballs are going to seem pretty darn organic.&lt;/p&gt;
&lt;p&gt;
Meanwhile, so much to do…&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/art/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/art/</guid>
      <description>
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Artworks
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
A sample of recent work created since 2018.  See also:
&lt;a href=&#34;https://www.instagram.com/eigenhombre/&#34;&gt;Instagram feed&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;












&lt;a href=&#34;http://johnj.com/art/noli-appropinquare&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/na2025_hu_994d64122010bd8c.jpeg&#34; style=&#34;width:600px&#34;/&gt;&lt;/a&gt;


&lt;br/&gt;
&lt;em&gt;Noli Appropinquare&lt;/em&gt;, 2020-2025

&lt;br/&gt;
Oil on linen


&lt;br/&gt;
&lt;em style=&#34;font-size: smaller;&#34;&gt;40&amp;#34;x28&amp;#34;&lt;/em&gt;
&lt;br/&gt;


&lt;br/&gt;
&lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;









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












&lt;a href=&#34;http://johnj.com/evening-coastal-landscape.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/evening-coastal-landscape_hu_70872877b615090c.jpg&#34; style=&#34;width:400px&#34;/&gt;&lt;/a&gt;


&lt;br/&gt;
&lt;em&gt;Evening Coastal Landscape&lt;/em&gt;, 2022

&lt;br/&gt;
Oil on wood


&lt;br/&gt;
&lt;em style=&#34;font-size: smaller;&#34;&gt;4&amp;#34;x5&amp;#34;&lt;/em&gt;
&lt;br/&gt;



&lt;span class=&#34;sold&#34;&gt;SOLD&lt;/span&gt;

&lt;br/&gt;

&lt;br/&gt;
&lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;












&lt;a href=&#34;http://johnj.com/red-light-skull.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/red-light-skull_hu_6081aeb1da9b5aeb.jpg&#34; style=&#34;width:400px&#34;/&gt;&lt;/a&gt;


&lt;br/&gt;
&lt;em&gt;Red Light Skull&lt;/em&gt;, 2022

&lt;br/&gt;
Oil on copper


&lt;br/&gt;
&lt;em style=&#34;font-size: smaller;&#34;&gt;4&amp;#34;x6&amp;#34;&lt;/em&gt;
&lt;br/&gt;



&lt;span class=&#34;sold&#34;&gt;SOLD&lt;/span&gt;

&lt;br/&gt;

&lt;br/&gt;
&lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;












&lt;a href=&#34;http://johnj.com/warperms.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/warperms_hu_6aab14a69fd8c893.jpg&#34; style=&#34;width:400px&#34;/&gt;&lt;/a&gt;


&lt;br/&gt;
&lt;em&gt;War Permutations&lt;/em&gt;, 2022

&lt;br/&gt;
Relief print on paper


&lt;br/&gt;
&lt;em style=&#34;font-size: smaller;&#34;&gt;7.5&amp;#34;x9&amp;#34;&lt;/em&gt;
&lt;br/&gt;


&lt;br/&gt;
&lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;












&lt;a href=&#34;http://johnj.com/skull-woodcut.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/skull-woodcut_hu_f4d72bbb9c6db01.jpg&#34; style=&#34;width:400px&#34;/&gt;&lt;/a&gt;


&lt;br/&gt;
&lt;em&gt;Skull&lt;/em&gt;, 2022

&lt;br/&gt;
Woodcut on paper


&lt;br/&gt;
&lt;em style=&#34;font-size: smaller;&#34;&gt;11&amp;#34;x16&amp;#34;&lt;/em&gt;
&lt;br/&gt;


&lt;br/&gt;
&lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;












&lt;a href=&#34;http://johnj.com/steelworkers-park.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/steelworkers-park_hu_8357ab3ea7dddba4.jpg&#34; style=&#34;width:500px&#34;/&gt;&lt;/a&gt;


&lt;br/&gt;
&lt;em&gt;Steelworkers&amp;#39; Park Blast Furnace Bell&lt;/em&gt;, 2021

&lt;br/&gt;
Oil on Panel


&lt;br/&gt;
&lt;em style=&#34;font-size: smaller;&#34;&gt;5&amp;#34;x7&amp;#34;&lt;/em&gt;
&lt;br/&gt;


&lt;br/&gt;
&lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;












&lt;a href=&#34;http://johnj.com/skull.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/skull_hu_b6f7c5b18030d145.jpg&#34; style=&#34;width:350px&#34;/&gt;&lt;/a&gt;


&lt;br/&gt;
&lt;em&gt;Skull Study&lt;/em&gt;, 2021

&lt;br/&gt;
Oil on Panel


&lt;br/&gt;
&lt;em style=&#34;font-size: smaller;&#34;&gt;5&amp;#34;x7&amp;#34;&lt;/em&gt;
&lt;br/&gt;



&lt;span class=&#34;sold&#34;&gt;SOLD&lt;/span&gt;

&lt;br/&gt;

&lt;br/&gt;
&lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;












&lt;a href=&#34;http://johnj.com/peonies.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/peonies_hu_65c00046446e4a9b.jpg&#34; style=&#34;width:350px&#34;/&gt;&lt;/a&gt;


&lt;br/&gt;
&lt;em&gt;Flower Study - Peonies&lt;/em&gt;, 2020

&lt;br/&gt;
Oil on Paper


&lt;br/&gt;
&lt;em style=&#34;font-size: smaller;&#34;&gt;10&amp;#34;x12&amp;#34;&lt;/em&gt;
&lt;br/&gt;



&lt;span class=&#34;sold&#34;&gt;SOLD&lt;/span&gt;

&lt;br/&gt;

&lt;br/&gt;
&lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;












&lt;a href=&#34;http://johnj.com/skull-tempera.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/skull-tempera_hu_86b0d18e838642bd.jpg&#34; style=&#34;width:350px&#34;/&gt;&lt;/a&gt;


&lt;br/&gt;
&lt;em&gt;Tempera Skull Study&lt;/em&gt;, 2021

&lt;br/&gt;
Egg tempera on paper


&lt;br/&gt;
&lt;em style=&#34;font-size: smaller;&#34;&gt;Approx. 6&amp;#34;x10&amp;#34;&lt;/em&gt;
&lt;br/&gt;


&lt;br/&gt;
&lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;












&lt;a href=&#34;http://johnj.com/small-skull-study.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/small-skull-study_hu_68fd3ba4773c76df.jpg&#34; style=&#34;width:250px&#34;/&gt;&lt;/a&gt;


&lt;br/&gt;
&lt;em&gt;Small Skull Study&lt;/em&gt;, 2020

&lt;br/&gt;
Oil on wood


&lt;br/&gt;
&lt;em style=&#34;font-size: smaller;&#34;&gt;Approx. 4&amp;#34;x5&amp;#34;&lt;/em&gt;
&lt;br/&gt;



&lt;span class=&#34;sold&#34;&gt;SOLD&lt;/span&gt;

&lt;br/&gt;

&lt;br/&gt;
&lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;












&lt;a href=&#34;http://johnj.com/art/crows-and-civilization&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/crows-and-civilization_hu_ad6925f5c730dd8.jpeg&#34; style=&#34;width:700px&#34;/&gt;&lt;/a&gt;


&lt;br/&gt;
&lt;em&gt;Crows and Civilization&lt;/em&gt;, 2019

&lt;br/&gt;
Oil on linen


&lt;br/&gt;
&lt;em style=&#34;font-size: smaller;&#34;&gt;40&amp;#34;x28&amp;#34;&lt;/em&gt;
&lt;br/&gt;


&lt;br/&gt;
&lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;












&lt;a href=&#34;http://johnj.com/johnportrait.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/johnportrait_hu_a174d49d3c3b1e43.jpg&#34; style=&#34;width:700px&#34;/&gt;&lt;/a&gt;


&lt;br/&gt;
&lt;em&gt;Portrait of John&lt;/em&gt;, 2018


&lt;br/&gt;
&lt;em style=&#34;font-size: smaller;&#34;&gt;11.5&amp;#34;x7.5&amp;#34;&lt;/em&gt;
&lt;br/&gt;


&lt;br/&gt;
&lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;












&lt;a href=&#34;http://johnj.com/IMG_3147ps2.jpg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/IMG_3147ps2_hu_ecde81409e0b7abe.jpg&#34; style=&#34;width:700px&#34;/&gt;&lt;/a&gt;


&lt;br/&gt;
&lt;em&gt;NUPOC Training Prosthesis&lt;/em&gt;, 2018

&lt;br/&gt;
Oil on Canvas



&lt;br/&gt;
&lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;












&lt;a href=&#34;http://johnj.com/figure-study-silverpoint.jpeg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/figure-study-silverpoint_hu_9acfad8ef488c94e.jpeg&#34; style=&#34;width:700px&#34;/&gt;&lt;/a&gt;


&lt;br/&gt;
&lt;em&gt;Figure study&lt;/em&gt;, 2018

&lt;br/&gt;
Silverpoint on paper



&lt;br/&gt;
&lt;br/&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/newview/crows/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/newview/crows/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/crows-and-civilization.jpeg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: #c4b3b3;
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: 200px;
       
      
      font-size: 20px;
  }
  .content a {
      color: #c4b3b3;
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: #777;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../feed&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../na2&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;Crows and Civilization&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/crows-and-civilization.jpeg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;description&#34;&gt;
Oil on Canvas&lt;br&gt;
&lt;/div&gt;

&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../feed&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../na2&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/newview/feed/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/newview/feed/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/feed.jpeg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: #827e76;
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: auto;
       
      
      font-size: 20px;
  }
  .content a {
      color: #827e76;
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: red;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../warperms&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../crows&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;Graphite drawing in progress&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/feed.jpeg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../warperms&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../crows&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/newview/johnportrait/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/newview/johnportrait/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/johnportrait.jpg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: rgb(111, 102, 94);
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: 0px;
       
      
      font-size: 20px;
  }
  .content a {
      color: rgb(111, 102, 94);
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: #636572;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../prosthesis&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../warperms&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;Portrait of John&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/johnportrait.jpg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;description&#34;&gt;
Oil on Panel&lt;br&gt;
&lt;/div&gt;

&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../prosthesis&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../warperms&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/newview/na1/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/newview/na1/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/noli-appropinquare.jpeg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: #caced2;
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: 400px;
       
      
      font-size: 20px;
  }
  .content a {
      color: #caced2;
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: #636572;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../na2&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../skull&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;Noli Appropinquare&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/noli-appropinquare.jpeg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;description&#34;&gt;
Later state of painting.&lt;br&gt;
&lt;/div&gt;

&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../na2&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../skull&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/newview/na2/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/newview/na2/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/na-2.jpeg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: rgb(67, 56, 54);
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: 250px;
       
      
      font-size: 20px;
  }
  .content a {
      color: rgb(67, 56, 54);
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: #000;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../crows&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../na1&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;Noli Appropinquare&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/na-2.jpeg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;description&#34;&gt;
Early state of oil painting.&lt;br&gt;
&lt;/div&gt;

&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../crows&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../na1&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/newview/na3/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/newview/na3/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/na-3.jpeg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: #292b8c;
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: 20px;
       
      
      background: #ffffff4f;
      
      font-size: 20px;
  }
  .content a {
      color: #292b8c;
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: #191970;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../crows&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../na2&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;Noli Appropinquare&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/na-3.jpeg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;description&#34;&gt;
Oil on canvas, recent detail&lt;br&gt;
&lt;/div&gt;

&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../crows&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../na2&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/newview/prosthesis/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/newview/prosthesis/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/IMG_3147ps2.jpg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: #333333;
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: 200px;
       
      
      background: #aaaaaa77;
      
      font-size: 20px;
  }
  .content a {
      color: #333333;
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: #636572;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../skull&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../johnportrait&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;NUPOC Training Prosthesis&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/IMG_3147ps2.jpg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;description&#34;&gt;
Oil on Canvas&lt;br&gt;
&lt;/div&gt;

&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../skull&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../johnportrait&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/newview/skull/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/newview/skull/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/skull.jpg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: #f2a69e;
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: 0px;
       
      
      font-size: 20px;
  }
  .content a {
      color: #f2a69e;
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: #636572;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../na1&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../prosthesis&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;Skull Study, 2021&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/skull.jpg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;description&#34;&gt;
Oil on Panel&lt;br&gt;
&lt;/div&gt;

&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../na1&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../prosthesis&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/newview/warperms/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/newview/warperms/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/warperms.jpg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: #1c1b1b;
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: 500px;
       
      
      background: #ffffff75;
      
      font-size: 20px;
  }
  .content a {
      color: #1c1b1b;
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: #636572;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../johnportrait&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../feed&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;War Permutations&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/warperms.jpg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;description&#34;&gt;
Relief print, series of 362880 unique arrangements.&lt;br&gt;
&lt;/div&gt;

&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../johnportrait&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../feed&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/paintings/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/paintings/</guid>
      <description>
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
Paintings
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;







 
 
&lt;a href=&#34;http://johnj.com/art/crows-and-civilization&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/crows-and-civilization_hu_ad6925f5c730dd8.jpeg&#34; style=&#34;width:700px&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
&amp;#34;Crows and Civilization&amp;#34;, 2019&lt;/p&gt;
&lt;p&gt;







 
 
&lt;a href=&#34;http://johnj.com/art/noli-appropinquare&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/noli-appropinquare_hu_963ab2105ad30876.jpeg&#34; style=&#34;width:700px&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;p&gt;
&amp;#34;Noli Appropinquare&amp;#34;, 2020-2022&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/some-drawings/a-seated/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/some-drawings/a-seated/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/a-seated.jpg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: #333B;
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: 0px;
       
      
      font-size: 20px;
  }
  .content a {
      color: #333B;
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: #FFF;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../foreshortened-figure&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../quicksketch-figures&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;A., Seated&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/a-seated.jpg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;description&#34;&gt;
Graphite&lt;br&gt;
&lt;/div&gt;

&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../foreshortened-figure&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../quicksketch-figures&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/some-drawings/composition-study-1/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/some-drawings/composition-study-1/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/composition-study-1.jpg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: #000;
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: 600px;
       
      
      background: #7775;
      
      font-size: 20px;
  }
  .content a {
      color: #000;
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: #636572;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../composition-study-2&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../foreshortened-figure&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;Composition Study&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/composition-study-1.jpg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;description&#34;&gt;
Gouache on paper&lt;br&gt;
&lt;/div&gt;

&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../composition-study-2&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../foreshortened-figure&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/some-drawings/composition-study-2/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/some-drawings/composition-study-2/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/composition-study-2.jpg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: #EEEE;
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: 600px;
       
      
      background: #7777;
      
      font-size: 20px;
  }
  .content a {
      color: #EEEE;
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: #000;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../n-portrait&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../composition-study-1&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;Composition in Black and White&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/composition-study-2.jpg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;description&#34;&gt;
Gouache on Paper&lt;br&gt;
&lt;/div&gt;

&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../n-portrait&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../composition-study-1&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/some-drawings/figure-silverpoint-1/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/some-drawings/figure-silverpoint-1/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/figure-silverpoint-1.jpg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: #666B;
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: 330px;
       
      
      font-size: 20px;
  }
  .content a {
      color: #666B;
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: #636572;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../quicksketch-figures&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../gouache-composition-1&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;Seated Figure&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/figure-silverpoint-1.jpg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;description&#34;&gt;
Silverpoint&lt;br&gt;
&lt;/div&gt;

&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../quicksketch-figures&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../gouache-composition-1&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/some-drawings/foreshortened-figure/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/some-drawings/foreshortened-figure/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/foreshortened-figure.jpg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: #caced2;
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: 100px;
       
      
      font-size: 20px;
  }
  .content a {
      color: #caced2;
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: #f2f2f2;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../composition-study-1&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../a-seated&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;Foreshortened Figure&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/foreshortened-figure.jpg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;description&#34;&gt;
Oil on Panel&lt;br&gt;
&lt;/div&gt;

&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../composition-study-1&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../a-seated&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/some-drawings/gouache-composition-1/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/some-drawings/gouache-composition-1/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/gouache-composition-1.jpg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: #222;
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: 0px;
       
      
      background: #AAAB;
      
      font-size: 20px;
  }
  .content a {
      color: #222;
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: #000;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../figure-silverpoint-1&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../na-charcoal-study-1&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;Monochrome Figure Study&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/gouache-composition-1.jpg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;description&#34;&gt;
Gouache on paper&lt;br&gt;
&lt;/div&gt;

&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../figure-silverpoint-1&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../na-charcoal-study-1&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/some-drawings/n-portrait/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/some-drawings/n-portrait/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/n-portrait.jpg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: #222B;
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: 0px;
       
      
      background: #FFF1;
      
      font-size: 20px;
  }
  .content a {
      color: #222B;
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: #222;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../na-charcoal-study-1&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../composition-study-2&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;Sketch of N.&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/n-portrait.jpg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;description&#34;&gt;
Graphite&lt;br&gt;
&lt;/div&gt;

&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../na-charcoal-study-1&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../composition-study-2&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/some-drawings/na-charcoal-study-1/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/some-drawings/na-charcoal-study-1/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/na-charcoal-study-1.jpg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: #caced2;
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: 50px;
       
      
      background: #5557;
      
      font-size: 20px;
  }
  .content a {
      color: #caced2;
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: #636572;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../gouache-composition-1&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../n-portrait&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;Noli Appropinquare&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/na-charcoal-study-1.jpg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;description&#34;&gt;
Study for work in progress&lt;br&gt;
&lt;/div&gt;

&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../gouache-composition-1&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../n-portrait&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/art/some-drawings/quicksketch-figures/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/art/some-drawings/quicksketch-figures/</guid>
      <description>











&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.googleapis.com&#34;&gt;
&lt;link rel=&#34;preconnect&#34; href=&#34;https://fonts.gstatic.com&#34; crossorigin&gt;
&lt;link href=&#34;https://fonts.googleapis.com/css2?family=Spectral:wght@300&amp;display=swap&#34; rel=&#34;stylesheet&#34;&gt;
&lt;style&gt;
  body {
      background-color: #333;
      background-image: url(&#34;/quicksketch-figures.jpg&#34;);
      background-repeat: no-repeat;
      background-size: contain;
       
      max-width: 100%;
  }
  @media (orientation: portrait) {
    body {
        background-size: auto 100%;
        background-position: center;
    }
  }

  @media (orientation: landscape) {
    body {
      background-size: 100% auto;
      background-position: top;
    }
  }
  .content {
      color: #EEEA;
      padding-top: 10px;
      padding-right: 10px;
      padding-bottom: 30px;
      padding-left: 30px;
       
      margin-top: 50px;
       
      
      background: #9995;
      
      font-size: 20px;
  }
  .content a {
      color: #EEEA;
      font-size: 20px;
  }
  .site-nav {
      padding-left: 30px;
  }
  .site-nav a {
      color: #000;
  }
  .artworktitle {
      font-family: &#39;Spectral&#39;, serif;
      font-size: 50px;
      font-style: italic;
  }
  a.imageonly {
      font-size: 15px;
  }
  .description {
  }
  .fullscreen-prev-next {
      font-size: 30px;
  }
&lt;/style&gt;
&lt;script&gt;
  function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == 39) {
      window.location.assign(&#34;../a-seated&#34;);
    } else if (e.keyCode == 37) {
      window.location.assign(&#34;../figure-silverpoint-1&#34;);
    }
  }
  document.onkeydown = checkKey;
&lt;/script&gt;


&lt;span class=&#34;artworktitle&#34;&gt;Quick-Sketch Figures&lt;/span&gt;
&lt;br/&gt;


&lt;a class=&#34;imageonly&#34; href=&#34;http://johnj.com/quicksketch-figures.jpg&#34;&gt;View image only&lt;/a&gt;
&lt;br/&gt;


&lt;div class=&#34;description&#34;&gt;
Graphite&lt;br&gt;
&lt;/div&gt;

&lt;div class=&#34;fullscreen-prev-next&#34;&gt;
&lt;br/&gt;

&lt;a href=&#34;../a-seated&#34;&gt;Next&lt;/a&gt;
&lt;br/&gt;


&lt;a href=&#34;../figure-silverpoint-1&#34;&gt;Previous&lt;/a&gt;
&lt;br/&gt;

&lt;/div&gt;

</description>
    </item>
    
    <item>
      <title></title>
      <link>http://johnj.com/now/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>http://johnj.com/now/</guid>
      <description>
&lt;hr&gt;
&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-1&#34;&gt;
2026 - What I&amp;#39;m Doing Now&lt;sup class=&#34;footnote-reference&#34;&gt;&lt;a id=&#34;footnote-reference-1&#34; href=&#34;#footnote-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
As of the beginning of the year I have been continue to assist with
the &lt;a href=&#34;https://icecube.wisc.edu/science/beyond/&#34;&gt;IceCube Upgrade&lt;/a&gt; (with a very exciting Pole season underway);
continuing a regular drawing practice, learning to play Mom&amp;#39;s old
concert flute, and caregiving duties.&lt;/p&gt;
&lt;p&gt;
I have also been reengaging with Clojure programming, being reminded
how fun Lisps and a good REPL can be.  The burgeoning and amazing AI
tooling landscape has not changed that – if anything, Clojure is even
more fun than ever.&lt;/p&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-2&#34;&gt;
2025 Projects
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-2&#34;&gt;
&lt;ul&gt;
&lt;li&gt;I showed fourteen pieces in the August group show, &amp;#34;&lt;a href=&#34;http://johnj.com/soa&#34;&gt;Sites of Arrival&lt;/a&gt;&amp;#34;,
at the &lt;a href=&#34;https://paletteandchisel.org&#34;&gt;Palette and Chisel Academy of
Fine Arts&lt;/a&gt; in Chicago.  Participated in a few other shows as well.&lt;/li&gt;
&lt;li&gt;I continued work for &lt;a href=&#34;https://icecube.wisc.edu/&#34;&gt;IceCube&lt;/a&gt;: embedded systems programming, test
visualization, and communications tests in preparation for the
2024-2025 Antarctic field season (&amp;#34;IceCube Upgrade&amp;#34;);&lt;/li&gt;
&lt;li&gt;I did regular &amp;#34;quick sketch&amp;#34; figure drawing at the Palette and Chisel;&lt;/li&gt;
&lt;li&gt;I spent more time than usual on family care, reading, and private writing.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-3&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-3&#34;&gt;
2024 Projects
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-3&#34; class=&#34;outline-text-2&#34;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://icecube.wisc.edu/&#34;&gt;IceCube&lt;/a&gt; work&lt;/li&gt;
&lt;li&gt;Playing with &lt;a href=&#34;http://johnj.com/posts/to-the-metal/&#34;&gt;compilers and toy languages&lt;/a&gt;; learning OCaml;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.instagram.com/eigenhombre/&#34;&gt;Drawing and painting practice&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Taking care of family.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://johnj.com/posts/e-paper-rpi-display/&#34;&gt;Making A Tiny E-Paper Status Display for the Raspberry Pi Zero&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://johnj.com/posts/wrangling-dreams/&#34;&gt;Wrangling Half a Thousand Dreams&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-4&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-4&#34;&gt;
2023 Projects
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-4&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Worked on &lt;a href=&#34;../art/art&#34;&gt;my painting and drawing practice&lt;/a&gt;, including a series of &lt;a href=&#34;../art/self&#34;&gt;self portraits&lt;/a&gt;.  Worked as an independent software developer for the
&lt;a href=&#34;https://en.wikipedia.org/wiki/IceCube_Neutrino_Observatory&#34;&gt;IceCube Neutrino Observatory&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-5&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-5&#34;&gt;
2022 - Sabbatical
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-5&#34; class=&#34;outline-text-2&#34;&gt;
&lt;p&gt;
Prior to September, 2022, I took a five month sabbatical from paid work.
Here are some of the things I worked on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Improved &lt;a href=&#34;https://github.com/eigenhombre/l1&#34;&gt;&lt;code class=&#34;verbatim&#34;&gt;l1&lt;/code&gt;, my Lisp dialect written in Go&lt;/a&gt;, and wrote the
beginnings of a &lt;a href=&#34;https://github.com/eigenhombre/onomat/&#34;&gt;roguelike-inspired mini-game&lt;/a&gt; in that language.&lt;/li&gt;
&lt;li&gt;Made &lt;a href=&#34;https://github.com/eigenhombre/tunnerl&#34;&gt;a tiny 1-d roguelike&lt;/a&gt; in Python.&lt;/li&gt;
&lt;li&gt;Improved &lt;a href=&#34;https://github.com/eigenhombre/smallscheme&#34;&gt;my Scheme implementation&lt;/a&gt; in Python.&lt;/li&gt;
&lt;li&gt;Tinkered with Common Lisp projects, including
&lt;a href=&#34;https://github.com/eigenhombre/cl-oju&#34;&gt;this library of functions
inspired by Clojure&lt;/a&gt;, a text-based &lt;a href=&#34;https://github.com/eigenhombre/hbook/&#34;&gt;histogramming library&lt;/a&gt;, and a
bookkeeping program for &lt;a href=&#34;http://johnj.com/art/warperms&#34;&gt;War Permutations&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Did the first 50+ &lt;a href=&#34;https://exercism.org/profiles/eigenhombre&#34;&gt;Common Lisp problems on Exercism&lt;/a&gt; to train myself
better in this old, strange, &lt;em&gt;fast&lt;/em&gt; language.&lt;/li&gt;
&lt;li&gt;Paintings and relief prints.  Example: &lt;a href=&#34;http://johnj.com/art/warperms&#34;&gt;War Permutations print&lt;/a&gt;. See
also &lt;a href=&#34;http://johnj.com/art/feed&#34;&gt;works in progress&lt;/a&gt; here, or my &lt;a href=&#34;https://www.instagram.com/eigenhombre/&#34;&gt;Instagram&lt;/a&gt; feed.&lt;/li&gt;
&lt;li&gt;Practiced &lt;a href=&#34;https://exercism.org/profiles/eigenhombre/solutions?order=newest_first&amp;amp;track_slug=python&#34;&gt;Python programming&lt;/a&gt; (again!).  I did a lot of Python
development up until about 2014, after which I switched to mostly
Clojure for day jobs.  But I still like Python and it&amp;#39;s fun to get
back to it for awhile.&lt;/li&gt;
&lt;li&gt;Learned about Quantum Computing by &lt;a href=&#34;https://www.cambridge.org/highereducation/books/quantum-computation-and-quantum-information/01E10196D0A682A6AEFFEA52D53BE9AE#overview&#34;&gt;reading&lt;/a&gt; &lt;a href=&#34;https://www.robertsutor.com/dancing-with-qubits/&#34;&gt;books&lt;/a&gt; and playing with
&lt;a href=&#34;https://qiskit.org/&#34;&gt;Qiskit&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://johnj.com/posts/another-migration&#34;&gt;Worked on&lt;/a&gt; the Web site you&amp;#39;re reading.&lt;/li&gt;
&lt;li&gt;Journaling and working on improving my handwriting.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-6&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-6&#34;&gt;
2022 - Prior to Sabbatical
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-6&#34; class=&#34;outline-text-2&#34;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://johnj.com/posts/l1&#34;&gt;Implemented a Lisp in Go&lt;/a&gt;, with detours into &lt;a href=&#34;https://craftinginterpreters.com/&#34;&gt;Crafting Interpreters&lt;/a&gt;
and &lt;a href=&#34;https://mitpress.mit.edu/sites/default/files/sicp/index.html&#34;&gt;Structure and Interpretation of Computer Programs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Learned the &lt;a href=&#34;https://go.dev/&#34;&gt;Go programming language&lt;/a&gt;.  I&amp;#39;ve written a &lt;a href=&#34;https://github.com/eigenhombre/treetop&#34;&gt;few&lt;/a&gt; &lt;a href=&#34;https://github.com/eigenhombre/rf&#34;&gt;modestly&lt;/a&gt;
&lt;a href=&#34;https://github.com/eigenhombre/conttest&#34;&gt;useful&lt;/a&gt; things and am really enjoying the experience after years of
focusing primarily on Lisps and functional programming.  Go
emphasizes a different kind of simplicity than Clojure does, and it
seems to occupy a sweet spot on the speed vs. power spectrum.  I&amp;#39;m
regularly impressed by how fast Go programs are, including the &lt;a href=&#34;https://gohugo.io/&#34;&gt;program&lt;/a&gt;
used to build this site.&lt;/li&gt;
&lt;li&gt;Learned some Mandarin (reading, mostly).  I got my vocabulary up to
about four hundred words.  It&amp;#39;s a beautiful language, and a slog to
learn, but &lt;a href=&#34;https://www.hackchinese.com/&#34;&gt;thanks to technology&lt;/a&gt; it is definitely possible!&lt;/li&gt;
&lt;li&gt;Until late April, 2022 I was a staff software engineer at &lt;a href=&#34;http://oppfi.com&#34;&gt;OppFi&lt;/a&gt;, where
I wrote software (mostly in &lt;a href=&#34;https://clojure.org/&#34;&gt;Clojure&lt;/a&gt;), mentored and taught other
engineers, and tried to improve process, code quality, and
architecture wherever I could.  I spent nearly four years at OppFi,
learned a lot, helped a lot of people, and am happy to move onto other
things.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-7&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;headline-7&#34;&gt;
Prior Decades
&lt;/h2&gt;
&lt;div id=&#34;outline-text-headline-7&#34; class=&#34;outline-text-2&#34;&gt;
&lt;div id=&#34;outline-container-headline-8&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-8&#34;&gt;
2010-2020
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-8&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Lived in Chicago.  Finished last few &lt;a href=&#34;http://johnj.com/tags/southpole/&#34;&gt;South Pole trips&lt;/a&gt;.  Stopped
contracting for IceCube and worked in industry.  Invested more
heavily in art practice.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-9&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-9&#34;&gt;
2000-2009
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-9&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Lived in San Francisco Bay Area, then left LBNL at moved to Chicago,
working for IceCube.  Ran a few marathons and half marathons,
went to the Pole several more times.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-headline-10&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;headline-10&#34;&gt;
1990-1999
&lt;/h3&gt;
&lt;div id=&#34;outline-text-headline-10&#34; class=&#34;outline-text-3&#34;&gt;
&lt;p&gt;
Graduated, worked at CERN for a year, then spent a few years in art
school, then grad school in art and physics at UW-Madison.  Finished
Ph.D.  1996, then moved to Bay Area.  First two trips to the South Pole.&lt;/p&gt;
&lt;p&gt;





&lt;a href=&#34;http://johnj.com/now.jpeg&#34;&gt;&lt;img class=&#34;resize&#34; src=&#34;http://johnj.com/now_hu_e8d1ca2bc9738e92.jpeg&#34; style=&#34;width:700px; border:0px solid black;&#34;/&gt;&lt;/a&gt;

&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;footnotes&#34;&gt;
&lt;hr class=&#34;footnotes-separatator&#34;&gt;
&lt;div class=&#34;footnote-definitions&#34;&gt;
&lt;div class=&#34;footnote-definition&#34;&gt;
&lt;sup id=&#34;footnote-1&#34;&gt;&lt;a href=&#34;#footnote-reference-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;
&lt;div class=&#34;footnote-body&#34;&gt;
&lt;p&gt;For more about Now Pages, see &lt;a href=&#34;https://nownownow.com/about&#34;&gt;this link&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
    </item>
    
  </channel>
</rss>
