Zach Beane Common LispTumblr (3.0; @zblisp)https://lispblog.xach.com/Maxima in the browser with ECL and wasm<p>Via Raymond Toy on the ecl mailing list, <a href="http://maxima-on-wasm.pages.dev/">Maxima in the browser</a>.</p>https://lispblog.xach.com/post/773844754188419072https://lispblog.xach.com/post/773844754188419072Mon, 27 Jan 2025 11:37:46 -0500lispeclmaximaOCR from Common Lisp<p><a href="https://nickfa.ro/wiki/OCRing_Music_from_YouTube_with_Common_Lisp">Neat use of CL for OCR</a> by Nick Faro. It leverages FFI and run-program nicely to get the job done.</p><p>I think run-program or equivalent is amazingly handy at getting quick CL access to outside functionality.</p><p>I ran a busy website that used imagemagick a lot, but I never bothered to use FFI. I called “convert” and friends via run-program, and it had the advantage that incorrect use of the C API never crashed my CL session.</p><p>run-program is not particularly fast, but for my application (and many others) it can be fast enough.</p>https://lispblog.xach.com/post/771929720703090688https://lispblog.xach.com/post/771929720703090688Mon, 06 Jan 2025 08:19:08 -0500lispToilet Lisp<p>This seems like an interesting old incomplete project - <a href="https://matthias.benkard.de/journal/37">Toilet Lisp</a> with some old <a href="https://github.com/benkard/toilet/blob/master/JOURNAL">source code</a> too.</p>https://lispblog.xach.com/post/771764698602520576https://lispblog.xach.com/post/771764698602520576Sat, 04 Jan 2025 12:36:11 -0500lispJackson Lee Underwriting has a remote Common Lisp job open<p><a href="https://jacksonleeunderwriting.co.uk/about-us/job-vacancies/">Check it out!</a></p>https://lispblog.xach.com/post/635869861926649856https://lispblog.xach.com/post/635869861926649856Thu, 26 Nov 2020 12:45:55 -0500Non-symbols as keyword arguments<p>Sometimes I like to have a short function call to make a lookup table
with arbitrary keys and values. Something like this:</p>
<pre><code>(table "name" "Alice" "age" 42) => #<TABLE ...>
</code></pre>
<p>This is easy enough to define like so:</p>
<pre><code>(defun table (&rest keys-and-values)
;;; loop over keys and values to construct a table
...)
</code></pre>
<p>But there’s another option that works:</p>
<pre><code>(defun table (&rest keys-and-values &key &allow-other-keys)
...)
</code></pre>
<p>This version has the advantage that missing arguments (e.g. <code>(table
"name")</code>) are caught at compile-time!</p>
<p>I’ve been using this construct for a few years, but recently found out
about <a href="http://l1sp.org/cl/3.5.1.5">3.5.1.5</a>, which says:</p>
<blockquote>
<p>It is not permitted to supply a keyword argument to a function using
a name that is not a symbol.</p>
</blockquote>
<p>Yikes! That seems simple and straightforward: what I’m doing is not
permitted. However! Every implementation I’ve tried (only three,
admittedly) actually <em>allows</em> my not-symbol keywords without
complaint!</p>
<p>I’m too old to think that “it works everywhere today” means “it will
continue to work in SBCL tomorrow”, so I’m trying to figure out where
I stand. 3.5.1.5 also says this:</p>
<blockquote>
<p>If this situation occurs in a safe call, an error of type
program-error must be signaled unless keyword argument checking is
suppressed as described in Section
<a href="http://l1sp.org/cl/3.4.1.4.1">3.4.1.4.1</a> (Suppressing Keyword
Argument Checking); and in an unsafe call the situation has
undefined consequences.</p>
</blockquote>
<p>So does that mean my code is:</p>
<ul>
<li>a safe call with suppressed keyword argument checking?</li>
<li>…and is that good to use now and forever?</li>
<li>an unsafe call with undefined consequences?</li>
<li>something else?</li>
</ul>
<p>I know the same effect could be achieved with a compiler macro, but
I’d like to know if I can use this simpler option safely.</p>https://lispblog.xach.com/post/631322365781065728https://lispblog.xach.com/post/631322365781065728Wed, 07 Oct 2020 09:05:25 -0400New SBCL 2.0.9 behavior breaks some stuff<p>The <a href="http://www.sbcl.org/news.html#2.0.9">latest SBCL</a> handles slot
<code>:initform</code> and <code>:type</code> options in a new way. It’s mentioned in the
release notes.</p>
<blockquote>
<p>minor incompatible change: the compiler signals a warning at
compile-time when an initform of T, NIL or 0 does not match a
STANDARD-CLASS slot’s declared type._</p>
</blockquote>
<p>Sounds pretty benign, but it <a href="http://report.quicklisp.org/2020-09-28/failure-report.html">breaks dozens of
projects</a>
in Quicklisp. (To be fair, most of the failures are caused by a small
number of core systems on which many other systems depend.)</p>
<p>Here’s an example of the new behavior:</p>
<pre><code>(defclass foo ()
((name :type string :initform nil)))
</code></pre>
<p>With the above defclass form, SBCL 2.0.9 will signal a warning at
compile time:</p>
<pre><code>; processing (DEFCLASS FOO ...)
; file: foo.lisp
; in: DEFCLASS FOO
; (NAME :TYPE STRING :INITFORM NIL)
; ==>
; (SB-KERNEL:THE* (STRING :SOURCE-FORM NIL :USE-ANNOTATIONS T) NIL)
;
; caught WARNING:
; Constant NIL conflicts with its asserted type STRING.
; See also:
; The SBCL Manual, Node "Handling of Types"
;
; compilation unit finished
; caught 1 WARNING condition
</code></pre>
<p>This compile-time warning means “failure” as far as loading with ASDF
is concerned.</p>
<p>If you have both <code>:type</code> and <code>:initform</code> in your slot definitions, and
you want to be compatible with the latest SBCL, make sure the initform
type matches the slot type. If you want to use NIL as the initform,
one easy option is to set the type to <code>(or null <actual type>)</code>.</p>https://lispblog.xach.com/post/630527392836943872https://lispblog.xach.com/post/630527392836943872Mon, 28 Sep 2020 14:29:40 -0400Ultralisp search is awesome<p><a href="https://ultralisp.org/">Ultralisp.org</a> has a great new search system. It indexes the docstrings of all the Ultralisp projects, and as a result it is very easy to search for specific functionality and get useful results. For example, I wanted to see what projects have base64-related functions, and now it’s just <a href="https://ultralisp.org/search/?query=base64">a simple search away</a>. I highly recommend it.</p>https://lispblog.xach.com/post/190553011248https://lispblog.xach.com/post/190553011248Thu, 30 Jan 2020 12:12:29 -0500SBCL20 in Vienna<p>Last week I attended the <a href="http://www.sbcl.org/sbcl20/">SBCL 20th anniversary
workshop</a>, held in Vienna, Austria. Here
are some rough impressions - I wish I had detailed enough notes to
recreate the experience for those who did not attend, but alas, this
is what you get! It’s incomplete and I’m sorry if I’ve left out
someone unfairly - you have to go yourself next time so you don’t miss
a thing.</p>
<h2>Structure of the gathering</h2>
<p>I didn’t go to SBCL10, so I didn’t know what to expect. There were few
speakers announced, and I worried (to myself) that this was a sign of
insufficient participation, but I couldn’t have been more wrong.</p>
<p>Philipp Marek played host at his employer,
<a href="https://www.brz.gv.at/en">BRZ</a>. We had a large room laid out with
several tables, ample power, notepads, markers, and treats, fresh food
and drink, and a stage area with chairs set out for an audience.</p>
<p>The conference lead off with a BRZ representative who explained BRZ’s
purpose with an English-language video and encouraged qualified people
to consider joining the company.</p>
<p>Christophe Rhodes acted as master of ceremonies. He put the conference
in historical context and explained the format. While there were only
a small number of planned talks, the remainder of the two-day
conference was intended for brainstorming, reminiscing, hacking, and
impromptu talks by anyone with an interesting idea, demo, or
controversial proclamation. He challenged all of us to pick something
to work on and present it by the end of the conference.</p>
<p>With everyone in the same room, it was nice to see people help each
other in unexpected ways. People describing a problem would get
interrupted by people who could help. And not “Have you tried
installing My Favorite Linux?”-type unhelpful speculation - it was
always valuable in one form or another. The breadth and depth of SBCL
and Common Lisp knowledge meant that, for example, someone could
explain why a certain decision was made in CMUCL 30 years ago, why
SBCL went in a different direction 20 years ago, and how things could
be improved today.</p>
<p>I chose to revisit a problem I first wrote about <a href="https://lispblog.xach.com/post/104872127228/a-verbosity-conundrum">five years
ago</a>. It
boils down to this: can a third party (Quicklisp, in this case)
control the dynamic environment of each load-system operation when
recursively loading a system? The SBCL connection is a little loose,
but it relates to how SBCL’s compiile-time analysis warnings should be
shown prominently for local development, even when loading systems
with <code>ql:quickload</code>.</p>
<p>A lot of people pitched in with ideas and suggestions. Mark Evanson in
particular acted as a sounding board in a way that helped me get to
the essence of the problem. Unfortunately, I wasn’t able to find a
solution before the end of the conference.</p>
<p><img src="https://64.media.tumblr.com/c2640353523cca50450ac58125ff3671/adeea331015c731a-2f/s540x810/1edeefe8fa4df4d6db16a729b47e7675cbe92d06.jpg" alt=""/></p>
<h2>Robert Smith and Lisp at Rigetti</h2>
<p>Robert gave an introduction to the math behind quantum computing, and
then described the success Rigetti has had with SBCL and Common Lisp
for building its <a href="https://github.com/rigetti/qvm/">quantum computing
simulator</a> and
<a href="https://github.com/rigetti/">compiler</a>. CL allows exploring and
adopting new ideas at a very quick pace. I liked that it wasn’t
high-level “Lisp is great!” preaching to the choir, but gave some
specific practical examples of how CL features made life easier.</p>
<h2>Charlie Zhang and RISC-V</h2>
<p>Charlie is a newcomer to SBCL development as of 2019. In the span of a
few months added a new compiler backend for fun. He talked about the
challenges of understanding and extending SBCL, and some of his future
plans.</p>
<p>He generated backend the assembly with the Lisp assembler - it gave
full advantages of Lisp for code manipulation at the assembly
level. First and only backend to do so!</p>
<p>Funniest fact I overheard at dinner after the workshop: “I don’t even
use Common Lisp for anything, I just hack on the compiler!”</p>
<p><img src="https://64.media.tumblr.com/f5c44986df592cd94d8d18448bb3e2c5/adeea331015c731a-d7/s540x810/ca9ceecb4ed330335baa2fbd81201fead3d13ea4.jpg" alt=""/></p>
<h2>Doug Katzman and SBCL as a Unix program</h2>
<p>Doug Katzman talked about his recent work at Google aimed at making
SBCL play well with Unix tools. Specifically debugging and profiling
tools that expect a binary to act in a certain way and to provide
debugging and stack info in a specific format. This makes it easier to
provide insight into how SBCL is spending its time when there are
many, many instances running across many, many computers. And with so
many instances running, the benefits of improving performance add up
in significant ways.</p>
<p>This use case is far removed from my typical live, ongoing,
interactive development session with SBCL. It was interesting to learn
about the constraints and requirements of Lisp servers in that kind of
environment.</p>
<p><img src="https://64.media.tumblr.com/21693299a649bbd884b4a8297d2b3ad3/adeea331015c731a-8c/s540x810/f0120ba192277970e9c1d9efa177a0e0c1bf8ca0.jpg" alt=""/></p>
<h2>Other talks</h2>
<p><img src="https://64.media.tumblr.com/16c6daae6a911c72efca12ac824887f3/adeea331015c731a-dd/s540x810/147393d8085972813eb1886dadc75e0f1b6ccae8.jpg" alt=""/></p>
<p>There were a dozen or more short presentations and talks about various
topics. <a href="http://kvardek-du.kerno.org">Luís</a> talked about porting an
application to SBCL from another Lisp and some of the good and bad
parts along the way. Charlie talked about <a href="https://www.cs.rit.edu/~mtf/research/contification/">contification
optimization</a> for
SBCL. There were quick talks about tuning the GC, <a href="https://github.com/marcoheisig/sb-simd">SIMD extensions</a>,
missing features of SBCL,
<a href="https://github.com/stylewarning/coalton">Coalton</a>, CL support in
<a href="http://swig.org">SWIG</a>, and several more.</p>
<h2>Bits and pieces</h2>
<ul>
<li>There are more commits to SBCL now than ever before, despite there
being fewer people contributing overall</li>
<li>It would nice to have support for good CL interaction in popular new
editors, but some of the existing components
(e.g. <a href="https://langserver.org">LSP</a>) are insufficient to support
SLIME-like levels of interaction</li>
<li><a href="https://www.siscog.pt/">Siscog</a> has more than 60 people who work on
Lisp programs - biggest collection in the world?</li>
</ul>
<p><img src="https://64.media.tumblr.com/d9ab8fd9eba6c9724e0895c6b1ea52e3/adeea331015c731a-db/s540x810/63b4886416989f7fdec0a07209c32bffcad4f802.jpg" alt=""/></p>
<h2>Closing wishlist items</h2>
<p>Christophe solicited wishlist items to close out the conference. Here
are a few that I jotted down:</p>
<ul>
<li>Debug-oriented interpeter, e.g. with macroexpand-always behavior
(the current interpreters do not especially improve the debug
experience)</li>
<li>Profile-based compilation feedback (sort of like tracing jit but not
exactly?)</li>
<li>Class sealing</li>
<li>Full configurable numeric tower</li>
<li>Arbitrary-precision floats</li>
<li>Concurrent GC - GC pauses cited by more than one person as a pain
point</li>
</ul>
<h2>Overall</h2>
<p>I had a great time at SBCL20 and it renewed my energy for working on
Common Lisp projects. It’s great to see in person the people you are
helping when you create or contribute to a community project.</p>
<p>Thanks to everyone who attended and spoke, to Philipp Marek for
hosting, and to Christophe Rhodes for acting as MC and much more.</p>
<p>It’s too long to wait for SBCL30. How about an SBCL25, or even sooner?</p>
<p>See you there!</p>
<p><img src="https://64.media.tumblr.com/447dbe33043542232e914436cc15c5c1/adeea331015c731a-17/s540x810/176d3c9d0f997310840115ee773c75d4b55703e7.jpg" alt=""/></p>https://lispblog.xach.com/post/189764932688https://lispblog.xach.com/post/189764932688Thu, 19 Dec 2019 19:09:38 -0500Exclusive file open<p>The Planet Lisp twitter fix involved tracking post status with a
file. Although it’s not 100% bulletproof, there’s a trick when using
files to reduce races.</p>
<p>Here’s a naive approach:</p>
<ol>
<li>Assign a Planet Lisp post a unique pathname</li>
<li>If that pathname exists, do nothing</li>
<li>Otherwise, send a tweet for the post and save its details to the
pathname</li>
</ol>
<p>The problem is between 2 and 3 - another process could post the tweet
first.</p>
<p>There’s another option:</p>
<ol>
<li>Assign a Planet Lisp post a unique pathname</li>
<li>Attempt to <a href="https://linux.die.net/man/3/open">open</a> the file with
<code>O_EXCL|O_CREAT</code> mode</li>
<li>If the attempt succeeds, send a tweet for the post and save its
details to the pathname</li>
</ol>
<p>The key bit is <code>O_EXCL|O_CREAT</code> mode, a Unix option that means <code>open</code>
will fail if the file exists, and succeed atomically
otherwise. Specifically:</p>
<blockquote>
<p>The check for the existence of the file and the creation of the file
if it does not exist shall be atomic with respect to other threads
executing open() naming the same filename in the same directory with
O_EXCL and O_CREAT set.</p>
</blockquote>
<p>In SBCL, <a href="https://github.com/sbcl/sbcl/blob/master/src/code/fd-stream.lisp#L2423">you can
get</a>
<code>O_EXCL|O_CREAT</code> semantics by specifing <code>:direction :output</code> and
<code>NIL</code>, <code>:error</code>, or <code>:new-version</code> as the <code>:if-exists</code> argument to
<a href="http://l1sp.org/cl/open">CL:OPEN</a>. For <code>NIL</code>, you can check to see if
the returned value is NIL, instead of a stream, to know if you have
successfully exclusively opened the file and can proceed. I <a href="https://github.com/xach/planetfeed/blob/ae06d0d8946c18cea95dda4f2523724f81761b75/planetfeed.lisp#L105">used the
NIL
approach</a>
in the Planet Lisp twitter gateway.</p>https://lispblog.xach.com/post/189664324263https://lispblog.xach.com/post/189664324263Sat, 14 Dec 2019 08:18:39 -0500Planet Lisp is back on Twitter<p>I brought the <a href="https://twitter.com/planet_lisp">@planet_lisp</a> Twitter
account back to life after more than a year of dormancy. It updates
twitter with every item on Planet Lisp.</p>
<p>It broke a while back because of how I used Twitter itself to keep
track of what had been posted. I <a href="https://github.com/xach/planetfeed/commit/ae06d0d8946c18cea95dda4f2523724f81761b75">updated it to use a local data
directory</a>
instead. It’s working well so far.</p>https://lispblog.xach.com/post/189657372493https://lispblog.xach.com/post/189657372493Fri, 13 Dec 2019 21:59:25 -0500Working with letsencrypt’s certbot for a Lisp webserver<p>Every 90 days my <a href="https://letsencrypt.org">letsencrypt</a> certificate
expires and I renew it manually. I have to cut and paste data from the
certbot script into repl forms to serve the right data on the right
path and it’s such a pain that sometimes I put it off until after it
expires, and people email me about it, and I feel bad.</p>
<p>The manual process looks something like this (not my actual domain or
challenges):</p>
<pre><code># certbot certonly --manual -d my.example.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Cert is due for renewal, auto-renewing...
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for my.example.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you're running certbot in manual mode on a machine that is not
your server, please ensure you're okay with that.
Are you OK with your IP being logged?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Create a file containing just this data:
uaut.gj61B3f7oYQcWZSF4kxS4OFh8KQlsDVtPXrw60Tkj2JLW7RtZaVE0MIWwiEKRlxph7SaLwp1ETFjaGDUKN
And make it available on your web server at this URL:
<a href="http://my.example.com/.well-known/acme-challenge/SpZa7sf4QMEFoF7lKh7aT4EZjNWSVcur2jODPQkgExa">http://my.example.com/.well-known/acme-challenge/SpZa7sf4QMEFoF7lKh7aT4EZjNWSVcur2jODPQkgExa</a>
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
</code></pre>
<p>There’s no way that letsencrypt’s certbot program will automatically
get support for my custom hunchentoot “framework” and I don’t really
want to look into adding it myself.</p>
<p>For a while I thought about writing some
<a href="https://en.wikipedia.org/wiki/Expect">Expect</a> functionality in SBCL -
<code>sb-ext:run-program</code> already supports a <code>:pty</code> option so it wouldn’t
be super-difficult. With a theoretical cl-expect you could spawn
certbot with the right options, slurp out the verification secret and
URL via the process’s standard output stream, and call whatever code
you need to serve the secret at that location.</p>
<p>I realized today there’s a halfway solution that takes the worst
cutting and pasting out of the loop. The unix command <a href="http://man7.org/linux/man-pages/man1/script.1.html">script
–flush</a> starts an
interactive session where all input and output is saved to a file. My
Lisp webserver can then read certbot program output from that file and
configure the webserver automagically for me. I still have to manually
start certbot and enter a few REPL commands, but it’s easier than
before.</p>
<p>Here’s the core of Lisp side of things for processing the <code>script</code>
file:</p>
<pre><code>(defun scrape-letsencrypt-interaction (file)
(let (secret path)
(with-open-file (stream file)
(labels (...)
(loop
(skip-past "Create a file containing")
(next-line)
(setf secret (read-trimmed-line))
(skip-past "make it available")
(next-line)
(setf path (substring-after ".well-known" (read-trimmed-line))))))))
</code></pre>
<p>This could be done just as well (perhaps with
<a href="http://edicl.github.io/cl-ppcre/">cl-ppcre</a>, but I didn’t want to
pull it in as dependency.</p>
<p>Here are the functions from <code>labels</code>:</p>
<pre><code>((next-line ()
(let ((line (read-line stream nil)))
(when (null line)
(unless (and secret path)
(error "Didn't find a secret and path anywhere in ~S"
file))
(return-from scrape-letsencrypt-interaction
(values secret path)))
line))
(skip-past (string)
(loop
(let ((line (next-line)))
(when (search string line)
(return)))))
(read-trimmed-line ()
(string-trim '(#\Return)
(next-line)))
(substring-after (string target)
(let ((pos (search string target)))
(unless pos
(error "Could not find ~S in ~S" string target))
(subseq target pos))))
</code></pre>
<p>The goal here is to only look at the last secret and URL in the script
output, so the main loop keeps track of what it’s seen so far and
<code>next-line</code> returns those values at EOF. The output also has ugly
trailing <code>^M</code> noise so <code>read-trimmed-line</code> takes care of that.</p>
<p>Here’s the whole thing all together:</p>
<pre><code>(defun scrape-letsencrypt-interaction (file)
(let (secret path)
(with-open-file (stream file)
(labels ((next-line ()
(let ((line (read-line stream nil)))
(when (null line)
(unless (and secret path)
(error "Didn't find a secret and path anywhere in ~S"
file))
(return-from scrape-letsencrypt-interaction
(values secret path)))
line))
(skip-past (string)
(loop
(let ((line (next-line)))
(when (search string line)
(return)))))
(read-trimmed-line ()
(string-trim '(#\Return)
(next-line)))
(substring-after (string target)
(let ((pos (search string target)))
(unless pos
(error "Could not find ~S in ~S" string target))
(subseq target pos))))
(loop
(skip-past "Create a file containing")
(next-line)
(setf secret (read-trimmed-line))
(skip-past "make it available")
(next-line)
(setf path (substring-after ".well-known" (read-trimmed-line))))))))
</code></pre>
<p>I don’t mind shaving only half a yak when it feels like useful
progress!</p>
<p>Someday I’ll get around to a proper Expect-like thing…</p>https://lispblog.xach.com/post/189499356038https://lispblog.xach.com/post/189499356038Thu, 05 Dec 2019 18:35:55 -0500lispGeneric vs. plain functions<p>I really like this comment from Stas Boukarev on <a href="https://www.reddit.com/r/lisp/comments/ctfk6d/methods_or_functions_when_do_i_use_which/">Methods or Functions, when do I use which</a> on reddit:</p>
<blockquote>
<p>[You] don’t make an extensible program by just making each function generic, if each function still makes some assumption on the data. You can’t say “oh, it’s extensible, but you have to define a hundred methods of your own”, an extensible protocol will require defining a handful of pertinent methods and then the hundred of other functions will automatically work on new classes.</p>
</blockquote>https://lispblog.xach.com/post/187188131688https://lispblog.xach.com/post/187188131688Thu, 22 Aug 2019 09:28:15 -0400Want to write Common Lisp for RavenPack? | R. Matthew Emerson<a href="http://www.thoughtstuff.com/rme/weblog/?p=35">Want to write Common Lisp for RavenPack? | R. Matthew Emerson</a>https://lispblog.xach.com/post/182034968033https://lispblog.xach.com/post/182034968033Tue, 15 Jan 2019 12:31:31 -0500Converter of maps from Reflex Arena to QuakeWorld<a href="https://fourier.github.io/lisp/2019/01/02/reflex-map.html">Converter of maps from Reflex Arena to QuakeWorld</a>: <p>Via dzecniv on reddit.</p>https://lispblog.xach.com/post/181822116328https://lispblog.xach.com/post/181822116328Mon, 07 Jan 2019 20:09:37 -0500ASCII Art Animations in Lisp<a href="https://terranostra.one/posts/ASCII-Art-Animations-in-Lisp.html">ASCII Art Animations in Lisp</a>https://lispblog.xach.com/post/181811483108https://lispblog.xach.com/post/181811483108Mon, 07 Jan 2019 13:18:30 -0500Writing a natural language date and time parser<a href="https://lisper.in/nlp-date-parser">Writing a natural language date and time parser</a>: <p>Via reddit.</p>https://lispblog.xach.com/post/181614264543https://lispblog.xach.com/post/181614264543Tue, 01 Jan 2019 11:06:45 -0500Personal Notes on Corman Lisp 3.1 Release<a href="https://chaoticlab.io/lisp/update/2018/12/30/corman-3-1-release.html">Personal Notes on Corman Lisp 3.1 Release</a>https://lispblog.xach.com/post/181553197083https://lispblog.xach.com/post/181553197083Sun, 30 Dec 2018 11:28:07 -0500A Road to Common Lisp - Steve Losh<a href="http://stevelosh.com/blog/2018/08/a-road-to-common-lisp/">A Road to Common Lisp - Steve Losh</a>https://lispblog.xach.com/post/177451719963https://lispblog.xach.com/post/177451719963Mon, 27 Aug 2018 12:47:18 -0400Thoughts on ELS 2018<p>Matt Emerson opened the conference keynote talk on Clozure CL. He also touched on using and celebrating CL. It provided a jolt of enthusiasm and positivity to kick off a fun conference. And it made me want to use Clozure CL more often and learn how to effectively hack on and with it.</p><p>Nicolas Hafner’s talk on shaders was interesting, but partway through the talk he revealed that the slideshow system itself was an interactive Common Lisp program. Along with standard slideshow behavior, it displayed and animated the classic teapot, with interactive recompilation and redisplay of the shaders.</p><p>Ethan Schwartz’s talk on Google’s tweaks to SBCL’s GC was a reminder that you don’t have to settle for the system-provided customization knobs. When source is available and you’re willing to customize very specifically for your application’s workload, you can get nice improvements.</p><p>(Also his passing mention of Docker inspired me to work on a Docker image with all the Quicklisp-required foreign libraries baked into it. I think it will be helpful to me for easier testing, and maybe distributed builds. It should be helpful to others for testing everything in Quicklisp without the pain of gathering all the build requirements for its many projects.)</p><p>You should check out Douglas Katzman’s lightning talk, “Self-modifying code (for fun and profit)”. He’s added a neat thing in SBCL where the system can be disassembled completely and reassembled into a new binary with various bits of optimization or instrumentation. <br/></p><p>There were many other great talks and discussions!</p><p>It’s rejuvenating to hear about all the cool things people are working on. There’s stuff people are making that you might make use of in your own projects, or inspiration to hack your own things to share with others.</p><p>Also: great weather, great city, fun excursion to Ronda, seeing old friends from past conferences, meeting new friends, putting online names to real-life faces, hearing directly from people who use Quicklisp. And Dmitri Fontaine told me about <a href="https://tic.computer" style="font-size: 14px;">tic80</a>, which my kid and I used to make a retro game in just a few days.<br/></p><p>Next ELS conference is in Genova, Italy on April 1, 2019. Start planning today, and I’ll see you there!</p>https://lispblog.xach.com/post/173467550358https://lispblog.xach.com/post/173467550358Mon, 30 Apr 2018 21:55:53 -0400Paradigms of AI Programming is now available as a free PDF<p>Peter Norvig has published <a href="https://github.com/norvig/paip-lisp">Paradigms of AI Programming on github</a>. There are PDFs of the entire book along with a plain-text version and separate files with the code.</p>
<p>I’m not exactly sure how this came about (Robert Smith <a href="https://twitter.com/stylewarning/status/968312810483613697">hints at it on twitter</a>) but it’s a fantastic development. I recommend Paradigms of AI Programming to anyone who wants to learn Common Lisp, and having it freely available will help a great many people.</p>
<p>I avoided this book for a while because I had little interest in AI. But PAIP isn’t really about AI. The book is about programming effectively, with Common Lisp as the language and classical AI problems as the context. The tools and techniques you take away from careful study are applicable in many, many situations.</p>https://lispblog.xach.com/post/171379263493https://lispblog.xach.com/post/171379263493Wed, 28 Feb 2018 09:15:49 -0500