Update clones

This commit is contained in:
Marcus Kammer 2022-08-04 11:37:48 +02:00
parent 77fe2d5efb
commit 62f229e4d1
44 changed files with 2046 additions and 1804 deletions

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"../assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"../assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=
@ -68,7 +70,7 @@ in other languages, and can do more.</p>
<blockquote>
<p>Just like in languages that support exception handling (Java, C++,
Python, etc.), a condition represents, for the most part, an
“exceptional” situation. However, even more so that those languages,
“exceptional” situation. However, even more so than those languages,
<em>a condition in Common Lisp can represent a general situation where
some branching in program logic needs to take place</em>, not
necessarily due to some error condition. Due to the highly

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=
@ -82,6 +84,34 @@ In a recipe or two we also use
<li><a href="http://gigamonkeys.com/book/files-and-file-io.html">Files and File I/O in Practical Common Lisp</a></li>
</ul>
<h3 id="getting-the-components-of-a-pathname">Getting the components of a pathname</h3>
<h4 id="file-extension">File extension</h4>
<p>The file extension is called “pathname type” in Lisp parlance:</p>
<pre><code class="language-lisp">(pathname-type "~/foo.org") ;; =&gt; "org"
</code></pre>
<h4 id="file-basename">File basename</h4>
<p>The basename is called the “name” -</p>
<pre><code class="language-lisp">(pathname-name "~/foo.org") ;; =&gt; "foo"
(pathname-name "~/foo") ;; =&gt; "foo"
</code></pre>
<p>If a directory pathname has a trailing slash, <code>pathname-name</code> may return <code>nil</code>; use <code>pathname-directory</code> instead -</p>
<pre><code class="language-lisp">(pathname-name "~/foo/") ;; =&gt; NIL
(first (last (pathname-directory #P"~/foo/"))) ;; =&gt; "foo"
</code></pre>
<h4 id="parent-directory">Parent directory</h4>
<pre><code class="language-lisp">(uiop:pathname-parent-directory-pathname #P"/foo/bar/quux/") ;; =&gt; #P"/foo/bar/"
</code></pre>
<h3 id="testing-whether-a-file-exists">Testing whether a file exists</h3>
<p>Use the function
@ -211,6 +241,16 @@ is somewhere on your filesystem and you want the path to <code>src/web/</code>.
<p>This will work on another users machine, where the system sources are located in another location.</p>
<h3 id="setting-the-current-working-directory">Setting the current working directory</h3>
<p>Use <a href="https://asdf.common-lisp.dev/uiop.html#Function-uiop_002fos_003achdir"><code>uiop:chdir</code></a> <em><code>path</code></em>:</p>
<pre><code class="language-lisp">(uiop:chdir "/bin/")
0
</code></pre>
<p>The trailing slash in <em>path</em> is optional.</p>
<h3 id="opening-a-file">Opening a file</h3>
<p>Common Lisp has
@ -518,13 +558,6 @@ has a function called <a href="https://gitlab.common-lisp.net/alexandria/alexand
<p>Both <code>alexandria:write-string-into-file</code> and <code>str:to-file</code> take the same keyword arguments as <code>cl:open</code> that controls file creation: <code>:if-exists</code> and <code>if-does-not-exists</code>.</p>
<h3 id="getting-the-file-extension">Getting the file extension</h3>
<p>The file extension is a pathname type in Lisp parlance:</p>
<pre><code class="language-lisp">(pathname-type "~/foo.org") ;; =&gt; "org"
</code></pre>
<h3 id="getting-file-attributes-size-access-time">Getting file attributes (size, access time,…)</h3>
<p><a href="https://www.common-lisp.net/project/osicat/">Osicat</a> (in Quicklisp)

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=
@ -85,13 +87,16 @@ a book containing recipes and other information about the preparation and cookin
</li>
<li><a href="functions.html">Functions</a></li>
<li><a href="data-structures.html">Data Structures</a></li>
<li><a href="strings.html">Strings</a></li>
<li><a href="strings.html">Strings</a>
<ul>
<li><a href="regexp.html">Regular Expressions</a></li>
</ul>
</li>
<li><a href="numbers.html">Numbers</a></li>
<li><a href="iteration.html">Loops, iteration, mapping</a></li>
<li><a href="arrays.html">Multidimensional Arrays</a></li>
<li><a href="dates_and_times.html">Dates and Times</a></li>
<li><a href="pattern_matching.html">Pattern Matching</a></li>
<li><a href="regexp.html">Regular Expressions</a></li>
<li><a href="io.html">Input/Output</a></li>
<li><a href="files.html">Files and Directories</a></li>
<li><a href="error_handling.html">Error and condition handling</a></li>

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=
@ -560,7 +562,7 @@ of warnings and errors during development.</p>
<h2 id="using-lispworks-from-emacs-and-slime">Using LispWorks from Emacs and Slime</h2>
<p>To do that, start LispWorks normally, start a Swank server and connect to it from Emacs (Swank is the backend part of Slime).</p>
<p>To do that, you have two possibilities. The first one is to start LispWorks normally, start a Swank server and connect to it from Emacs (Swank is the backend part of Slime).</p>
<p>First, lets load the dependencies:</p>
@ -586,6 +588,27 @@ of warnings and errors during development.</p>
(capi:contain button)
</code></pre>
<p>The second possibility is to create a non-GUI LispWorks image, with
Swank loaded, and to run this image from SLIME or SLY. For example, to
create a so-called <code>console</code> image with multiprocessing enabled:</p>
<pre><code class="language-lisp">(in-package "CL-USER")
(load-all-patches)
(save-image "~/lw-console"
:console t
:multiprocessing t
:environment nil)
</code></pre>
<p>and run LispWorks like this to create the new image ~/lw-console:</p>
<pre><code>lispworks-7-0-0-x86-linux -build /tmp/resave.lisp
</code></pre>
<p>However: <code>console</code> is implemented <strong>only for Windows and Mac</strong>.</p>
<p>See LispWorks documentation.</p>
<h2 id="see-also">See also</h2>
<ul>

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=
@ -396,7 +398,7 @@ output to be shown on the main console screen.</p>
(bt:make-thread
(lambda ()
(format top-level "Hello from thread!"))
:name "hello")))
:name "hello"))
nil)
</code></pre>

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=
@ -84,7 +86,7 @@ location information, and more.</p>
<p>How to build (self-contained) executables is, by default, implementation-specific (see
below for portable ways). With SBCL, as says
<a href="http://www.sbcl.org/manual/index.html#Function-sb_002dext_003asave_002dlisp_002dand_002ddie">its documentation</a>,
it is a matter of calling <code>save-lisp-and-die</code> with the <code>executable</code> argument to T:</p>
it is a matter of calling <code>save-lisp-and-die</code> with the <code>:executable</code> argument to T:</p>
<pre><code class="language-lisp">(sb-ext:save-lisp-and-die #P"path/name-of-executable" :toplevel #'my-app:main-function :executable t)
</code></pre>
@ -107,21 +109,21 @@ In that case, we re-use the image with <code>sbcl --core name-of-image</code>.</
<p>Cannot save core with multiple threads running.</p>
</blockquote>
<p>So we must run the command from a simple SBCL repl.</p>
<p>We must run the command from a simple SBCL repl, from the terminal.</p>
<p>I suppose your project has Quicklisp dependencies. You must then:</p>
<ul>
<li>ensure Quicklisp is installed and loaded at the Lisp startup (you
completed Quicklisp installation),</li>
<li><code>load</code> the projects .asd,</li>
<li><code>asdf:load-asd</code> the projects .asd (recommended instead of just <code>load</code>),</li>
<li>install the dependencies,</li>
<li>build the executable.</li>
</ul>
<p>That gives:</p>
<pre><code class="language-lisp">(load "my-app.asd")
<pre><code class="language-lisp">(asdf:load-asd "my-app.asd")
(ql:quickload "my-app")
(sb-ext:save-lisp-and-die #p"my-app-binary" :toplevel #'my-app:main :executable t)
</code></pre>
@ -141,7 +143,7 @@ version 3.1, ASDF allows to do that. It introduces the <a href="https://common-l
that reads parameters from the .asd. Add this to your .asd declaration:</p>
<pre><code>:build-operation "program-op" ;; leave as is
:build-pathname "&lt;binary-name&gt;"
:build-pathname "&lt;here your final binary name&gt;"
:entry-point "&lt;my-package:main-function&gt;"
</code></pre>
@ -158,6 +160,82 @@ build:
--eval '(quit)'
</code></pre>
<h3 id="with-deploy---ship-foreign-libraries-dependencies">With Deploy - ship foreign libraries dependencies</h3>
<p>All this is good, you can create binaries that work on your machine…
but maybe not on someone elses or on your server. Your program
probably relies on C shared libraries that are defined somewhere on
your filesystem. For example, <code>libssl</code> might be located on</p>
<pre><code>/usr/lib/x86_64-linux-gnu/libssl.so.1.1
</code></pre>
<p>but on your VPS, maybe somewhere else.</p>
<p><a href="https://github.com/Shinmera/deploy">Deploy</a> to the rescue.</p>
<p>It will create a <code>bin/</code> directory with your binary and the required
foreign libraries. It will auto-discover the ones your program needs,
but you can also help it (or tell it to not do so much).</p>
<p>Its use is very close to the above recipe with <code>asdf:make</code> and the
<code>.asd</code> project configuration. Use this:</p>
<pre><code class="language-lisp">:defsystem-depends-on (:deploy) ;; (ql:quickload "deploy") before
:build-operation "deploy-op" ;; instead of "program-op"
:build-pathname "my-application-name" ;; doesn't change
:entry-point "my-package:my-start-function" ;; doesn't change
</code></pre>
<p>and build your binary with <code>(asdf:make :my-app)</code> like before.</p>
<p>Now, ship the <code>bin/</code> directory to your users.</p>
<p>When you run the binary, youll see it uses the shipped libraries:</p>
<pre><code class="language-lisp">$ ./my-app
==&gt; Performing warm boot.
-&gt; Runtime directory is /home/debian/projects/my-app/bin/
-&gt; Resource directory is /home/debian/projects/my-app/bin/
==&gt; Running boot hooks.
==&gt; Reloading foreign libraries.
-&gt; Loading foreign library #&lt;LIBRARY LIBRT&gt;.
-&gt; Loading foreign library #&lt;LIBRARY LIBMAGIC&gt;.
==&gt; Launching application.
[…]
</code></pre>
<p>Success!</p>
<p>A note regarding <code>libssl</code>. Its easier, on Linux at least, to
rely on your OS current installation, so well tell Deploy to not
bother shipping it (nor <code>libcrypto</code>):</p>
<pre><code class="language-lisp">#+linux (deploy:define-library cl+ssl::libssl :dont-deploy T)
#+linux (deploy:define-library cl+ssl::libcrypto :dont-deploy T)
</code></pre>
<p>The day you want to ship a foreign library that Deploy doesnt find, you can instruct it like this:</p>
<pre><code class="language-lisp">(deploy:define-library cl+ssl::libcrypto
;; ^^^ CFFI system name. Find it with a call to "apropos".
:path "/usr/lib/x86_64-linux-gnu/libcrypto.so.1.1")
</code></pre>
<p>A last remark. Once you built your binary and you run it for the first
time, you might get a funny message from ASDF that tries to upgrade
itself, finds nothing into a <code>~/common-lisp/asdf/</code> repository, and
quits. To tell it to not upgrade itself, add this into your .asd:</p>
<pre><code class="language-lisp">;; Tell ASDF to not update itself.
(deploy:define-hook (:deploy asdf) (directory)
(declare (ignorable directory))
#+asdf (asdf:clear-source-registry)
#+asdf (defun asdf:upgrade-asdf () nil))
</code></pre>
<p>But there is more, so we refer you to Deploys documentation.</p>
<h3 id="with-roswell-or-buildapp">With Roswell or Buildapp</h3>
<p><a href="https://roswell.github.io">Roswell</a>, an implementation manager, script launcher and
@ -270,9 +348,13 @@ ECL is more involved and takes the longer to compile of these three implementati
<h3 id="building-a-smaller-binary-with-sbcls-core-compression">Building a smaller binary with SBCLs core compression</h3>
<p>Building with SBCLs core compression can dramatically reduce your
application binarys size. In our case, we passed from 120MB to 23MB,
application binarys size. In our case, it reduced it from 120MB to 23MB,
for a loss of a dozen milliseconds of start-up time, which was still
under 50ms!</p>
under 50ms.</p>
<div class="info-box info">
<strong>Note:</strong> SBCL 2.2.6 switched to compression with zstd instead of zlib, which provides smaller binaries and faster compression and decompression times. Un-official numbers are: about 4x faster compression, 2x faster decompression, and smaller binaries by 10%.
</div>
<p>Your SBCL must be built with core compression, see the documentation: <a href="http://www.sbcl.org/manual/#Saving-a-Core-Image">http://www.sbcl.org/manual/#Saving-a-Core-Image</a></p>

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=
@ -440,7 +442,7 @@ either with a simple <code>C-c C-c</code> in Slime, or when we <code>load</code>
<p>A class slot accepts a <code>:type</code> slot option. It is however generally
<em>not</em> used to check the type of the initform. SBCL, starting with
<a href="http://www.sbcl.org/news.html#1.5.9">version 1.5.9</a> released on
<a href="http://www.sbcl.org/all-news.html#1.5.9">version 1.5.9</a> released on
november 2019, now gives those warnings, meaning that this:</p>
<pre><code class="language-lisp">(defclass foo ()

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=
@ -347,9 +349,12 @@ parameter:</p>
handling extension on top of Hunchentoot. It provides:</p>
<ul>
<li>dispatch based on HTTP method (otherwise cumbersome in Hunchentoot)</li>
<li>arguments extraction from the url path</li>
<li>and decorators.</li>
<li><strong>dispatch</strong> based on the HTTP method, such as GET or POST (which is otherwise cumbersome to do in Hunchentoot)</li>
<li><strong>arguments extraction</strong> from the url path</li>
<li><strong>decorators</strong> (functions to run before the route body, typically used to add a layer of authentication or changing the returned content type)</li>
<li><strong>URL generation</strong> from route names and given URL parameters</li>
<li>visualization of routes</li>
<li>and more</li>
</ul>
<p>To use it, dont create a server with <code>hunchentoot:easy-acceptor</code> but
@ -365,7 +370,7 @@ serve static content the usual way with Hunchentoot.</p>
<p>Then define a route like this:</p>
<pre><code class="language-lisp">(easy-routes:defroute name ("/foo/:x" :method :get) (y &amp;get z)
<pre><code class="language-lisp">(easy-routes:defroute my-route-name ("/foo/:x" :method :get) (y &amp;get z)
(format nil "x: ~a y: ~a z: ~a" x y z))
</code></pre>
@ -377,6 +382,18 @@ body.</p>
<p>These parameters can take an <code>:init-form</code> and <code>:parameter-type</code>
options as in <code>define-easy-handler</code>.</p>
<p>Now, imagine that we are deeper in our web application logic, and we
want to redirect our user to the route “/foo/3”. Instead of hardcoding
the URL, we can <strong>generate the URL from its name</strong>. Use
<code>easy-routes:genurl</code> like this:</p>
<pre><code class="language-lisp">(easy-routes:genurl my-route-name :id 3)
;; =&gt; /foo/3
(easy-routes:genurl my-route-name :id 3 :y "yay")
;; =&gt; /foo/3?y=yay
</code></pre>
<p><strong>Decorators</strong> are functions that are executed before the route body. They
should call the <code>next</code> parameter function to continue executing the
decoration chain and the route body finally. Examples:</p>
@ -973,7 +990,7 @@ Listening on localhost:9003.
<p>We can start our executable in a shell and send it to the background (<code>C-z bg</code>), or run it inside a <code>tmux</code> session. These are not the best but hey, it works©.</p>
<h3 id="daemonizing-restarting-in-case-of-crashes-handling-logs-with-systemd">Daemonizing, restarting in case of crashes, handling logs with Systemd</h3>
<h3 id="systemd-daemonizing-restarting-in-case-of-crashes-handling-logs">Systemd: Daemonizing, restarting in case of crashes, handling logs</h3>
<p>This is actually a system-specific task. See how to do that on your system.</p>
@ -981,47 +998,59 @@ Listening on localhost:9003.
<p>Deploying an app with Systemd is as simple as writing a configuration file:</p>
<pre><code>$ emacs -nw /etc/systemd/system/my-app.service
<pre><code>$ sudo emacs -nw /etc/systemd/system/my-app.service
[Unit]
Description=stupid simple example
Description=your lisp app on systemd example
[Service]
WorkingDirectory=/path/to/your/app
ExecStart=/usr/local/bin/sthg sthg
WorkingDirectory=/path/to/your/project/directory/
ExecStart=/usr/bin/make run # or anything
Type=simple
Restart=on-failure
[Install]
WantedBy=network.target
</code></pre>
<p>Then we have a command to start it:</p>
<p>Then we have a command to <code>start</code> it, only now:</p>
<pre><code>sudo systemctl start my-app.service
</code></pre>
<p>a command to check its status:</p>
<p>and a command to install the service, to <strong>start the app after a boot
or reboot</strong> (thats the “[Install]” part):</p>
<pre><code>sudo systemctl enable my-app.service
</code></pre>
<p>Then we can check its <code>status</code>:</p>
<pre><code>systemctl status my-app.service
</code></pre>
<p>and Systemd can handle <strong>logging</strong> (we write to stdout or stderr, it writes logs):</p>
<p>and see our applications <strong>logs</strong> (we can write to stdout or stderr,
and Systemd handles the logging):</p>
<pre><code>journalctl -f -u my-app.service
<pre><code>journalctl -u my-app.service
</code></pre>
<p>and it handles crashes and <strong>restarts the app</strong>:</p>
<p>(you can also use the <code>-f</code> option to see log updates in real time, and in that case augment the number of lines with <code>-n 50</code> or <code>--lines</code>).</p>
<pre><code>Restart=on-failure
</code></pre>
<p>Systemd handles crashes and <strong>restarts the application</strong>. Thats the <code>Restart=on-failure</code> line.</p>
<p>and it can <strong>start the app after a reboot</strong>:</p>
<p>Now keep in mind a couple things:</p>
<pre><code>[Install]
WantedBy=basic.target
</code></pre>
<p>to enable it:</p>
<pre><code>sudo systemctl enable my-app.service
</code></pre>
<ul>
<li>we want our app to crash so that it can be re-started automatically:
youll want the <code>--disable-debugger</code> flag with SBCL.</li>
<li>Systemd will, by default, run your app as root. If you rely on your
Lisp to read your startup file (<code>~/.sbclrc</code>), especially to setup
Quicklisp, you will need to use the <code>--userinit</code> flag, or to set the
Systemd user with <code>User=xyz</code> in the <code>[service]</code> section. And if you
use a startup file, be aware that the line <code>(user-homedir-pathname)</code>
will not return the same result depending on the user, so the snippet
might not find Quicklisps setup.lisp file.</li>
</ul>
<p>See more: <a href="https://www.freedesktop.org/software/systemd/man/systemd.service.html">https://www.freedesktop.org/software/systemd/man/systemd.service.html</a>.</p>

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=

View file

@ -8,6 +8,8 @@
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=