<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title>Andreas Fuchs&#8217; Journal</title>
  <link href="http://boinkor.net/atom.xml" rel="self"/>
  <link href="http://boinkor.net/"/>
  <updated>2011-12-11T16:06:47-08:00</updated>
  <id>http://boinkor.net/</id>
  <author>
    <name>Andreas Fuchs</name>
    
      <email>asf@boinkor.net</email>
    
  </author>

  
  <entry>
    <title>Accessing the Stripe API From Lisp</title>
    <link href="http://boinkor.net/archives/2011/10/accessing-the-stripe-api-from-lisp.html"/>
    <updated>2011-10-08T23:31:00-07:00</updated>
    <id>http://boinkor.net/archives/2011/10/accessing-the-stripe-api-from-lisp</id>
    
    <category term="Lisp" />
    
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://stripe.com&quot;&gt;Stripe&lt;/a&gt; is a new payment processor on the Web,
and they seem to be
&lt;a href=&quot;http://www.google.com/search?q=paypal+screwed+me&quot;&gt;a lot less insane&lt;/a&gt;
than Paypal. On a whim, I made a little (almost completely untested,
toy) CL library for accessing their HTTP API from Lisp. Maybe you&amp;#8217;ll
find it useful: &lt;a href=&quot;https://github.com/antifuchs/cl-stripe&quot;&gt;cl-stripe&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This was pretty great fun! Thanks to their nice
&lt;a href=&quot;https://stripe.com/api/docs&quot;&gt;HTTP API&lt;/a&gt;,
&lt;a href=&quot;http://weitz.de/drakma&quot;&gt;drakma&lt;/a&gt;, and
&lt;a href=&quot;http://common-lisp.net/project/alexandria/&quot;&gt;alexandria&lt;/a&gt;, I have been
able to write this with a minimum of horribly hacky code, in just 5 or
6 hours of working on it, on and off, this saturday afternoon.&lt;/p&gt;

&lt;p&gt;If it still looks like fun, I think I may add some clucumber tests to
it tomorrow. Stay tuned.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>A Weird Problem With ASDF on NFS (and a workaround)</title>
    <link href="http://boinkor.net/archives/2011/10/a-weird-problem-with-asdf-on-nfs.html"/>
    <updated>2011-10-06T22:37:00-07:00</updated>
    <id>http://boinkor.net/archives/2011/10/a-weird-problem-with-asdf-on-nfs</id>
    
    <category term="Lisp" />
    
    <content type="html">&lt;p&gt;Recently, we at Franz have been seeing weird failures when building a
certain ASDF system on NFS: We were intermittently getting
redefinition warnings when loading a system - not all the time, but
more often when we compiled during certain timeslots.&lt;/p&gt;

&lt;p&gt;This was a weird one, and I think it would be nice to record what this
is, and how we figured out what&amp;#8217;s going on (and how we arrived at our
work-around).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update 2011-10-11&lt;/strong&gt;: Faré
&lt;a href=&quot;http://lists.common-lisp.net/pipermail/asdf-devel/2011-October/002196.html&quot;&gt;informs&lt;/a&gt;
me that this problem is fixed (all the way, no need for a workaround)
in ASDF 2.017.9!&lt;/p&gt;

&lt;h2&gt;The Symptom&lt;/h2&gt;

&lt;p&gt;We have a system and a specialized operation (&lt;code&gt;concat-op&lt;/code&gt;, it
generates a single loadable .fasl we can ship) that depends on
&lt;code&gt;asdf:load-op&lt;/code&gt;. In our build process, we first load the system, then
generate some data with the loaded system, and then perform the custom
operation on the system.&lt;/p&gt;

&lt;p&gt;When performing that operation with a source tree that was checked out
on NFS, the &lt;code&gt;load-op&lt;/code&gt; that it depends on sometimes got performed a
second time: The lisp loaded all the .fasls again, and for some
constructs in some .fasls, signaled a &lt;code&gt;WARNING&lt;/code&gt;, which made the build
break.&lt;/p&gt;

&lt;p&gt;Oddly enough, the failure happened only during certain time slots - we
would see the build work between 3pm and 4:30pm, and starting at 4:30
it failed consistently until it was time to go home. Huh.&lt;/p&gt;

&lt;h2&gt;Aside: How ASDF Operates&lt;/h2&gt;

&lt;p&gt;Not everyone might be familiar with how ASDF works (if you are, feel
free to skip to the next section, or stay and nitpick (-:), so here&amp;#8217;s
a small primer on what happens when you type &lt;code&gt;(asdf:load-system
:some-system)&lt;/code&gt;. Here&amp;#8217;s a little walkthrough:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;ASDF runs the generic function &lt;code&gt;traverse&lt;/code&gt; with the system and the
operation as parameters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;traverse&lt;/code&gt; walks the dependencies of the system and the contents of
the system itself, and determines which operations are not yet
done.&lt;/p&gt;

&lt;p&gt;For a &lt;code&gt;load-op&lt;/code&gt; on a CL source file, &lt;code&gt;traverse&lt;/code&gt; will try to
generate a &lt;code&gt;load-op&lt;/code&gt; for the input-file of that load-op (the .fasl
file), check if that .fasl file exists, and if it doesn&amp;#8217;t, then it
will also generate a &lt;code&gt;compile-op&lt;/code&gt; for the corresponding .lisp file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a result, &lt;code&gt;traverse&lt;/code&gt; returns a list of operations that must be
performed on each component (or module, or system). For a clean
source tree, that list looks something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;((compile-op . source-1) (load-op . source-1) 
 (compile-op . source-2) (load-op . source-2) &#8230;)
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;operate&lt;/code&gt; takes that list and just performes each operation on its
component in order.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;All this means that ASDF takes a two-step approach: It first
determines what needs to be done, then does it. All the smarts in ASDF
are in that &lt;code&gt;traverse&lt;/code&gt; operation and the underlying mechanisms. The
rest is just a dolist.&lt;/p&gt;

&lt;p&gt;OK, with that out of the way:&lt;/p&gt;

&lt;h2&gt;The Hunt&lt;/h2&gt;

&lt;p&gt;I&amp;#8217;d gotten this error before, but that was when I was running on a
source tree checked out on an NFS-mounted file system on Windows. I
didn&amp;#8217;t pay it much mind, because, hey, it&amp;#8217;s the NFS client on Windows.&lt;/p&gt;

&lt;p&gt;But then this exact same problem started happening to a client using
two Linux machines as the client and the server. We had a problem.&lt;/p&gt;

&lt;p&gt;At first, we suspected that there was an issue with build order (that
result list of &lt;code&gt;traverse&lt;/code&gt;). This was a blind alley: The files were
loaded in exactly the same order in the failing and working
scenarios. No luck.&lt;/p&gt;

&lt;p&gt;The next thing was to instrument &lt;code&gt;operation-done-p&lt;/code&gt; before performing
the operation, and there we saw what happened: &lt;code&gt;operation-done-p&lt;/code&gt;
reported that &lt;code&gt;load-op&lt;/code&gt; had not been performed on a file. But that
file had been loaded into this very same image just minutes before!
Huh?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;operation-done-p&lt;/code&gt; a generic function and has a method that attempts
to handle the most common cases of operations on ASDF components: the
method specialized on &lt;code&gt;(operation component)&lt;/code&gt;, which does the
following in the branch that applies to &lt;code&gt;load-op&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;(defmethod operation-done-p (operation component))&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;cl&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;out-files&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;output-files&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;op-time&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;component-operation-time&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;flet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;latest-in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;             &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;reduce&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#&amp;#39;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mapcar&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#&amp;#39;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;safe-file-write-date&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;in-files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cond&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;c1&quot;&gt;;; &#8230;[cut some branches]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;        &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;out-files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;         &lt;span class=&quot;c1&quot;&gt;;; an operation without output-files is probably meant&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;         &lt;span class=&quot;c1&quot;&gt;;; for its side-effects in the current image,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;         &lt;span class=&quot;c1&quot;&gt;;; assumed to be idem-potent,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;         &lt;span class=&quot;c1&quot;&gt;;; e.g. LOAD-OP or LOAD-SOURCE-OP of some CL-SOURCE-FILE.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;op-time&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;op-time&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;latest-in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;         &lt;span class=&quot;c1&quot;&gt;;; &#8230;[some more branches here]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;         &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;This consults a registry of times when an operation was performed on a
component: &lt;code&gt;component-operation-time&lt;/code&gt; returns a
&lt;a href=&quot;http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_u.htm#universal_time&quot;&gt;universal-time&lt;/a&gt;,
that is a number of seconds, and compares that to the
&lt;a href=&quot;http://www.lispworks.com/documentation/HyperSpec/Body/f_file_w.htm&quot;&gt;file-write-date&lt;/a&gt;
- also a universal-time - of the input file (the .fasl). After some
tracing, we determined that for some reason, the .fasl file was one
second younger than the time that ASDF thought the &lt;code&gt;load-op&lt;/code&gt; had been
performed on it. In other words, the compiler had written the file
AFTER
&lt;a href=&quot;http://www.lispworks.com/documentation/HyperSpec/Body/f_load.htm&quot;&gt;load&lt;/a&gt;
had had a chance to read it. ASDF was reading a file from the future.&lt;/p&gt;

&lt;p&gt;This was the time when we started scratching our heads.&lt;/p&gt;

&lt;p&gt;First, we wrote a little test program to verify we weren&amp;#8217;t crazy:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;wtf.c&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;17&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;18&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;19&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;20&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;21&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;22&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;23&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;24&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;25&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;26&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;27&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;28&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;29&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;30&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;31&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;32&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;33&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;34&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;35&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;36&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;37&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;38&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;39&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;40&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;41&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;42&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;43&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;44&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;45&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;46&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;47&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;48&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;49&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;50&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;c&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;stdio.h&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;sys/fcntl.h&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;unistd.h&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;sys/time.h&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;sys/stat.h&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeval&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tv1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stat&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sb1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sb2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;gettimeofday&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tv1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;%u.%u&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tv1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tv_sec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tv1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tv_usec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;O_WRONLY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;O_CREAT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;O_TRUNC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0660&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;gettimeofday&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tv1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;stat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sb1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;gettimeofday&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;stat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sb2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;cm&quot;&gt;/* never seems to be triggered */&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sb2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_mtime&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sb1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_mtime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;mtime changed between last write (%d) and close (%u)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;       &lt;span class=&quot;n&quot;&gt;sb1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_mtime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sb2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_mtime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;n&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sb1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_mtime&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tv1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tv_sec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;mtime after last write has a future timestamp (%u &amp;gt; %u)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;       &lt;span class=&quot;n&quot;&gt;sb1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_mtime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tv1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tv_sec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;n&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sb2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_mtime&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tv_sec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;mtime after close has a future timestamp (%u &amp;gt; %u)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;       &lt;span class=&quot;n&quot;&gt;sb2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st_mtime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tv2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tv_sec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;n&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;When we ran it, after a while, at timestamps very close to the
boundary to the next second, we&amp;#8217;d get &amp;#8220;mtime after close has a future
timestamp&amp;#8221;. &lt;a href=&quot;http://www.osnews.com/story/19266/WTFs_m&quot;&gt;What. The.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We checked that all machines were synchronized with NTP. They were, to
the same machine on the local network. What is going on?&lt;/p&gt;

&lt;p&gt;Luckily, my colleague Ahmon has a lot of experience with
&lt;a href=&quot;http://nfsforwindows.com/home&quot;&gt;NFS&lt;/a&gt;. His expertise and ample use of
tcpdump finally provided the final puzzle piece: NFS protocol 3 on
Linux has a feature called &amp;#8220;weak cache consistency&amp;#8221;: information can
be supplied by servers after most NFS calls (e.g., WRITE) and has the
server&amp;#8217;s take on file attributes (such as mtime). So if the time on
the server is just a tiny bit ahead of the client, the server will
report the file that the client just wrote is from the client&amp;#8217;s
future.&lt;/p&gt;

&lt;p&gt;When one apparently time-traveling file appears in the source tree,
the &lt;code&gt;traverse&lt;/code&gt; method will consider the system to not have been
loaded, and will reload the .fasl files starting at the time-traveling
file. Anything after that file in the build order could (and did!)
potentially mess up the lisp image. In the best case, it would just
slow down the build a lot by re-loading a ton of .fasl files. Argh.&lt;/p&gt;

&lt;h2&gt;Fixing this Mess (aka, the Workaround)&lt;/h2&gt;

&lt;p&gt;Since ASDF consults a registry of times that a file was loaded, we
decided it would be easiest to alter the method that records this
timestamp: Instead of the current time, it should record whichever is
later: the current time or the timestamp of the file that it loaded.&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;ASDF work-around for NFS files created in the future&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;cl&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defmethod&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;perform&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:after&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;operation&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;load-op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;setf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gethash&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type-of&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;operation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;component-operation-times&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;reduce&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#&amp;#39;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cons&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get-universal-time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;                        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mapcar&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#&amp;#39;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;safe-file-write-date&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;input-files&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;operation&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))))&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;And that&amp;#8217;s it - with this method in place, asdf can now accurately
build our system repeatedly, on NFS, even if wtf.c triggers.&lt;/p&gt;

&lt;h2&gt;Lessons Learned&lt;/h2&gt;

&lt;p&gt;That was a pretty fun afternoon spent debugging our build process. As
a result, we got a working build, and a few shiny new ideas in our
heads:&lt;/p&gt;

&lt;p&gt;One, a program should never rely on the system time and some file&amp;#8217;s
creation time being comparable. This just doesn&amp;#8217;t work anymore in a
distributed system, especially if you&amp;#8217;re using full seconds to
represent time.&lt;/p&gt;

&lt;p&gt;Two, ASDF is pretty flexible (almost to the point of being too
flexible). To diagnose ASDF&amp;#8217;s internal state, all we had to do was
&lt;a href=&quot;http://www.lispworks.com/documentation/HyperSpec/Body/m_tracec.htm&quot;&gt;trace&lt;/a&gt;
some functions it defines, and we managed to put this workaround in
without having to deeply modify any of its sources: All it takes is an
additional :after method. Sweet.&lt;/p&gt;

&lt;p&gt;And three, the Allegro CL fasl loader is very fast (at least it feels
so to me, coming from SBCL): In that tiny window (less than 0.07
seconds of real time) it would load a pretty substantial .fasl file
and asdf would register it as loaded. That&amp;#8217;s pretty impressive! (-:&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>New Lisp Tips Blogs</title>
    <link href="http://boinkor.net/archives/2011/09/new-lisp-tips-blogs.html"/>
    <updated>2011-09-30T10:14:00-07:00</updated>
    <id>http://boinkor.net/archives/2011/09/new-lisp-tips-blogs</id>
    
    <category term="Lisp" />
    
    <content type="html">&lt;p&gt;As of today, there are two new Lisp tips blogs on the web: &lt;a href=&quot;http://lisptips.tumblr.com&quot;&gt;Common Lisp tips&lt;/a&gt; by &lt;a href=&quot;http://xach.livejournal.com/&quot;&gt;Xach&lt;/a&gt; and &lt;a href=&quot;http://slime-tips.tumblr.com/&quot;&gt;SLIME tips&lt;/a&gt; by Stas. Both already have some nice stuff that I didn&amp;#8217;t know about, so I hope they keep the tips coming!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>&#8220;Basic Lisp Techniques&#8221; for sale on Amazon</title>
    <link href="http://boinkor.net/archives/2011/09/basic-lisp-techniques-for-sale-on-amazon.html"/>
    <updated>2011-09-27T14:00:00-07:00</updated>
    <id>http://boinkor.net/archives/2011/09/basic-lisp-techniques-for-sale-on-amazon</id>
    
    <category term="Lisp" />
    
    <content type="html">&lt;p&gt;I just saw that David Cooper&amp;#8217;s &lt;a href=&quot;http://www.franz.com/resources/educational_resources/cooper.book.pdf&quot;&gt;Basic Lisp Techniques&lt;/a&gt; is now available &lt;a href=&quot;http://www.amazon.com/Basic-Lisp-Techniques-ebook/dp/B0058V1FJG/ref=sr_1_1&quot;&gt;on Amazon, as a Kindle edition&lt;/a&gt;, for $9.95.&lt;/p&gt;

&lt;p&gt;Problem is, this book is freely available &lt;a href=&quot;http://www.franz.com/resources/educational_resources/cooper.book.pdf&quot;&gt;on the Franz web site&lt;/a&gt;, doesn&amp;#8217;t seem like it is an authorized conversion, and judging from the free sample the Kindle edition it is a slightly crappy (footnotes didn&amp;#8217;t convert properly, ToC is ugly) pdf-&gt;azw conversion of the PDF. I recommend using the free PDF (you can even convert it yourself using &lt;a href=&quot;http://calibre-ebook.com/&quot;&gt;Calibre&lt;/a&gt; if you want the book on an e-reader, it&amp;#8217;s not hard at all to get very readable results).&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Switching this blog to Octopress</title>
    <link href="http://boinkor.net/archives/2011/09/switching_this_blog_to_octopress.html"/>
    <updated>2011-09-26T22:56:00-07:00</updated>
    <id>http://boinkor.net/archives/2011/09/switching_this_blog_to_octopress</id>
    
    <content type="html">&lt;p&gt;I&amp;#8217;ve just made the jump from a creaky, old, badly-styled and annoying Movable Type installation to &lt;a href=&quot;http://octopress.org&quot;&gt;Octopress&lt;/a&gt;. It looks pretty nice, and as of now works better than MT has ever worked here, although I hope I didn&amp;#8217;t break too many things with the switch over. If you find any 404s where they shouldn&amp;#8217;t be, please contact me.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>SBCL git repo is now official!</title>
    <link href="http://boinkor.net/archives/2011/06/sbcl_git_repo_is_now_official.html"/>
    <updated>2011-06-07T06:16:02-07:00</updated>
    <id>http://boinkor.net/archives/2011/06/sbcl_git_repo_is_now_official</id>
    
    <category term="Lisp" />
    
    <content type="html">&lt;p&gt;Almost exactly four years after I &lt;a href=&quot;http://comments.gmane.org/gmane.lisp.steel-bank.devel/7033&quot;&gt;announced&lt;/a&gt; the availability of the first iteration of the SBCL cvs-&gt;git mirror (and a few more years after the &lt;a href=&quot;http://permalink.gmane.org/gmane.lisp.steel-bank.devel/2536&quot;&gt;cvs-&gt;arch mirror even&lt;/a&gt;!), we now have an official SBCL repository! Many thanks to Nikodemus for doing all the heavy lifting! (-:&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve stopped the (now defuct) cvs-&gt;git mirror. In its place, there is a new repository that mirrors the official git repo. To get the old, now static repo, see &lt;a href=&quot;http://git.boinkor.net/gitweb/sbcl-cvs-import.git&quot;&gt;sbcl-cvs-import&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you are a committer and have any old checkouts around, please make sure that you follow &lt;a href=&quot;http://thread.gmane.org/gmane.lisp.steel-bank.devel/15983/focus=15987&quot;&gt;the procedure for eliminating unnecessary branches / tags&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Userscript for nicer l1sp.org search</title>
    <link href="http://boinkor.net/archives/2010/11/userscript_for_nicer_l1sporg_s.html"/>
    <updated>2010-11-20T08:28:00-08:00</updated>
    <id>http://boinkor.net/archives/2010/11/userscript_for_nicer_l1sporg_s</id>
    
    <category term="Hacks" />
    
    <category term="Lisp" />
    
    <content type="html">&lt;p&gt;I love the &lt;a href=&quot;http://l1sp.org&quot;&gt;l1sp.org&lt;/a&gt; documentation redirection service. It is quick and easy to look stuff up there if you know the name, and it has a pretty good search if you don&amp;#8217;t. However, the search results are not presented very nicely: They&amp;#8217;re very close together, and the ones I&amp;#8217;m looking for most often (mostly CLHS pages) are buried somewhere in the middle.&lt;/p&gt;

&lt;p&gt;So I wrote a userscript (for Firefox through greasemonkey or Google Chrome/Chromium) to improve things a bit: It enables keyboard navigation (j/k or cursor-down/up select the next/previous result, enter opens the page, and / focuses the input field), and searches for the closest match from the results (ranks them by section and then selects the shortest matching entry).&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/antifuchs/userscripts/raw/master/l1sp_org-cursor-support.user.js&quot;&gt;Get the l1sp.org userscript here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I do hope that Xach will consider adding these features to l1sp proper (maybe de-uglified a bit&amp;#8230; that yellow highlight is really not too great). Until then, you can already enjoy the benefits of just a little javascript (-:&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Visualizing the CLHS interlinking structure</title>
    <link href="http://boinkor.net/archives/2010/09/visualizing_the_clhs_interlink.html"/>
    <updated>2010-09-25T00:52:02-07:00</updated>
    <id>http://boinkor.net/archives/2010/09/visualizing_the_clhs_interlink</id>
    
    <category term="Lisp" />
    
    <content type="html">&lt;p&gt;Lately, I&amp;#8217;ve been wondering what we could use the ~110k Hyperlinks in the CLHS for, other than click through the spec in a web browser. For example, given a glossary entry, how do you find out which functions refer to it?&lt;/p&gt;

&lt;p&gt;So I wrote a little program that crawls (a local copy of) the HyperSpec, and creates an RDF graph of its link structure. This graph can be used to answer these questions, or it could be the basis of a useful research overlay on top of the HyperSpec, who knows.&lt;/p&gt;

&lt;p&gt;Lots of tools exist to visualize and manipulate the facts in an RDF graph already; Here&amp;#8217;s a screen shot of &lt;a href=&quot;http://www.franz.com/agraph/gruff/&quot;&gt;gruff&lt;/a&gt; with a small trace through the HyperSpec:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://boinkor.net/assets/images/gruff-with-hyperspec-rdf.png&quot; title=&quot;Gruff with Hyperspec RDF&quot; &gt;&lt;/p&gt;

&lt;p&gt;You can get the code to create the RDF graph &lt;a href=&quot;http://github.com/antifuchs/clsem/&quot;&gt;at github&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Huge life changes ahead.</title>
    <link href="http://boinkor.net/archives/2010/08/huge_life_changes_ahead.html"/>
    <updated>2010-08-11T00:09:39-07:00</updated>
    <id>http://boinkor.net/archives/2010/08/huge_life_changes_ahead</id>
    
    <category term="Lisp" />
    
    <content type="html">&lt;p&gt;In October, I will be moving to California to work for a &lt;a href=&quot;http://franz.com/&quot;&gt;hugely awesome lisp company&lt;/a&gt; there.&lt;/p&gt;

&lt;p&gt;Exciting and excellent times ahead, I&amp;#8217;m sure!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>I think this is going to be pretty sweet.</title>
    <link href="http://boinkor.net/archives/2010/04/i_think_this_is_going_to_be_pr.html"/>
    <updated>2010-04-28T19:51:47-07:00</updated>
    <id>http://boinkor.net/archives/2010/04/i_think_this_is_going_to_be_pr</id>
    
    <category term="Lisp" />
    
    <content type="html">&lt;p&gt;&lt;img src=&quot;http://boinkor.net/assets/images/clucumber-baby-steps.png&quot; title=&quot;Clucumber baby steps&quot; &gt;&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve been toying around with making a Common Lisp adapter to &lt;a href=&quot;http://cukes.info/&quot;&gt;Cucumber&lt;/a&gt;, a behavior-driven development tool. I think this will really be very sweet.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s how the step definition file would look like (these are really just stubs; in reality, you&amp;#8217;d put in the lisp code you want to happen for the given textual description):&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;Clucumber example steps  &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;cl&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Given*&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;^I start clucumber in (.*)$&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;When*&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;^I define some-other-package as the test package$&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pending&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Then*&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;^the current package should be \&amp;quot;([^\&amp;quot;]+)\&amp;quot;$&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;package-name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pending&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;package is ~A&amp;quot;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;package-name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;

</content>
  </entry>
  
  <entry>
    <title>Vienna informal Lisp meeting 2010-02-27</title>
    <link href="http://boinkor.net/archives/2010/02/vienna_informal_lisp_meeting_2.html"/>
    <updated>2010-02-19T10:02:49-08:00</updated>
    <id>http://boinkor.net/archives/2010/02/vienna_informal_lisp_meeting_2</id>
    
    <category term="Lisp" />
    
    <content type="html">&lt;p&gt;Date: Saturday, 2010-02-27&lt;br/&gt;
Time: 12:30
Venue: In and around the Metalab, Rathausstrasse 6, Vienna (&lt;a href=&quot;http://maps.google.com/maps?f=q&amp;amp;source=s_q&amp;amp;hl=en&amp;amp;geocode=&amp;amp;q=rathausstra%C3%9Fe+6&amp;amp;sll=48.208974,16.35875&amp;amp;sspn=0.009509,0.014999&amp;amp;ie=UTF8&amp;amp;hq=&amp;amp;hnear=Rathausstra%C3%9Fe+6,+Innere+Stadt+1010+Wien,+Austria&amp;amp;ll=48.209174,16.358364&amp;amp;spn=0.009509,0.014999&amp;amp;z=16&amp;amp;iwloc=A&quot;&gt;map&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m pleased to announce the first international totally informal lisp meeting in Vienna. A bunch of Lisp hackers are coming to here on the 27th, and we will meet, talk and hack in and around the Metalab.&lt;/p&gt;

&lt;p&gt;The approximate schedule is as follows:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;12:30&lt;/em&gt; - Lunch at &lt;a href=&quot;http://www.frommehelene.at/&quot;&gt;Fromme Helene&lt;/a&gt;. There is a table reserved for 15 persons (we&amp;#8217;re 5 confirmed hackers at the moment). If you want in, drop me a line.&lt;br/&gt;
~&lt;em&gt;14:30&lt;/em&gt; - Reconvene at the Metalab for hacking/coffee/cold drinks/(optional) lightning talks&lt;/p&gt;

&lt;p&gt;Hackers who have confirmed they&amp;#8217;ll be there, so far:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tobias C. Rittweiler&lt;/li&gt;
&lt;li&gt;Luke Gorrie&lt;/li&gt;
&lt;li&gt;Stelian Ionescu&lt;/li&gt;
&lt;li&gt;Attila Lendvai&lt;/li&gt;
&lt;li&gt;Gábor Melis&lt;/li&gt;
&lt;li&gt;Mark Evenson&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Thanks to the SBCL team for infusing this event with positive energy. SBCL: Harming the software industry since 1999.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>cl-beanstalk: A queue service client</title>
    <link href="http://boinkor.net/archives/2010/01/cl-beanstalk_a_queue_service_c.html"/>
    <updated>2010-01-31T17:49:52-08:00</updated>
    <id>http://boinkor.net/archives/2010/01/cl-beanstalk_a_queue_service_c</id>
    
    <category term="Lisp" />
    
    <content type="html">&lt;p&gt;Over the weekend, I wrote a little client library to a queue server that I&amp;#8217;ve grown very fond of over the last year, &lt;a href=&quot;http://kr.github.com/beanstalkd/&quot;&gt;beanstalk&lt;/a&gt;. It&amp;#8217;s a very simple queue server, but it comes with a nice feature (delayed jobs) that I&amp;#8217;ve had a use for recently.&lt;/p&gt;

&lt;p&gt;The queue server is nicely engineered (written in C, works with queues a few million jobs deep), and very fast; it has guards in the protocol against worker failure, and it was a pleasure to implement: The whole thing is just 320 lines of code, including comments.&lt;/p&gt;

&lt;p&gt;You can get the source (and a tiny example) at the &lt;a href=&quot;http://github.com/antifuchs/cl-beanstalk&quot;&gt;cl-beanstalk&lt;/a&gt; github repository.&lt;/p&gt;

&lt;p&gt;Hope this is useful for anyone else - I am planning on using this in autobench myself, to distribute work across several build hosts.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Hunchentoot gets a debugging-acceptor</title>
    <link href="http://boinkor.net/archives/2009/11/hunchentoot_gets_a_debugging-a.html"/>
    <updated>2009-11-15T22:11:36-08:00</updated>
    <id>http://boinkor.net/archives/2009/11/hunchentoot_gets_a_debugging-a</id>
    
    <category term="Lisp" />
    
    <content type="html">&lt;p&gt;Today, I submitted a patch (the first free software lisp one in months for me!) to the &lt;a href=&quot;http://weitz.de/hunchentoot/&quot;&gt;Hunchentoot&lt;/a&gt; project, and it got accepted. Yay!&lt;/p&gt;

&lt;p&gt;Some backstory: Hunchentoot&amp;#8217;s 1.0.0 release dropped a lot of implementation-dependent features, among them functionality to invoke the debugger if an error happens while handling a request. While &lt;a href=&quot;http://paste.lisp.org/display/81046&quot;&gt;workarounds&lt;/a&gt; &lt;a href=&quot;http://www.lispworks.com/documentation/HyperSpec/Body/v_break_.htm&quot;&gt;exist&lt;/a&gt;, none of them were obvious to new users or users who recently upgraded.&lt;/p&gt;

&lt;p&gt;The patch I sent should fix this, hopefully. It adds a rudimentary error handling protocol to Hunchentoot, and provides two generic functions whose behavior can be adapted to your error handling needs. You can see for yourself in Hunchentoot&amp;#8217;s &lt;a href=&quot;http://bknr.net/trac/browser/trunk/thirdparty/hunchentoot&quot;&gt;svn repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re a Hunchentoot user, I urge you to test this (in both development mode using debuggable-acceptor and running with the default settings). The sooner you find bugs, the sooner they can be fixed, the sooner a release can be pushed out. And if you don&amp;#8217;t find bugs at all, that&amp;#8217;s cool, too (-:&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>There are only two hard problems in Austrian family law:</title>
    <link href="http://boinkor.net/archives/2009/09/two_hard_problems.html"/>
    <updated>2009-09-06T21:24:46-07:00</updated>
    <id>http://boinkor.net/archives/2009/09/two_hard_problems</id>
    
    <category term="Hacks" />
    
    <content type="html">&lt;p&gt;Caching and naming things.&lt;/p&gt;

&lt;p&gt;Well, maybe not caching. But if two people are getting married in Austria, they do have to solve the other hard problem.
That is, one partner gets to keep their name, and the other partner has to decide what to do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Take on the partner&amp;#8217;s name (it&amp;#8217;s expected that the female partner does this),&lt;/li&gt;
&lt;li&gt;keep one&amp;#8217;s old name,&lt;/li&gt;
&lt;li&gt;or prepend or append one&amp;#8217;s own name to the partner&amp;#8217;s name.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;In the latter two cases, Austrian family law introduces a &amp;#8220;family name&amp;#8221; that is one of the two partners&amp;#8217; original names, which is what they pass on to their children. This makes both options a non-solution: You get your pie, but something else gets eaten: Possibly your &lt;a href=&quot;http://juanfgs.files.wordpress.com/2008/02/internet-o_rlyeh.jpg&quot;&gt;sanity&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, if partners &amp;#8220;Fuchs&amp;#8221; and &amp;#8220;Liewald&amp;#8221; were to get married and wanted to use the (wonderfully punny) &amp;#8220;Liewald-Fuchs&amp;#8221; as both partners&amp;#8217; name and the name that their children get, they would be out of luck. Or so it would seem.&lt;/p&gt;

&lt;p&gt;It turns out there might be a way to pull this off. A person who recently got a bit of media attention bearing the last name of &amp;#8220;Hollunder-Hollunder&amp;#8221; has done this already (but with slightly different starting parameters and a different goal):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get married, prepend/append names such that one partner has the desired combination of names,&lt;/li&gt;
&lt;li&gt;divorce, arrange that both partners keep the new names,&lt;/li&gt;
&lt;li&gt;get married &lt;em&gt;again,&lt;/em&gt; and have the other partner take on the desired name.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;One divorce costs &lt;a href=&quot;http://www.help.gv.at/Content.Node/10/Seite.100001.html#einver&quot;&gt;€500&lt;/a&gt;, the legal cost for a marriage certificate after a divorce is &lt;a href=&quot;http://www.help.gv.at/Content.Node/7/Seite.070100.html#Kosten&quot;&gt;€70&lt;/a&gt;. Might just be worth it (-:&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Clojure and Art of Illusion: BFF</title>
    <link href="http://boinkor.net/archives/2009/03/clojure_and_art_of_illusion_bf.html"/>
    <updated>2009-03-29T13:00:14-07:00</updated>
    <id>http://boinkor.net/archives/2009/03/clojure_and_art_of_illusion_bf</id>
    
    <category term="Lisp" />
    
    <content type="html">&lt;p&gt;Two weeks ago, &lt;a href=&quot;http://www.23hq.com/antifuchs/photo/4075448&quot;&gt;the rotary program dial on my dishwasher broke&lt;/a&gt;. Luckily, I could fix it with two Lego parts (&lt;a href=&quot;http://www.ihmc.us/lego/kits/peices.html&quot;&gt;a Cross Axle #6 and a 16-teeth gear&lt;/a&gt;) initially, but the program selection experience suffered from the axle&amp;#8217;s being too thin: it&amp;#8217;d always bend in the turning direction until the selector would too-rapidly rotate past the point I wanted to select. Ugh.&lt;/p&gt;

&lt;p&gt;Luckily for me, there&amp;#8217;s a &lt;a href=&quot;http://reprap.org/bin/view/Main/WebHome&quot;&gt;reprap&lt;/a&gt; at the &lt;a href=&quot;http://reprap.soup.io&quot;&gt;Metalab&lt;/a&gt;. This is a low-cost 3d printer that can extrude parts made of ABS (the same material that Lego pieces are made of). With the help of &lt;a href=&quot;http://metalab.at/wiki/Benutzer:Wizard23&quot;&gt;Philipp&lt;/a&gt;&amp;#8217;s MetaCADEvaluator plugin to &lt;a href=&quot;http://aoi.sf.net&quot;&gt;Art of Illusion (AoI)&lt;/a&gt;, I managed to create a very nice 3d model of a replacement for the dial. That plugin let me define parameters for each part, so I could easily resize all parts manually once I discovered that I&amp;#8217;d mistakenly noted down each part&amp;#8217;s diameter instead of the radius.  However, this was slightly fiddly business: All editing happens inside Art of Illusion&amp;#8217;s part name text fields, the syntax is slightly odd, and you can&amp;#8217;t define your own part library.&lt;/p&gt;

&lt;p&gt;Enter my urge to try out &lt;a href=&quot;http://clojure.org&quot;&gt;Clojure&lt;/a&gt;. This little side project took three steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find out how to embed clojure in AoI (done).&lt;/li&gt;
&lt;li&gt;Make it open a swank port so I can on AoI from emacs without having to recompile all the time (done).&lt;/li&gt;
&lt;li&gt;Build a part definition DSL (ongoing, one milestone achieved).&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;There&amp;#8217;s a detailed description of these steps after the jump. Here&amp;#8217;s &lt;a href=&quot;http://github.com/antifuchs/aoi-swank-plugin/&quot;&gt;the github project for my AoI clojure plugin&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Embedding clojure inside AoI&lt;/h2&gt;

&lt;p&gt;This was rather easier than I&amp;#8217;d thought. The hardest part was finding out how clojure&amp;#8217;s &lt;a href=&quot;http://clojure.org/compilation&quot;&gt;gen-class&lt;/a&gt; works so as to generate two classes, one to implement the Plugin interface (so that the plugin gets loaded) and one to implement the Tool interface (so I get a menu entry that lets me start the Swank listener).&lt;/p&gt;

&lt;p&gt;After that, it was building an extensions.xml and figuring out how to make ant build a .jar file that AoI could grok (both easy).&lt;/p&gt;

&lt;h2&gt;Making it open a Swank port&lt;/h2&gt;

&lt;p&gt;That one was easy, as well: Just add the swank-clojure project as a submodule, and add its sources to the plugin .jar file. Having done that, open a port and add the current window somewhere so we can manipulate objects in it later (&lt;a href=&quot;http://github.com/antifuchs/aoi-swank-plugin/blob/1987fb6d3477fc5835d1c37b2762ac2cf82c5696/src/org/reprap/artofillusion/SwankTool.clj#L24&quot;&gt;source&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;So after that, opening the Swank port vie the tool menu let me connect to AoI with emacs and off I went, doing experiments! For all who want to build Art of Illusion plugins with clojure, I&amp;#8217;ve made a minimal-plugin branch that does exactly this, available &lt;a href=&quot;http://github.com/antifuchs/aoi-swank-plugin/tree/minimal-plugin&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Building a part definition DSL&lt;/h2&gt;

&lt;p&gt;This one was the biggie: I wanted to write lisp that lets me interactively define 3d models. What is here right now is a little DSL that lets me create &lt;a href=&quot;http://github.com/antifuchs/aoi-swank-plugin/blob/1987fb6d3477fc5835d1c37b2762ac2cf82c5696/src/org/reprap/artofillusion/objects.clj#L165-171&quot;&gt;simple 3d models&lt;/a&gt;, and lets me perform boolean operations on them (&lt;a href=&quot;http://github.com/antifuchs/aoi-swank-plugin/blob/1987fb6d3477fc5835d1c37b2762ac2cf82c5696/src/org/reprap/artofillusion/objects.clj#L156-163&quot;&gt;union, difference, intersection&lt;/a&gt;). This is enough to make &lt;a href=&quot;http://github.com/antifuchs/aoi-swank-plugin/blob/1987fb6d3477fc5835d1c37b2762ac2cf82c5696/examples/dishwasher-part.clj&quot;&gt;this model&lt;/a&gt;, which is the &lt;a href=&quot;http://reprap.soup.io/post/15859377/Reprapping-a-Dishwasher-Replacement-Knob&quot;&gt;exact same part we extruded before&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are still things left TODO:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The syntax of the DSL needs more love. It is quite verbose right now.&lt;/li&gt;
&lt;li&gt;Models need relative transformations: witness the &amp;#8220;90 0 0&amp;#8221; on almost every part.&lt;/li&gt;
&lt;li&gt;For debugging purposes, it would be useful to get a tree of the composite objects (with only the end result visible), instead of just the one result object.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;All of this was way easier and far more fun than I&amp;#8217;d thought building plugins to java projects could be: I&amp;#8217;d gone in expecting something in the order of gratuitously frustrating and mind-numbingly boring. Instead, after I had the first few hurdles out of the way (most of which were rooted in my emacs&amp;#8217;s slime config (-:), I was euphoric from regular small successes all the way. As you can tell from the &lt;a href=&quot;http://github.com/antifuchs/aoi-swank-plugin/commits/master&quot;&gt;commit history&lt;/a&gt;, this took a little over 3 days to build.&lt;/p&gt;

&lt;p&gt;I strongly recommend the Clojure and swank-clojure approach to building plugins to java projects: Once you&amp;#8217;ve got a Swank listener open, it&amp;#8217;s all experimentation and small bits of progress. Excellent stuff, all around.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Perfectstorm by Johann Korndoerfer</title>
    <link href="http://boinkor.net/archives/2008/04/perfectstorm_by_johann_korndoe.html"/>
    <updated>2008-04-01T17:34:53-07:00</updated>
    <id>http://boinkor.net/archives/2008/04/perfectstorm_by_johann_korndoe</id>
    
    <category term="Lisp" />
    
    <content type="html">&lt;p&gt;&lt;img src=&quot;http://erleuchtet.org/with-health-bars-thumb-300x225.png&quot; alt=&quot;perfectstorm screenshot&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This isn&amp;#8217;t original work, so perhaps more suited to being in my &lt;a href=&quot;http://mublag.boinkor.net&quot;&gt;soup&lt;/a&gt; than this blog, but it&amp;#8217;s so cool it just has to be on Planet Lisp. &lt;a href=&quot;http://erleuchtet.org/2008/03/project-overview-perfectstorm.html&quot;&gt;perfectstorm&lt;/a&gt; is:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;a real time strategy game study written in Common Lisp using OpenGL for graphics display and cairo for texture generation.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Looks very very interesting. Google SoC students take note: this is an open source project (-:&lt;/p&gt;

&lt;p&gt;&lt;small&gt;(found via &lt;a href=&quot;http://nein.gei.st/post/1968414/perfectstorm-is-a-real-time-strategy-game&quot;&gt;neingeist&lt;/a&gt;)&lt;/small&gt;&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>A public service announcement</title>
    <link href="http://boinkor.net/archives/2008/01/a_public_service_announcement.html"/>
    <updated>2008-01-15T16:15:06-08:00</updated>
    <id>http://boinkor.net/archives/2008/01/a_public_service_announcement</id>
    
    <category term="Lisp" />
    
    <content type="html">&lt;p&gt;(This blog entry is &lt;strong&gt;outdated&lt;/strong&gt;. The currently recommended way to get lisp software and its dependencies is &lt;a href=&quot;http://quicklisp.org/&quot;&gt;quicklisp&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;Outdated information&lt;/h2&gt;

&lt;p&gt;It has been brought to our attention that &lt;a href=&quot;http://www.cliki.net/ASDF-Install&quot; title=&quot;CLiki : ASDF-Install&quot;&gt;asdf-install&lt;/a&gt; is still thought to be the preferred way to install cool lisp software. I would like to use this space to advertise an alternative tool that too few people know about, and that allows you to almost instantly (OK, as fast as your computer can install the required software and download &amp;amp; build the packages) get you up and running with and get you updates of the newest in cool lisp packages.&lt;/p&gt;

&lt;p&gt;That tool is &lt;a href=&quot;http://common-lisp.net/project/clbuild/&quot;&gt;clbuild&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It doesn&amp;#8217;t yet bring in all of the software available on cliki, but it includes enough cool things that I would recommend it to anyone who wants to check out with a minimum of hassle either of (not an exhaustive list, but you get the idea):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;McCLIM,&lt;/li&gt;
&lt;li&gt;Climacs, Closure, Beirc, Gsharp,&lt;/li&gt;
&lt;li&gt;Hunchentoot, and&lt;/li&gt;
&lt;li&gt;CXML&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Or just get a lisp system up and running that includes most of the useful libraries out there. If you have been messing around with asdf-install (raise hands if you ever asdf-installed a library to get its dependencies and then pulled that library from CVS again and replaced the symlinks manually), do yourself a favour and check it out.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Broadcatching, iTunes, a &#8220;mini&#8221; Apple TV</title>
    <link href="http://boinkor.net/archives/2007/12/broadcatching_itunes_a_mini_ap.html"/>
    <updated>2007-12-06T01:18:37-08:00</updated>
    <id>http://boinkor.net/archives/2007/12/broadcatching_itunes_a_mini_ap</id>
    
    <content type="html">&lt;p&gt;Recently, I got a used Mac Mini from a friend; I decided to put it to good use as a media station in my living room, and it does indeed work pretty well (after fixing it up with codecs that are in use in the real world, but that&amp;#8217;s not the topic of this article (-:).&lt;/p&gt;

&lt;p&gt;One thing that I find very useful is the ability to import movie files (that one might download from the vast and unfriendly-to-copyright-holders internet, as described &lt;a href=&quot;http://www.engadget.com/2004/11/23/how-to-broadcatching-using-rss-bittorrent-to-automatically/&quot;&gt;here&lt;/a&gt; for instance) into iTunes on my desktop mac and have the Front Row thing on the living room machine play them over the network. The steps one needs to take in order to get this working are many and tedious, and so I&amp;#8217;ve created an AppleScript to do all the hard work for me. It:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Converts an .avi movie (they usually come encoded as DivX or Xvid) into a standalone .mov file using Quicktime Player (this doesn&amp;#8217;t transcode),&lt;/li&gt;
&lt;li&gt;extracts the Show name, Season, Episode number, Episode name from the file name via a friend&amp;#8217;s service called &amp;#8220;renamr&amp;#8221; (a telnet 2.0 service, he calls it),&lt;/li&gt;
&lt;li&gt;imports the file into iTunes, tags it nicely, and&lt;/li&gt;
&lt;li&gt;cleans up after itself.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The files thus imported will pop up in the nicely remote-controllable interface, marked as &amp;#8220;unwatched,&amp;#8221; and wait for me to finally get some spare time to sit down and watch them. (Which might very well be after the &lt;a href=&quot;http://en.wikipedia.org/wiki/2007_Writers_Guild_of_America_strike&quot;&gt;WGA strike&lt;/a&gt; ends, so it all should work out nicely in the end.)&lt;/p&gt;

&lt;p&gt;If you find yourself wishing for a similar solution, download &lt;a href=&quot;http://boinkor.net/mac/Save%20as%20TV%20show.scpt&quot;&gt;this file&lt;/a&gt;, read the comments in the beginning, skip over the MIT-style licence, and read the code until you are convinced I&amp;#8217;m not doing anything stupid or malicious. Then, have fun using it!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>CXML-RPC update: changed interface, includes server part</title>
    <link href="http://boinkor.net/archives/2007/12/cxmlrpc_update_changed_interfa.html"/>
    <updated>2007-12-03T22:45:16-08:00</updated>
    <id>http://boinkor.net/archives/2007/12/cxmlrpc_update_changed_interfa</id>
    
    <content type="html">&lt;p&gt;I didn&amp;#8217;t really like the DWIM interface for type translations on the client, so I made the type information mandatory. (-:&lt;/p&gt;

&lt;p&gt;This means that instead of:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;cl&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;xrpc:call&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;http://localhost:8080/RPC2&amp;quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;addNumbers&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; WRONG&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;You get to do this:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;cl&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;xrpc:call&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;http://localhost:8080/RPC2&amp;quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;addNumbers&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:integer&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;                                                         &lt;span class=&quot;ss&quot;&gt;:double&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;                                                         &lt;span class=&quot;ss&quot;&gt;:double&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;mf&quot;&gt;6.0&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;This doesn&amp;#8217;t look vastly superior, but consider this case:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;cl&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;xrpc:call&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;http://localhost:8080/RPC2&amp;quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;weekDay&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get-universal-time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Where before, you had to construct an xml-rpc-date structure; ew. This also allows nicer handling of (unsigned-byte 8) vectors (you can base64-encode them now), and you don&amp;#8217;t have to construct yucky xml-rpc-struct objects anymore: just use alists. The decoding functions now return the type tag that they saw in the response or request.&lt;/p&gt;

&lt;p&gt;Speaking of requests, the server is now finished, lifting CXML-RPC to more or less the same level as s-xml-rpc. It implements the introspection functions specified in &lt;a href=&quot;http://xmlrpc-c.sourceforge.net/introspection.html&quot;&gt;xmlrpc-c&amp;#8217;s documentation&lt;/a&gt;, and the &lt;a href=&quot;http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php&quot;&gt;faults_interop spec&lt;/a&gt;. You can define methods for different handlers, which means that you can attach more than one handler to different URLs and they can expose different sets of methods to the world. This might be handy for those running virtual hosts.&lt;/p&gt;

&lt;p&gt;In response to yesterday&amp;#8217;s post, Rafal Strzalinski pointed me at Ivan Boldyrev&amp;#8217;s &lt;a href=&quot;http://mesemb.ru/soft/lisp/&quot;&gt;s-xml-rpc-hunchentoot&lt;/a&gt;, which adapts the s-xml-rpc server functions for use with hunchentoot&amp;#8217;s handlers. There&amp;#8217;s no port to DRAKMA for the client part.&lt;/p&gt;

&lt;p&gt;I think you should give CXML-RPC a try if you either want to expose multiple sets of methods on different handlers, or you don&amp;#8217;t want to install aserve just for an xml-rpc client. (-:&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>XML-RPC client library using Drakma and CXML</title>
    <link href="http://boinkor.net/archives/2007/12/xmlrpc_client_library_using_dr.html"/>
    <updated>2007-12-02T16:30:37-08:00</updated>
    <id>http://boinkor.net/archives/2007/12/xmlrpc_client_library_using_dr</id>
    
    <content type="html">&lt;p&gt;A few weeks ago, I tried using &lt;a href=&quot;http://common-lisp.net/project/s-xml-rpc/&quot; title=&quot;S-XML-RPC&quot;&gt;S-XML-RPC&lt;/a&gt; for use with a hunchentoot-based web interface to &lt;a href=&quot;http://libtorrent.rakshasa.no/&quot; title=&quot;The libTorrent and rTorrent Project - Trac&quot;&gt;rtorrent&lt;/a&gt;. Unfortunately, it comes with a long list of dependencies that are already implemented better by &lt;a href=&quot;http://weitz.de&quot;&gt;Ediware&lt;/a&gt; such as &lt;a href=&quot;http://www.weitz.de/drakma/&quot; title=&quot;DRAKMA - A Common Lisp web client&quot;&gt;drakma&lt;/a&gt;: it can speak HTTPS, connect via proxies, and allows cookies (although I&amp;#8217;m not aware of any xml-rpc implementation that supports this (-:).&lt;/p&gt;

&lt;p&gt;So I re-implemented s-xml-rpc&amp;#8217;s client part to use the libraries that are already available in &lt;a href=&quot;http://common-lisp.net/project/clbuild/&quot;&gt;clbuild&lt;/a&gt;, and got a pretty pleasant-to-use library. To simply invoke an xml-rpc method, use:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;cl&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;xrpc:call&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;http://betty.userland.com/RPC2&amp;quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;examples.getStateName&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:integer&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;41&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;South Dakota&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nb&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;xrpc:call&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;http://time.xmlrpc.com/RPC2&amp;quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;currentTime.getCurrentTime&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;lt;CXML-RPC::XML-RPC-DATE&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;20071202T06:56:43&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;It&amp;#8217;s entirely undocumented right now, and some names (and interfaces) may be subject to change, but I&amp;#8217;m making it available now anyway, at &lt;a href=&quot;http://sbcl.boinkor.net/gitweb?p=cxml-rpc.git;a=summary&quot;&gt;my git repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The plans for the near future (e.g. next weekend) include a server part based on &lt;a href=&quot;http://weitz.de/hunchentoot&quot;&gt;Hunchentoot&lt;/a&gt;, and, um, test cases and documentation. Stay tuned!&lt;/p&gt;
</content>
  </entry>
  
</feed>

