<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Antoine Kalmbach's website</title>
    <description>Antoine Kalmbach's website</description>
    <link>http://ane.iki.fi</link>
    <language>en-gb</language>
    <managingEditor>ane@iki.fi (Antoine Kalmbach)</managingEditor>
    <webMaster>ane@iki.fi (Antoine Kalmbach)</webMaster>
    <atom:link href="http://ane.iki.fi/feed.xml" rel="self" type="application/rss+xml" />
    
    
      <item>
        <title>Guile fun times, and blog update</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;Holy crap, &lt;a href=&quot;/2015/12/07/start-once-software.html&quot;&gt;it’s been five years&lt;/a&gt;! Time passes so quickly. What can happen in five years? Well, during these
five years I met my wife, we moved not three but four times, we bought our own
apartment, our daughter was born… many things indeed! Here’s to hoping the
next five years will be as fun and exciting.&lt;/p&gt;

&lt;p&gt;On this site I’ve posted &lt;a href=&quot;/archive.html&quot;&gt;twenty something blog entries&lt;/a&gt; plus a
smattering of other writings. I’ve picked up the pace this year after having
a renewed interest for this site. It’s still running on Jekyll and hosted on
GitHub pages, so that hasn’t changed.&lt;/p&gt;

&lt;p&gt;I’m still working at the same place as before, though I’ve changed roles and
responsibilities some four to five times. I have not had the chance to become
bored, so that’s nice.&lt;/p&gt;

&lt;p&gt;Lately I’ve been playing around with &lt;a href=&quot;https://www.gnu.org/software/recutils/&quot;&gt;GNU
Recutils&lt;/a&gt; and became maintainer of it’s
Emacs major mode &lt;a href=&quot;https://elpa.gnu.org/packages/rec-mode.html&quot;&gt;rec-mode&lt;/a&gt;. In
passing I’ve also dabbled in writing &lt;a href=&quot;https://www.gnu.org/software/guile/&quot;&gt;Guile
Scheme&lt;/a&gt; bindings for librec, the library
powering recutils. &lt;a href=&quot;/programming/lisp/goops-virtual-slots-and-ffi.html&quot;&gt;Read more about this here&lt;/a&gt;!&lt;/p&gt;

        </description>
        <pubDate>Tue, 08 Dec 2020 13:36:12 +0000</pubDate>
        <link>http://ane.iki.fi/2020/12/08/five-years-of-blogging.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2020/12/08/five-years-of-blogging.html</guid>
      </item>
    
      <item>
        <title>Recutils, GOOPS and virtual slots</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;For the past month or so I’ve been contributing to &lt;a href=&quot;https://www.gnu.org/software/recutils/&quot;&gt;GNU
Recutils&lt;/a&gt;, a set of tools for editing
human-readable plain text databases. It’s a cool project in its own right, I’ve
been using recutils myself for tracking workouts and storing cooking
recipes. The cool part of it is its attempt to be both human-readable &lt;em&gt;and&lt;/em&gt;
machine-readable, which makes it very easy to use programmatically and then with
a simple text editor.&lt;/p&gt;

&lt;p&gt;The powerful &lt;a href=&quot;https://www.gnu.org/software/recutils/manual/Querying-Recfiles.html#Querying-Recfiles&quot;&gt;querying
facilities&lt;/a&gt;
of recutils is what turns it into a thing of beauty. In particular, &lt;a href=&quot;https://www.gnu.org/software/recutils/manual/Selecting-by-predicate.html#Selecting-by-predicate&quot;&gt;selection
expressions&lt;/a&gt;
are expressions for querying recfiles. For instance, here’s how I would query
exercises in my workout log for squats:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;recsel -t Exercise -e &quot;Name ~ 'Squat'&quot; workouts.rec
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This would match records of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Exercise&lt;/code&gt; where the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Name&lt;/code&gt; field matches
regular expressions, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Squat&lt;/code&gt; will match all exercise varieties with the word
&lt;em&gt;Squat&lt;/em&gt; in it.&lt;/p&gt;

&lt;p&gt;The machine readability makes it easy to write programs or tools that interact
with recfiles. I’ve become maintainer of the Emacs recfile major mode
&lt;a href=&quot;https://elpa.gnu.org/packages/rec-mode.html&quot;&gt;rec-mode&lt;/a&gt;. The major mode makes
heavy use of the command line tools of the recutils suite to do provide
automatic fixing and parsing of recfiles.&lt;/p&gt;

&lt;h3 id=&quot;if-its-possible-to-put-lisp-in-it-someone-will&quot;&gt;if it’s possible to put Lisp in it, someone will&lt;/h3&gt;

&lt;p&gt;For fun and profit, I’ve also been writing &lt;a href=&quot;https://www.gnu.org/software/guile/&quot;&gt;GNU
Guile&lt;/a&gt; bindings for librec, the library
powering recutils itself.  The bindings actually interface with the C library
directly using Guile’s amazing &lt;a href=&quot;https://www.gnu.org/software/guile/manual/html_node/C-Extensions.html&quot;&gt;C
extensions&lt;/a&gt;. I
was interested in using recfiles in a Guile program, and while it would not have
been too difficult to write a parser myself, I thought it was more important to
&lt;em&gt;not&lt;/em&gt; write one myself. What is more, Guile makes it almost too easy to wrap
libraries, I had a functioning Scheme interface for parsing records in less than
an hour.&lt;/p&gt;

&lt;p&gt;Let’s explore what that interface looks like. We start with the simplest data
type in librec, &lt;em&gt;fields&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A recutils record is defined as an ordered collection of fields. Below is a
record of three fields:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Book: Structure and Interpretation of Computer Programs
Author: Harold Abelson
Author: Gerald Sussman
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The inner field type of librec is defined as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rec_field_t&lt;/code&gt;, which is an opaque
data type wrapping &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rec_field_s&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;typedef&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rec_field_s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rec_field_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The underlying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rec_field_s&lt;/code&gt; structure is a bit more complicated since it
includes location data for the field, but for our example imagine it contains
just the fields &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt;, which are null-terminated strings. You don’t
need to know anything about that, since librec offers an extensive API for
working with the opaque types.&lt;/p&gt;

&lt;p&gt;To make a new field, you would write:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;rec_field_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rec_field_new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Author&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Harold Abelson&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To get the value and name, you use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rec_field_value&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rec_field_name&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;const&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;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rec_field_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* &quot;Author&quot; */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;const&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;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rec_field_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* &quot;Harold Abelson */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To modify its name or value, you can use:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;rec_field_set_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rec_field_set_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Structure and Interpretation of Computer Programs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;How do we wrap these into Guile, using C extensions? To start with, we can
simply make some Scheme methods that work with plain pointers and pass that
pointer value around.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;SCM_DEFINE&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_field_new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;new-field&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&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 class=&quot;mi&quot;&gt;0&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;n&quot;&gt;SCM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SCM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;Make a new field from a string and value.&quot;&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;n&quot;&gt;SCM_ASSERT_TYPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_is_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm_name&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;s&quot;&gt;&quot;new-field&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;SCM_ASSERT_TYPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_is_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;new-field&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;const&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;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm_to_utf8_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;const&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;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm_to_utf8_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;rec_field_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rec_field_new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&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;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SCM_BOOL_F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm_from_pointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destroy_field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This defines two functions: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;destroy_field&lt;/code&gt; for letting the garbage collector
get rid of unused fields, and then a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scm_field_new&lt;/code&gt; function defined using the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SCM_DEFINE&lt;/code&gt; macro. The procedure is straightforward: assert both parameters are
strings, convert to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const char*&lt;/code&gt;, create the field and return it if it was
successful, otherwise return Scheme false &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#f&lt;/code&gt;. The last bit creates a &lt;a href=&quot;https://www.gnu.org/software/guile/manual/html_node/Foreign-Variables.html&quot;&gt;pointer
object&lt;/a&gt;
to store the pointer address, and passes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;destroy_field&lt;/code&gt; as the finalizer
parameter for the garbage collector.&lt;/p&gt;

&lt;p&gt;In the Guile REPL, it looks like this:&lt;/p&gt;

&lt;div class=&quot;language-scheme highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recutils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new-field&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;foo&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bar&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;lt;pointer&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x7fc0654040f0&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;OK, it seems to be a pointer all right. Let’s define some helper methods to work
with that:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;SCM_DEFINE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_field_get_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;field-name&quot;&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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&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 class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SCM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
           &lt;span class=&quot;s&quot;&gt;&quot;Get the name of a field&quot;&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;n&quot;&gt;rec_field_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&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;n&quot;&gt;rec_field_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_to_pointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;const&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;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rec_field_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm_from_utf8_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&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;n&quot;&gt;SCM_DEFINE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_field_get_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;field-value&quot;&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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&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 class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SCM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
           &lt;span class=&quot;s&quot;&gt;&quot;Get the value of a field&quot;&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;n&quot;&gt;rec_field_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&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;n&quot;&gt;rec_field_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_to_pointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;const&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;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rec_field_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm_from_utf8_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Loading this extension into the REPL, we get&lt;/p&gt;

&lt;div class=&quot;language-scheme highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recutils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new-field&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;foo&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bar&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;lt;pointer&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x7fa123d0b980&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recutils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;field-name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;foo&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recutils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;field-value&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bar&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What about modifying the field? Well, that’s easy:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;SCM_DEFINE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_field_set_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;set-field-name!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&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 class=&quot;mi&quot;&gt;0&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;n&quot;&gt;SCM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SCM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
           &lt;span class=&quot;s&quot;&gt;&quot;Set the name of a field&quot;&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;n&quot;&gt;SCM_ASSERT_TYPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_is_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm_name&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;s&quot;&gt;&quot;set-field-name!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;rec_field_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&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;n&quot;&gt;rec_field_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_to_pointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;const&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;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm_to_utf8_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rec_field_set_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm_from_bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&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;n&quot;&gt;SCM_DEFINE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_field_set_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;set-field-value!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&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 class=&quot;mi&quot;&gt;0&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;n&quot;&gt;SCM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SCM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
           &lt;span class=&quot;s&quot;&gt;&quot;Set the value of a field&quot;&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;n&quot;&gt;SCM_ASSERT_TYPE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_is_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm_value&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;s&quot;&gt;&quot;set-field-value!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;rec_field_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&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;n&quot;&gt;rec_field_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_to_pointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;const&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;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm_to_utf8_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scm_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rec_field_set_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scm_from_bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Using all this in the REPL yields:&lt;/p&gt;

&lt;div class=&quot;language-scheme highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recutils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new-field&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;foo&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bar&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;lt;pointer&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x7ffcac406530&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recutils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;set-field-name!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Blah&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;#t&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recutils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;set-field-value!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Test&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;#t&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recutils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;field-name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$4&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Blah&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recutils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;field-value&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$5&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Test&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There we go!&lt;/p&gt;

&lt;h3 id=&quot;the-smell-of-raw-pointers&quot;&gt;the smell of raw pointers&lt;/h3&gt;

&lt;p&gt;OK, this looks great. But somehow it feels funny to pass a raw pointer object
around as a parameter. Ideally, I’d like to define some sort of structure that
wraps the raw pointer into something less &lt;em&gt;raw&lt;/em&gt;. Well, turns out Guile has
exactly that in the &lt;a href=&quot;https://www.gnu.org/software/guile/manual/html_node/Void-Pointers-and-Byte-Access.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;define-wrapped-pointer-type&lt;/code&gt;&lt;/a&gt; macro! With the above
constructor and procedures, we can go further:&lt;/p&gt;

&lt;div class=&quot;language-scheme highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;define-wrapped-pointer-type&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;field-ptr&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;field-ptr?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;wrap-field-ptr&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;unwrap-field-ptr&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ptr&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;port&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;nf&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;#&amp;lt;field-ptr name=~s value=~s 0x~x&amp;gt;&quot;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;field-name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unwrap-field-ptr&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ptr&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;nf&quot;&gt;field-value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unwrap-field-ptr&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ptr&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;nf&quot;&gt;pointer-address&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unwrap-field-ptr&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What the macro defines are a type name (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;field-ptr&lt;/code&gt;), a predicate
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;field-ptr?&lt;/code&gt;), methods for wrapping and unwrapping, and lastly a &lt;em&gt;printer&lt;/em&gt;
for pretty printing our pointer. The printer outputs a human readable
representation of the printer, in which we leverage the procedures defined
above, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;field-name&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;field-value&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-scheme highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recutils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;wrap-field-ptr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new-field&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Author&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Harold Abelson&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;lt;field-ptr&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Author&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Harold Abelson&quot;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x7f8a6950b2d0&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recutils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;field-ptr?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$3&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;#t&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;scheme@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recutils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unwrap-field-ptr&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$4&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;&amp;lt;pointer&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;x7f8a6950b2d0&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This makes it a bit easier to pass around field values so that we can treat them
like structures, or records in Scheme parlance. That said, constructing the
values is still a bit tedious, especially now that our Scheme user would have to
constantly wrap and unwrap values if they are to work with a field.&lt;/p&gt;

&lt;p&gt;What if we could work with fields as if they were pure Scheme objects and the
underlying machinery – pointers and so forth – would be hidden from us? Well,
we can use
&lt;a href=&quot;https://www.gnu.org/software/guile/manual/html_node/GOOPS.html&quot;&gt;GOOPS&lt;/a&gt;, but
first let’s digress into the exciting world of FFI.&lt;/p&gt;

&lt;h3 id=&quot;why-not-dynamic-ffi&quot;&gt;why not dynamic FFI?&lt;/h3&gt;

&lt;p&gt;These days the Guile manual recommends using &lt;a href=&quot;https://www.gnu.org/software/guile/manual/html_node/Dynamic-FFI.html&quot;&gt;Dynamic
FFI&lt;/a&gt; when
working with a foreign function interface. That is, the above examples are just
C code, but we could have done the same with just regular Scheme using the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(system foreign)&lt;/code&gt; module. This is what I would do in many other languages
(Common Lisp, Python, and so on…). In such a case, I could make my Scheme
module completely separate from recutils and librec, since I just need the
dynamic library &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libguile-recutils.so&lt;/code&gt; for it to functions. But there are subtle
reasons why writing these extensions in C is a good idea.&lt;/p&gt;

&lt;p&gt;As I went ahead and wrote the bindings, I had a curious thought: I’m writing
functionality for working with recfiles from Guile. But what about adding Guile
facilities to recutils? What about letting recutils users extend the programs
using Scheme? Wouldn’t it be cool if instead of recutils selection expressions
I could pass Scheme programs as the query language? Indeed, this was a topic
worth exploring!&lt;/p&gt;

&lt;p&gt;The consequence of this was that now I was adding code to recutils itself to
link against Guile, which means I will already have a dependency to the Guile C
library &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libguile&lt;/code&gt;. So, since I’m now already working with the C API of Guile,
limiting myself to the strange world of dynamic FFI was starting to feel rather
tedious.&lt;/p&gt;

&lt;p&gt;From the start I wanted to work with the real deal: the wrapper types of the
Guile extensions would be real wrappers. Each field in Scheme would be
represented by a librec C struct underneath. This is so that I can leverage the
bidirectional design above, and there is no need to parse or convert values twice
when crossing language barriers. So, how do we make a Scheme API that is both
nice to use and still C structs underneath? Well, the answer is GOOPS and
object-oriented programming!&lt;/p&gt;

&lt;h3 id=&quot;goops-virtual-slots-and-you&quot;&gt;GOOPS, virtual slots, and you&lt;/h3&gt;

&lt;p&gt;Working with raw pointers and even pointer records can be painful. It would be
much better if we could make fields like this:&lt;/p&gt;

&lt;div class=&quot;language-scheme highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&amp;lt;field&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Author&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:value&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Gerald Sussman&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is a GOOPS
&lt;a href=&quot;https://www.gnu.org/software/guile/manual/html_node/Class-Definition.html&quot;&gt;class&lt;/a&gt;,
of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;field&amp;gt;&lt;/code&gt;. The constructor has two keyword arguments &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#:name&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#:value&lt;/code&gt; for the rec names.&lt;/p&gt;

&lt;p&gt;How can we get a class that has both getters and setters (in terms of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slot-ref&lt;/code&gt;
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slot-set!&lt;/code&gt;) that work on the underlying pointer? Easy enough, the answer is
&lt;a href=&quot;https://www.gnu.org/software/guile/manual/html_node/Slot-Description-Example.html&quot;&gt;&lt;em&gt;virtual
slots&lt;/em&gt;&lt;/a&gt;!
If we were to define an ordinary class with slots &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt;, Guile
would allocate memory for those and if we are to juggle the pointer alongside
all of this, both the name and value would be in two places: once, behind the
pointer (in C world) and in Scheme, as a slot in the class.&lt;/p&gt;

&lt;p&gt;But first, how do we create a class &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;field&amp;gt;&lt;/code&gt; that wraps a pointer? Easy enough,
we can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#:init-form&lt;/code&gt; as the &lt;a href=&quot;https://www.gnu.org/software/guile/manual/html_node/Slot-Options.html&quot;&gt;slot
option&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-scheme highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;define-class&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&amp;lt;field&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;;; Internal pointer type.&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ptr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:init-form&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;wrap-rec-ptr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new-field&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:init-keyword&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#:init-form&lt;/code&gt; causes the following expression to be evaluated every
time a new class is instantiated, creating a field with an empty name and value.
To get the signature we desire above, we need to use &lt;em&gt;virtual accessors&lt;/em&gt;. These
let us override the getter and setter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#:slot-ref&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#:slot-set!&lt;/code&gt;
respectively which will work on the raw pointer, instead of occupying memory
like a normal slot would. This is achieved using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#:allocation #:virtual&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-scheme highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;define-class&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&amp;lt;field&amp;gt;&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;nf&quot;&gt;ptr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:init-form&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;wrap-field-ptr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new-field&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:init-keyword&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:ptr&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;nf&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:init-keyword&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:allocation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:virtual&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:accessor&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;field-name&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:slot-ref&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;field&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;nf&quot;&gt;%field-name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unwrap-field-ptr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;slot-ref&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:slot-set!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&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;nf&quot;&gt;set-field-name!&lt;/span&gt;
                       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unwrap-field-ptr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;slot-ref&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&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;nf&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:init-keyword&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:allocation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:virtual&lt;/span&gt;
         &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:accessor&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;field-value&lt;/span&gt;
         &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:slot-ref&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;field&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;nf&quot;&gt;%field-value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unwrap-field-ptr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;slot-ref&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
         &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:slot-set!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value&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;nf&quot;&gt;set-field-value!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unwrap-field-ptr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;slot-ref&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that the procedures we defined previously in C were renamed to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%field-value&lt;/code&gt; since it would otherwise conflict with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#:accessor&lt;/code&gt; slot option.&lt;/p&gt;

&lt;p&gt;So using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#:virtual&lt;/code&gt; lets us write GOOPS classes and not worry about double
allocation. It looks like a regular GOOPS class but actually it is modifying a
pointer to a C struct underneath using a C API. Moreover, the biggest benefit of
this is the ability to pass values in the constructor. If we didn’t have
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#:virtual&lt;/code&gt;, we’d have to write separate accessor methods like this:&lt;/p&gt;

&lt;div class=&quot;language-scheme highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;define-method&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;f-name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&amp;lt;field&amp;gt;&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;nf&quot;&gt;%field-name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unwrap-field-ptr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;slot-ref&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'ptr&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;nf&quot;&gt;define-method&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setter&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f-name&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;nf&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&amp;lt;field&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&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;nf&quot;&gt;set-field-name!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unwrap-field-ptr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;slot-ref&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But the problem with this and any other approach is that you’d still have memory
allocated for the slots. All &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;field&amp;gt;&lt;/code&gt;s will have unnecessary &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt;
slots allocated. I think the only way to get this behaviour if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#:virtual&lt;/code&gt; were
not available would be to create a custom method for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initialize&lt;/code&gt;. I think the
same applies in other CLOS-like systems (and CLOS itself), but I’m not sure.&lt;/p&gt;

&lt;h3 id=&quot;context-is-everything-friends&quot;&gt;context is everything, friends&lt;/h3&gt;

&lt;p&gt;I don’t think many Guile users will find Scheme bindings for recutils that useful in
itself, as a library. Guix uses recfiles in its search output, but its record
generation is
&lt;a href=&quot;https://git.savannah.gnu.org/cgit/guix.git/tree/guix/ui.scm#n1505&quot;&gt;hand-written&lt;/a&gt;,
usage not deep enough to warrant using the library.&lt;/p&gt;

&lt;p&gt;But I think a case can be made for recutils &lt;em&gt;itself&lt;/em&gt;, that is, if recutils were
to develop extensibility via Guile, the extension mechanism can load the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recutils&lt;/code&gt; Scheme module as its base runtime. I discussed the idea over at IRC
with Jose Marchesi, the Recutils author and maintainer, and he thought it was a
good idea as long as there’s someone there to maintain it.&lt;/p&gt;

&lt;p&gt;Maybe this will fly, I don’t know. I don’t see any big technical barriers for it
to &lt;em&gt;not&lt;/em&gt; work, even if it amounts to just adding Scheme bindings without
extending recutils itself. That said, every now and then I’m running into the
limitations of selection expressions, so being able to use Scheme as a measure
of last resort would be interesting, if nothing else.&lt;/p&gt;

&lt;p&gt;As of early December 2020 I have bindings for parsing and creating records and
fields, so expect an early release of the Scheme bindings to appear within the
next few months.&lt;/p&gt;

&lt;p&gt;Have I mentioned I also plan to make Common Lisp bindings as well? Well, now I have,
but that’s another story!&lt;/p&gt;

        </description>
        <pubDate>Sun, 06 Dec 2020 11:56:09 +0000</pubDate>
        <link>http://ane.iki.fi/programming/lisp/goops-virtual-slots-and-ffi.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/programming/lisp/goops-virtual-slots-and-ffi.html</guid>
      </item>
    
      <item>
        <title>A Guile test runner with an exit code</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;The other day I was playing around with the &lt;a href=&quot;https://mesonbuild.com/&quot;&gt;Meson&lt;/a&gt;
build system for building &lt;a href=&quot;https://www.gnu.org/software/guile/&quot;&gt;GNU Guile&lt;/a&gt;
projects. It was actually a lot of fun, Meson build files are in my opinion much
easier to manage than &lt;a href=&quot;https://www.gnu.org/software/autoconf/&quot;&gt;Autoconf&lt;/a&gt;,
although Autoconf the &lt;em&gt;de facto&lt;/em&gt; build system for Guile.&lt;/p&gt;

&lt;p&gt;It was all fun and nice until I ran into a problem with running unit tests using
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;meson test&lt;/code&gt;. Meson expects unit tests to return exit code 1 to signal a
failure, but the standard Guile test runner that implements
&lt;a href=&quot;https://srfi.schemers.org/srfi-64/srfi-64.html&quot;&gt;SRFI-64&lt;/a&gt; does not have an exit
code.&lt;/p&gt;

&lt;p&gt;So I wrote the following Scheme snippet to make a small script that you can
invoke to run tests from an arbitrary Scheme file and it returns 1 if the tests
fail. That way it can be used in Meson builds to signal unit test failures.&lt;/p&gt;

&lt;div class=&quot;language-scheme highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;define-module&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;test-driver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:declarative?&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;#f&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:use-module&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;srfi&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;srfi-64&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;nf&quot;&gt;define*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:rest&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot;Load each file in FILES while evaluating them within the context of a test
runner.&quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&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;nb&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;files&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;nb&quot;&gt;display&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Usage: test-driver.scm &amp;lt;TEST-FILE&amp;gt;\n&quot;&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;current-error-port&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;nf&quot;&gt;exit&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 class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;files&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;nf&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;file-exists?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;file&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;nb&quot;&gt;display&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;#f&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;File ~A does not exist!~%&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;file&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;nf&quot;&gt;current-error-port&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;nf&quot;&gt;exit&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 class=&quot;k&quot;&gt;let*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;full&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;string-append&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getcwd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;file&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;nf&quot;&gt;runner&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;test-runner-simple&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;nf&quot;&gt;test-with-runner&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;runner&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;load&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;full&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;lt;&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 class=&quot;nf&quot;&gt;test-runner-fail-count&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;runner&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;nf&quot;&gt;exit&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 class=&quot;nf&quot;&gt;exit&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 class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;command-line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Invoking it on a file like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;simple.scm&lt;/code&gt; as follows:&lt;/p&gt;

&lt;div class=&quot;language-scheme highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;define-module&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;simple-tests&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;:use-module&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;srfi&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;srfi-64&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;nf&quot;&gt;test-begin&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;simple&quot;&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;nf&quot;&gt;test-equal&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ok&quot;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&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;nf&quot;&gt;test-equal&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bad&quot;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&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;nf&quot;&gt;test-end&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;simple&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;produces the exit code 1 as is expected:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ guile --no-auto-compile test-driver.scm simple.scm
%%%% Starting test simple  (Writing full log to &quot;simple.log&quot;)
/Users/akalmbach/code/guile/simple.scm:8: FAIL bad
# of expected passes      1
# of unexpected failures  1

$ echo $?
1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

        </description>
        <pubDate>Fri, 30 Oct 2020 19:02:40 +0000</pubDate>
        <link>http://ane.iki.fi/programming/lisp/guile-test-driver.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/programming/lisp/guile-test-driver.html</guid>
      </item>
    
      <item>
        <title>Working with Git and patches in Emacs</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;Git was initially designed around emails.  Modern &lt;a href=&quot;https://en.wikipedia.org/wiki/Forge_(software)&quot;&gt;Git forges&lt;/a&gt; have co-opted the
term &lt;em&gt;pull request&lt;/em&gt; to mean using web-based applications for collaborating using
Git.  This has become the de facto method of collaboration in the Git world.
Before that happened, people actually used plain &lt;em&gt;emails&lt;/em&gt; when working with
decentralized version control system.  There was no notion of requiring a web
application for collaboration, you simply mailed your changes to someone and
they merged them if they wished.&lt;/p&gt;

&lt;p&gt;This document demonstrates the way I use email and Git using Emacs.&lt;/p&gt;

&lt;h3 id=&quot;why-git-and-email&quot;&gt;Why Git and email?&lt;/h3&gt;

&lt;p&gt;While working with Git these days you cannot but notice the mainstream
collaboration model is completely unlike what this document details.  You are
expected to use web applications like Github or its copies (Gitlab, etc., see
above).  Lots of people have written about the pros and cons of each, to
highlight a few:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Drew Devault in &lt;a href=&quot;https://drewdevault.com/2018/07/02/Email-driven-git.html&quot;&gt;&lt;em&gt;The advantages of email-driven git workflow&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Joe Nelson in &lt;a href=&quot;https://begriffs.com/posts/2018-06-05-mailing-list-vs-github.htm&quot;&gt;&lt;em&gt;Mailing lists vs. Github&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My own reason for preferring email is that it &lt;em&gt;promotes discussion&lt;/em&gt;.  Many
forges do not actively promote a discussion forum, which is why things like
&lt;a href=&quot;https://gitter.im&quot;&gt;gitter.im&lt;/a&gt; exist. Other alternatives is to have an IRC
channel, but those are usually too informal to focus on development.&lt;/p&gt;

&lt;h4 id=&quot;development-forums-are-essential&quot;&gt;Development forums are essential&lt;/h4&gt;

&lt;p&gt;With an email-based workflow the place for collaboration supports both
discussion and actual development work and review.  A project mailing list
offers an environment for discussing the project and for sending and reviewing
patches.&lt;/p&gt;

&lt;p&gt;When patches are mixed with discussion, it makes it easy for people to follow
the current zeitgeist of the project. Changes have more context this
way. Contrast this to a forge like GitHub where, if the project doesn’t really
state anything, you’re suppose to conduct your discussion in issues before
making a pull request.  But that can lead to confusion: issues &lt;em&gt;usually&lt;/em&gt; are
synonymous with &lt;em&gt;bug reports&lt;/em&gt;.  It would be nicer if issues were, well, issues.
In an email-based collaboration model, discussion and development happen in the
same place, it’s a vibrant
&lt;a href=&quot;http://www.catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/index.html#catbmain&quot;&gt;bazaar&lt;/a&gt;
of development.&lt;/p&gt;

&lt;h4 id=&quot;email-seriously&quot;&gt;Email? Seriously?&lt;/h4&gt;

&lt;p&gt;Ok, email and git isn’t for everybody.  That’s fine.  The folks at GitHub
rightly understood that if one were to make sending pull requests easier it
would increase the popularity of Git.  The point isn’t in elitism
or setting high barriers of entry.  I don’t think the point is in filtering
beginners either, since I wouldn’t want to be hostile to beginners.&lt;/p&gt;

&lt;p&gt;I suppose advocating Git and email in 2020 is in one sense some kind of activism
for simpler solutions from a more elegant time.  The argument is also
interesting from a technological perspective: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; is actually a
uniform, standard way of collaborating in Git.&lt;/p&gt;

&lt;p&gt;As a result, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; is actually quite relevant still despite forges
having twisted the meaning of pull request. That is why in every forge a pull
request is slightly different. Some forges call them &lt;em&gt;merge requests&lt;/em&gt; or
something similar, and the user experience for making them varies ever so
slightly.&lt;/p&gt;

&lt;h4 id=&quot;there-is-no-standard-pull-request-any-more&quot;&gt;There is no standard &lt;em&gt;pull request&lt;/em&gt; any more&lt;/h4&gt;

&lt;p&gt;There is certain nonobvious elegance in the email-based workflow: it actually
standardizes on two tools: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git am&lt;/code&gt;.  This standardization
means that everyone, regardless of their mail client, will be working with a
uniform language for collaboration.&lt;/p&gt;

&lt;p&gt;Now, many will say that web applications offer a better user experience than
emails.  That is, first and foremost, a matter of &lt;em&gt;opinion&lt;/em&gt;.  While web
applications offer more graphical bells and whistles, the problem is that in the
modern age of a multitude of Git forges every one of them will have slight
differences in the language they use and implement &lt;em&gt;pull requests&lt;/em&gt; in.  So if
you regularly collaborate on many platforms the slight idiosyncracies of each
forge will get in the way. Not so with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt;, it’s the same for
everyone!&lt;/p&gt;

&lt;h4 id=&quot;barriers-of-entry&quot;&gt;Barriers of entry&lt;/h4&gt;

&lt;p&gt;Some forges embrace email based collaboration natively:
&lt;a href=&quot;https://sourcehut.org&quot;&gt;sourcehut&lt;/a&gt; is a newish forge from 2018 which is still in
alpha as of October 2020, and it actively promotes an email-based workflow. In
fact, the people behind sourcehut are behind the tutorial at
&lt;a href=&quot;http://git-send-email.io&quot;&gt;git-send-email.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Even sourcehut recognizes that setting up &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sendemail&lt;/code&gt; in git can be onerous and
a lot of people don’t want to work with email. So they built a webpage to handle
that part where you can interactively prepare a patch email as if you were using
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt;. It’s still email at the bottom, that’s the cool part!&lt;/p&gt;

&lt;p&gt;So as a result, don’t think of git and email as some sort of activism mixed with
retrocomputing or text-based interfaces, rather, the goal is to&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;rely on a standard way of collaboration, and&lt;/li&gt;
  &lt;li&gt;natively mix discussion and development in the same environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; encourages the use of mailing lists, you no longer need
an official IRC channel or subreddit or gitter room or whatever.  And forges
like sourcehut have made it easy to separate patches in the web interface for
mailing lists, as well as having &lt;a href=&quot;https://sourcehut.org/blog/2020-07-14-setting-up-ci-for-mailing-lists/&quot;&gt;CI for mailing
lists&lt;/a&gt;
(seriously, &lt;em&gt;how cool is that&lt;/em&gt;?).&lt;/p&gt;

&lt;h3 id=&quot;git-and-email-in-5-minutes&quot;&gt;Git and email in 5 minutes&lt;/h3&gt;

&lt;p&gt;Email-based workflows in Git are based on two tools:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; for &lt;em&gt;sending changes to someone&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git am&lt;/code&gt; for &lt;em&gt;applying changes from someone&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; is essentially a wrapper around &lt;a href=&quot;https://git-scm.com/docs/git-format-patch&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git
format-patch&lt;/code&gt;&lt;/a&gt;. This wrapper calls
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git format-patch&lt;/code&gt; and mails it to the email address in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--to&lt;/code&gt; parameter. So&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ git send-email --to=&quot;foo@bar.com@&quot; HEAD^
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git format-patch HEAD^&lt;/code&gt; and send it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo@bar.com&lt;/code&gt;.  Git
includes a Perl-based email client that it uses.  This mail includes your commit
message and the diff of the changes. When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo@bar.com&lt;/code&gt; wants to apply your
patch, they save the mail and use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git am&lt;/code&gt; on it.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ git am patch.mbox
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now the question is, how do you use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git am&lt;/code&gt; from Emacs so
that you don’t have to exit to the shell?&lt;/p&gt;

&lt;h3 id=&quot;sending-patches-from-emacs&quot;&gt;Sending patches from Emacs&lt;/h3&gt;

&lt;p&gt;Those daring enough who have configured Emacs as their email client probably
think, ok, what’s the big deal, let me just call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git format-patch&lt;/code&gt; and then
mail the patch myself. The workflow would be thus:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Prepare some changes.&lt;/li&gt;
  &lt;li&gt;Commit the changes.&lt;/li&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git format-patch&lt;/code&gt; to prepare a file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo.patch&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Send &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo.patch&lt;/code&gt; as an email to the intended recipient, e.g. by opening it
and then calling &lt;kbd&gt;M-x message-mode&lt;/kbd&gt; which would open it in a major
mode for sending emails.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While this makes sense, you’ll still have to edit the intended recipient
manually, ensure your subject is formatted properly, and so on. For basic
one-off patches this might be sufficient, but you risk deviating from the
standard &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; format. The following is displayed on &lt;a href=&quot;https://git-send-email.io/#step-3&quot;&gt;git-send-email.io,
the git &amp;amp; email tutorial:&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Warning! Some people think that they can get away with sending patches through
  some means other than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt;, but you can’t. Your patches will be
  broken and a nuisance to the maintainers whose inbox they land in. Follow the
  golden rule: just use git &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;send-email&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So it’s safe to say we ought to stick to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt;. But we can use it
interactively from within Emacs.&lt;/p&gt;

&lt;h4 id=&quot;calling-git-send-email-from-emacs&quot;&gt;Calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; from Emacs&lt;/h4&gt;

&lt;p&gt;Calling any shell command is pretty easy in Emacs, just type &lt;kbd&gt;M-!&lt;/kbd&gt;
(or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x shell-command&lt;/code&gt;) and type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email -1&lt;/code&gt;. This will open up a shell
command buffer and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; will prompt you for the recipient and so on.
You can stop this process at any time using &lt;kbd&gt;C-c C-c&lt;/kbd&gt; if you’re note
happy with it. Here’s an example patch generated using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;From: Antoine Kalmbach &amp;lt;ane@iki.fi&amp;gt;
Date: Mon, 19 Oct 2020 21:47:50 +0300
Subject: [PATCH] Added a line
&lt;/span&gt;
This should improve the README experience by quite a bit.
&lt;span class=&quot;p&quot;&gt;---
Not sure about the final wording.
&lt;/span&gt; README.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/README.md b/README.md
&lt;span class=&quot;gh&quot;&gt;index f9e3d61..2e4f197 100644
&lt;/span&gt;&lt;span class=&quot;gd&quot;&gt;--- a/README.md
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+++ b/README.md
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@@ -1,3 +1,5 @@&lt;/span&gt;
 # Hello there!
 
 Blah blah blah.
&lt;span class=&quot;gi&quot;&gt;+
+Let's add this line here.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sometimes it makes sense to annotate your patch with a message that explains
what the patch does, but not in a way that it would end up into the commit
history.  In the example above, that’s the bit under the three dashes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;---&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To add such an annotation, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; specifies a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--annotate&lt;/code&gt; flag that
will preview your patch in your editor specified by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$EDITOR&lt;/code&gt; environment
variable. If you have your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EDITOR&lt;/code&gt; set correctly to e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;emacsclient&lt;/code&gt;, this
will work just fine provided you’re running an Emacs server.&lt;/p&gt;

&lt;h4 id=&quot;setting-emacs-as-editor&quot;&gt;Setting Emacs as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$EDITOR&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;If you try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--annotate&lt;/code&gt; without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EDITOR&lt;/code&gt; set, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; will most likely
complain that your terminal has no editor specified, and quit.  We’re executing
a shell command, so we want to tell the terminal that we’re doing this from &lt;em&gt;the
editor&lt;/em&gt;. There’s an easy way to do this: Emacs has a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with-editor-shell-command&lt;/code&gt;
which will then set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EDITOR&lt;/code&gt; to the Emacs process. Just call &lt;kbd&gt;M-x&lt;/kbd&gt;
&lt;kbd&gt;with-editor-shell-command&lt;/kbd&gt; and type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email -1 &amp;amp;&lt;/code&gt;.  The
ampersand tells the shell to execute the command asynchronously, letting us
interact with the process while it is running.  (If it was executing
synchronously we’d have no way of suspending the command execution to spawn an
editor buffer.) You can also do directly &lt;kbd&gt;M-x&lt;/kbd&gt;
&lt;kbd&gt;with-editor-async-shell-command&lt;/kbd&gt; and you can drop the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can also call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git format-patch&lt;/code&gt; to produce the patch and then send it using
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; which also accepts patch files.  That way you can inspect the
patch file before sending it, but this is mostly unnecessary since if you pass
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--annotate&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; it will preview the file anyway.  I recommend
calling&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ git config --global sendemail.annotate yes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git send-email&lt;/code&gt; will always preview the patch before sending it.&lt;/p&gt;

&lt;p&gt;Ok now that we’ve successfully sent a patch, how do we turn this around and
&lt;em&gt;apply&lt;/em&gt; patches sent to us?&lt;/p&gt;

&lt;h3 id=&quot;applying-email-patches-in-emacs&quot;&gt;Applying email patches in Emacs&lt;/h3&gt;

&lt;p&gt;Let’s assume a patch has landed in your email.  You need to be able to save this
patch in either a &lt;a href=&quot;https://en.wikipedia.org/wiki/Mbox&quot;&gt;mbox&lt;/a&gt; or
&lt;a href=&quot;https://en.wikipedia.org/wiki/Maildir&quot;&gt;maildir&lt;/a&gt; format.  If you’re not sure how
to do this, you can just copy the mail verbatim into a text file and then pass
that to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git am&lt;/code&gt;.  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git am&lt;/code&gt; will detect the format and use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;From:&lt;/code&gt; field to
set the committer and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Subject:&lt;/code&gt; and message body will go into the commit
message.&lt;/p&gt;

&lt;p&gt;How to do this in Emacs?  For this, we don’t have to just rely only on shell
commands anymore.  We can use either&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the wonderful &lt;a href=&quot;http://magit.vc/&quot;&gt;Magit&lt;/a&gt; package with its interface for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git
am&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;opening the patch and sending (piping) the whole buffer to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git am&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using Magit, this is as simple as pressing &lt;kbd&gt;w w&lt;/kbd&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;magit-am-apply-patches&lt;/code&gt;) or
&lt;kbd&gt;w m&lt;/kbd&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;magit-am-apply-maildir&lt;/code&gt;).  Just find the patch email and you’re
set.&lt;/p&gt;

&lt;p&gt;Without Magit you can do this just by opening the patch and piping its output to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git am&lt;/code&gt;. That is as easy as doing &lt;kbd&gt;M-|&lt;/kbd&gt; &lt;kbd&gt;git am&lt;/kbd&gt;. But that
requires you to be in the same directory as the repository itself. So you’d have
to &lt;kbd&gt;M-x&lt;/kbd&gt; &lt;kbd&gt;cd&lt;/kbd&gt; into the directory before applying. But all in
all, there are several ways for doing this directly from Emacs, and of course as
a last resort you can just open the Emacs shell &lt;kbd&gt;M-x&lt;/kbd&gt; &lt;kbd&gt;eshell&lt;/kbd&gt;
and do it from thecommand line.&lt;/p&gt;

&lt;h4 id=&quot;making-our-own-m-x-git-am&quot;&gt;Making our own &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x git-am&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;If you’re not too keen on using Magit or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd&lt;/code&gt;ing to the directory every time, I
wrote this handy little Emacs Lisp to provide a nice &lt;kbd&gt;M-x&lt;/kbd&gt;
&lt;kbd&gt;git-am&lt;/kbd&gt; command:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;git-am&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;repository&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot;Run git-am in REPOSITORY with the current buffer.

If REPOSITORY is nil, prompt for a directory.  If a region is
selected, it will pipe the buffer to git am.  If the current
buffer mode is Rmail, Gnus article, or diff mode, it will call
`git am' with the contents of the current buffer.  

If the current buffer isn't appropriate and there is no region selected,
call git am after prompting for a patch/mbox/maildir. 

If the current buffer is a `vc-dir-mode', assume we are in
the repository and we want to look for a patch somewhere else.

If Magit is available and we're in a `magit-status-mode' buffer,
the same treatment as `vc-dir-mode' is given.

With prefix argument ignore the fact we're in a version control
buffer and prompt for the repository anyway.&quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;interactive&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&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;nb&quot;&gt;and&lt;/span&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;current-prefix-arg&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;memq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;major-mode&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;nv&quot;&gt;vc-dir-mode&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;magit-status-mode&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;nb&quot;&gt;eq&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'Git&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;vc-responsible-backend&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;default-directory&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;vc-git-root&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;default-directory&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;read-directory-name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Repository: &quot;&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;nb&quot;&gt;when&lt;/span&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;repository&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;nb&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;No repository given.&quot;&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;nb&quot;&gt;when&lt;/span&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eq&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'Git&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;vc-responsible-backend&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;repository&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;nb&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Not a git repository: %s&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;repository&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;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;default-directory&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;expand-file-name&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;repository&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;nb&quot;&gt;cond&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;mark&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;shell-command-on-region&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;region-beginning&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;region-end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;git am&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

          &lt;span class=&quot;c1&quot;&gt;;; Use the whole mail buffer when viewing a patch email or patch file.&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;memq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;major-mode&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;nv&quot;&gt;rmail-mode&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;gnus-article-mode&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;diff-mode&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;shell-command-on-region&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;point-min&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;point-max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;git am&quot;&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;no&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;shell-command&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;s&quot;&gt;&quot;git am %s&quot;&lt;/span&gt;
                      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;read-file-name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Apply patch (mbox/patch/maildir): &quot;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This command works both in version control status buffers, dired buffers, patch
files and patch emails. If the user is looking at some version control status
buffer, it assumes the repository is the one we’re in, unless the prefix
argument is given by pressing &lt;kbd&gt;C-u&lt;/kbd&gt; &lt;kbd&gt;M-x&lt;/kbd&gt;
&lt;kbd&gt;git-am&lt;/kbd&gt;. If we’re in a mail buffer or looking at a diff-mode file
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.patch&lt;/code&gt;), we’re going to apply &lt;em&gt;this patch&lt;/em&gt; to some unknown repository. And
if none of this is true we’re going to prompt for the patch as well.&lt;/p&gt;

&lt;p&gt;Emacs has for a couple of major versions supported the idea of &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/emacs/Projects.html&quot;&gt;version control&lt;/a&gt;
as projects. That is, a version controlled directory tree is a &lt;em&gt;project&lt;/em&gt;, i.e. a
collection of related files. This facility leverages ignore mechanisms like
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt; by providing an interactive file selection interface but with ignored
files filtered out from the search.  Whenever you interact with such a project,
Emacs registers this repository into its list of known projects.&lt;/p&gt;

&lt;p&gt;Since these projects map to git repositories, I wrote a wrapper for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git-am&lt;/code&gt;
that will present repositories using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;project-prompt-project-dir&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;project-git-am&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;amp;optional&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;use-current-project&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot;Run `git-am' in a project directory.

With a prefix argument run in the current project if found, otherwise
prompt for a project directory.

See the Info node `(emacs) Projects' for what a project is.&quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;interactive&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;P&quot;&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;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&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;nb&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;use-current-project&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;project-current&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;project-root&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;project-current&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;project-prompt-project-dir&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;git-am&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Looks like this requires installing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;project.el&lt;/code&gt; from &lt;a href=&quot;http://elpa.gnu.org/packages/project.html&quot;&gt;GNU
ELPA&lt;/a&gt;, or using Emacs 28 from Git,
which includes this version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;project.el&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Who knows, maybe all of this will end up in its own package one day!  Even
without this Elisp code you can easily use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git am&lt;/code&gt; quite readily in Emacs with
the tools already available. If nothing else, this code shows how easily you can
do powerful customizations for simple shell commands in Emacs!&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Git + Email = ❤. It’s nice to see a resurgence of Git and email being boosted by
sites like &lt;a href=&quot;http://sourcehut.org&quot;&gt;sourcehut&lt;/a&gt;.  I think the first time I used Git
and email must have been in maybe 2008?  I don’t remember what it was for, but I
do remember mailing it to the author directly from
&lt;a href=&quot;https://en.wikipedia.org/wiki/Alpine_(email_client)&quot;&gt;alpine&lt;/a&gt;.  Not long after
that GitHub came and made everything different.&lt;/p&gt;

        </description>
        <pubDate>Mon, 19 Oct 2020 12:17:06 +0000</pubDate>
        <link>http://ane.iki.fi/emacs/patches.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/emacs/patches.html</guid>
      </item>
    
      <item>
        <title>Divergence: A website is born</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;Some readers might have noticed a new section appearing on the &lt;a href=&quot;http://ane.iki.fi&quot;&gt;front page&lt;/a&gt;. It’s
just a simple heading with a list of sections &lt;em&gt;outside the blog&lt;/em&gt;. This is because
I’ve for a long time felt that the blog format doesn’t feel right for
informative or lengthy writing. That is, I’d much rather prefer my blog to be
just a simple journal I don’t have to think too hard about, since I find it
reduces my eagerness to write simple updates.&lt;/p&gt;

&lt;p&gt;To me, and I emphasize &lt;em&gt;to me&lt;/em&gt;, the blogging format is like a journal, like a
&lt;a href=&quot;https://en.wikipedia.org/wiki/Finger_protocol#Finger_user_information_protocol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.plan&lt;/code&gt; file&lt;/a&gt;, but on the web.  That is why I’m putting new content that doesn’t
fit the format to just as plain pages.  I’ll set up some sort of index using the
Jekyll tags mechanism, it fits well for this purpose.&lt;/p&gt;

&lt;p&gt;I’ve also added a &lt;a href=&quot;/changelog.html&quot;&gt;change log&lt;/a&gt; that lists what has changed on the site. While I
write &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/emacs/Format-of-ChangeLog.html&quot;&gt;GNU style ChangeLogs&lt;/a&gt; in commit messages, this format is not really
readable or accessible to readers.&lt;/p&gt;

&lt;p&gt;I also removed &lt;a href=&quot;https://getbootstrap.com/&quot;&gt;Bootstrap&lt;/a&gt; CSS from the site. Utility CSS is fun, but the site
design is so minimal it doesn’t really make any sense. I also added a &lt;a href=&quot;https://lists.sr.ht/~ane/web&quot;&gt;mailing
list&lt;/a&gt; to serve as a comment box or discussion forum for the site, but time will
tell if that place will see any discussion.&lt;/p&gt;

&lt;p&gt;So, all in all, expect to see more interesting content and more blog updates as
now I’ve finally made sense of the whole website thing!&lt;/p&gt;

        </description>
        <pubDate>Sun, 11 Oct 2020 10:32:21 +0000</pubDate>
        <link>http://ane.iki.fi/2020/10/11/divergence.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2020/10/11/divergence.html</guid>
      </item>
    
      <item>
        <title>The overhead of test-driven development</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;There are significant merits in &lt;a href=&quot;https://en.wikipedia.org/wiki/Test-driven_development&quot;&gt;test-driven development&lt;/a&gt; (TDD), but I think its costs
outweigh its benefits. The idea in short is that&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;you write all your software requirements as test cases,&lt;/li&gt;
  &lt;li&gt;you write the test cases &lt;em&gt;first&lt;/em&gt; so that they fail,&lt;/li&gt;
  &lt;li&gt;you write the program until &lt;em&gt;all&lt;/em&gt; test cases pass,&lt;/li&gt;
  &lt;li&gt;and your program is complete.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that the test cases do not necessarily need to be automated, nor do they
need to be &lt;em&gt;unit tests&lt;/em&gt;, as long as there’s a test–develop–test–develop cycle.&lt;/p&gt;

&lt;h3 id=&quot;iterate-iterate-iterate&quot;&gt;Iterate, iterate, iterate&lt;/h3&gt;

&lt;p&gt;This can lead to a very short and sweet development cycle, because as soon as
all the tests pass, your program is ready–supposedly. But the devil is in the
details, because as soon as you lay down those four items, you start asking
questions like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How is a requirement properly captured as a test case?&lt;/li&gt;
  &lt;li&gt;What is the level of granularity for your tests?&lt;/li&gt;
  &lt;li&gt;How much work is needed to create working tests?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To answer the first question, you need to properly understand the
requirement. You need to be testing the right thing, at the right level. For
instance, if a requirement of a library management system says that “the same
user cannot make more than one reservation on a single item”, how do you test
this? Do you register a user, create an item in the library catalog, make one
reservation, then try making another, expecting a rejection? Initially we’d like
our fail the test case by not rejecting the double reservation, once the second
reservation is rejected the test is considered a success.&lt;/p&gt;

&lt;p&gt;The design of the test case itself is quite complex. For the test to be able to
work, we now need to have functionality for&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;registering or loading a preset user,&lt;/li&gt;
  &lt;li&gt;loading a library catalog (or adding new items to it), and&lt;/li&gt;
  &lt;li&gt;a mechanism for making reservations, and checking whether they succeed or not.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So obviously the first step is not to get the test to fail but to &lt;em&gt;work&lt;/em&gt;: our test
program needs to get to the point it has to signal failures or passes. This is
where we get to the second question: what do we use to build the test scenario?
Do we just write a program that calls some functions in the reservation system,
or we do user interface tests where another program interacts with the program?
Choosing the testing level is not easy! User interface tests require complex
machinery to set up, but they are valuable, because you can treat the underlying
implementation as a black box. This is valuable, because this way you cannot
make tight coupling between the implementation and the interface. Only the
results matter.&lt;/p&gt;

&lt;h3 id=&quot;first-you-must-create-the-universe&quot;&gt;First, you must create the universe…&lt;/h3&gt;

&lt;p&gt;The last question is the most interesting one: we need to be able to create
tests that signal whether they have failed or not. For them to be useful, you
need the tests to actually interact with the program somehow. This could mean
that the tests call the functions you are testing. To get that to work, you need
to define function stubs so that the compiler or interpreter you are working
with does not reject your code.&lt;/p&gt;

&lt;p&gt;For instance, consider this Java code:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testReservation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Reservation&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reservation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TestData&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getReservation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// some global reservationSystem defined outside this method&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;success&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reservationSystem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;makeReservation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reservation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;failure&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reservationSystem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;makeReservation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reservation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;assertFalse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;failure&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Rather obviously for the Java compiler to accept this we need to have the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;makeReservation&lt;/code&gt; method on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reservationSystem&lt;/code&gt;! In the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReservationSystem&lt;/code&gt;
class we define&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// in ReservationSystem.java&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;makeReservation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Reservation&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reservation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Not to mention that you’d have to define the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Reservation&lt;/code&gt; class, and so
on.&lt;/p&gt;

&lt;p&gt;I think test-driven development can be quite beneficial when you are refactoring
your code or adding or modifying functionality. That is, in the
above example, suppose we already have a working reservation system and all the
necessary scaffolding in place. Implementing the double-reservation prevention
in a TDD fashion is quite simple: just add the test above, and fix your code.&lt;/p&gt;

&lt;p&gt;But what about when you don’t have a program to modify, or you are writing a
suite of test cases for a part that isn’t there? Suppose we don’t yet have a
reservation system at all, and this test case is a part of a number of many test
cases each and everyone of which needs some kind of functionality in order to
compile to get to the failing state?&lt;/p&gt;

&lt;p&gt;Futhermore, if you’re starting from scratch, it’s obvious that you need to spend
considerable effort on writing the stubs first, and this indirectly guides your
development process, and the way you design the program. Here’s where get to the
big question: &lt;strong&gt;does test-driven development guide your program design in a way
that’s appropriate?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The answer is &lt;em&gt;it depends&lt;/em&gt;. To be precise, it depends on the way you approach
program design. For those who don’t mind writing the stubs and test scaffolding
first it can be a hugely productive manner of working, but to those who like to
think in small iterations with functionality first, it feels counterintuitive.&lt;/p&gt;

&lt;p&gt;When building a bridge it makes a lot of sense to specify up front that it
should be robust enough to tolerate the weight of a hundred cows when
complete. On the other hand, it would be rather stupid to continuously drive
cows on the bridge even before construction has started. The cows would fall
into the water and everyone, especially the cows, would find the experience
quite displeasing.&lt;/p&gt;

&lt;p&gt;Although software is not physical, time is still time and just like the bridge
testers would have spend time driving cows into water (initially) and have to
rescue them from the water, in the beginning of a TDD process one needs to fight
the compiler so that you get the tests to work.&lt;/p&gt;

&lt;p&gt;So to me doing the initial grunt work of setting up stubs for test-driven
development feels like throwing cows into the water. I like to start with the
requirements, figure out a minimum viable design that’s testable, and then write
the tests, and repeat until the program satisfies the requirement and the tests
are rigorous enough.&lt;/p&gt;

&lt;p&gt;But when refactoring programs or adding or modifying functionality I &lt;em&gt;sometimes&lt;/em&gt;
practice TDD but not religiously. It largely depends on what I’m working on and
if the feedback loop between change-test-change-test is fast.&lt;/p&gt;

        </description>
        <pubDate>Fri, 09 Oct 2020 08:44:50 +0000</pubDate>
        <link>http://ane.iki.fi/programming/practices/tdd.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/programming/practices/tdd.html</guid>
      </item>
    
      <item>
        <title>How this site works</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;This site is a fairly standard &lt;a href=&quot;http://jekyllrb.com&quot;&gt;Jekyll&lt;/a&gt; static website. The site is divided into
two principal sections: content and &lt;a href=&quot;/archive.html&quot;&gt;blog&lt;/a&gt;. Posts are written primarily in
Markdown. The site is versioned using Git and hosted at &lt;a href=&quot;https://github.com/ane/ane.github.io/&quot;&gt;GitHub&lt;/a&gt;, a &lt;a href=&quot;https://github.com/ane/ane.github.io/blob/develop/.travis.yml&quot;&gt;Travis CI&lt;/a&gt; job
builds the site after every commit and then pushes the contents of the develop
branch onto master, which is served by GitHub pages.&lt;/p&gt;

&lt;p&gt;An essential part of the content section is the &lt;a href=&quot;https://jekyllrb.com/docs/liquid/tags/#links&quot;&gt;_link&lt;/a&gt; function in Jekyll. All
the hyperlinks to documents in the site are linked using that, absolute file
references are not used. The link function ensures the files are there, this
ensures that there are no dead links on the site.  I don’t use &lt;a href=&quot;https://jekyllrb.com/docs/collections/&quot;&gt;collections&lt;/a&gt;
anymore (I used them for the microblog), basic &lt;a href=&quot;https://jekyllrb.com/docs/pages/&quot;&gt;pages&lt;/a&gt; are sufficient to maintain
the non-blog content on this site.  They are not useful for my purposes, perhaps
I’ll need them one day.&lt;/p&gt;

&lt;p&gt;I once tried to use &lt;a href=&quot;http://orgmode.org/&quot;&gt;Org&lt;/a&gt; to maintain this site, but it was slow and I saw very
little gain in that. It was quite painful to configure as well. Jekyll is fairly
easy to hack on and the templating language is quite sufficient.&lt;/p&gt;

&lt;figure style=&quot;float: right; margin: 1rem;&quot;&gt;
 &lt;a href=&quot;/this-site/how.png&quot;&gt;&lt;img src=&quot;/this-site/how.png&quot; width=&quot;350px&quot; /&gt;&lt;/a&gt;
 &lt;figcaption&gt;What this paragraph looks like with markup hidden in Emacs&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;For editing, I make heavy use of &lt;a href=&quot;https://jblevins.org/projects/markdown-mode/&quot; title=&quot; &quot;&gt;markdown-mode&lt;/a&gt; and &lt;a href=&quot;http://web-mode.org/&quot;&gt;web-mode&lt;/a&gt;. Both are &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/emacs/Major-Modes.html&quot;&gt;Emacs
major modes&lt;/a&gt; for editing markdown and HTML, respectively. web-mode in particular
is essential for HTML editing since it can handle template engines and has great
structural navigation and editing commands. Markdown mode does many things, what
I use the most is the ability to hide the markup (&lt;kbd&gt;C-c C-x C-m&lt;/kbd&gt;), so it just looks
like text, and hyperlinks are formatted inline so I don’t see the ugly link
syntax. I also insert hyperlinks using &lt;kbd&gt;C-c C-l&lt;/kbd&gt; since I can use links I’ve
previously inserted in the same file.&lt;/p&gt;


        </description>
        <pubDate>Wed, 07 Oct 2020 08:54:36 +0000</pubDate>
        <link>http://ane.iki.fi/this-site/how.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/this-site/how.html</guid>
      </item>
    
      <item>
        <title>Origin of this site</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;About five years ago I realized I wanted to have a website again. Yes, &lt;em&gt;again&lt;/em&gt;,
this wasn’t the first time I had had a website.&lt;/p&gt;

&lt;p&gt;I think I had my first website in the late 90s, it was hosted on &lt;a href=&quot;https://en.wikipedia.org/wiki/Xoom_(web_hosting)&quot;&gt;xoom.com&lt;/a&gt; and I
had to upload content to it via &lt;a href=&quot;https://en.wikipedia.org/wiki/File_Transfer_Protocol&quot;&gt;FTP&lt;/a&gt; over a 56k modem, no broadband at that time
yet. We had fast internet at our school so sometimes I edited the site
there. Later on I switched to hosting provided by a Finnish computer magazine
&lt;a href=&quot;https://en.wikipedia.org/wiki/MikroBitti&quot;&gt;MikroBitti&lt;/a&gt;. I stopped maintaining that site around 2005 or so, I must have been
17 or something and had more important things to worry about (like school and
&lt;em&gt;World of Warcraft&lt;/em&gt;… ok, mostly &lt;em&gt;World of Warcraft&lt;/em&gt;).. It wasn’t interesting
anymore, it mostly contained some CSS website layouts I had made.&lt;/p&gt;

&lt;p&gt;Early 2015 I decided I wanted to write a blog. I had no idea what about, but
everyone on the internet seemed to have some sort of verbal outlet for their
computer things. So I joined the club, copied some Jekyll theme from somewhere,
and wrote a couple of posts. Eventually I ended up &lt;a href=&quot;https://github.com/ane/ane.github.io/commit/0e8fb2a3ab9ed9ed17c7dbabd0451eaea3fab799&quot;&gt;deleting those&lt;/a&gt;, and I had
actually nothing on this site, but in January 2016 &lt;a href=&quot;/2016/01/01/before-we-begin.html&quot;&gt;I lowered the bar&lt;/a&gt; and started
again.&lt;/p&gt;

&lt;p&gt;It seems the most active year (up to now) was 2016, with the quietest period
being the years 2018-2019. I had lots of things going on in my life around that
time, and I was still holding the site to too high a standard. I was torn:
because I was misusing blogging as a medium, I couldn’t blog as a &lt;em&gt;journal&lt;/em&gt;
instead I was blogging as a &lt;em&gt;magazine&lt;/em&gt;. I’ve come to accept that if I am to blog
often it needs to be an informal journal, otherwise I will set the posting
standard too high and not post.&lt;/p&gt;

&lt;p&gt;Fast forward to 2020 I ended up revitalizing my interest on this site, and this
happened almost by accident. I created a &lt;a href=&quot;/micro/202006130000&quot;&gt;created a microblog&lt;/a&gt; and then &lt;a href=&quot;/2020/10/06/no-more-microblog.html&quot;&gt;ended it&lt;/a&gt;,
because I realized it made no sense to have a blog with an arbitrary minimum
post length. Then I realized I need to actually have more than just blog posts,
many of the blog posts I have are actually quite &lt;a href=&quot;/2018/04/26/software-customization.html&quot;&gt;gargantuan in size&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So I started to transition the site towards the blog being, well, just an online
journal of sorts. More structured content is grouped and assembled into the
front page, you can read about that &lt;a href=&quot;/this-site/how.html&quot;&gt;over here&lt;/a&gt;. Eventually, most of the content
will live outside the blog in various sections, because I think blogging as a
medium should focus more on a streams-of-though type of posting instead of
having informative content. I think combining the two makes it very confusing
for readers.&lt;/p&gt;

        </description>
        <pubDate>Wed, 07 Oct 2020 08:52:24 +0000</pubDate>
        <link>http://ane.iki.fi/this-site/origin.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/this-site/origin.html</guid>
      </item>
    
      <item>
        <title>Design of this site</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;This page describes the design of this website. If you come here often you might
notice that every now and then something changes. That is normal, because I
&lt;em&gt;really&lt;/em&gt; enjoy tweaking the smallest of things here, be it adjusting margins,
adding padding, changing fonts, and so on. It’s a neverending project, I can’t
tell you if the site as you see &lt;em&gt;now&lt;/em&gt; will be how it will look like in five
years. But here’s a rough idea how it looks like at the time of writing.&lt;/p&gt;

&lt;p&gt;Most people will ask, “what design?”, as you’re greeted with the browser default
font, probably a serif or sans-serif font, no colors beside the links, barely
any borders or visual frills. This is by design, or &lt;em&gt;the&lt;/em&gt; design: the design
emphasizes this site’s focus on &lt;em&gt;content&lt;/em&gt;. I want the text to be as readable and
distraction-free as possible. To this end,&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the content is center-aligned and constrained to a maximum width on large
screens,&lt;/li&gt;
  &lt;li&gt;the font is black-on-white at about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;16px&lt;/code&gt; of height,&lt;/li&gt;
  &lt;li&gt;the navigation is at the top of the page, and also aligned to the center,&lt;/li&gt;
  &lt;li&gt;there are no colours or background highlights unless absolutely necessary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Part of the reason why I don’t specify any extra fonts or the like is to make
sure the site works on any device possible. I also happen to enjoy browsing
“unstyled” pages because it puts emphasis on content over form, although some
styling is necessary to make this enjoyable. There is no need to design for
responsiveness when the site mostly just text.&lt;/p&gt;

&lt;p&gt;The stylesheet is &lt;a href=&quot;https://github.com/ane/ane.github.io/blob/develop/assets/override.scss&quot;&gt;a couple hundred lines of SCSS&lt;/a&gt; and mostly just deals with the
formating of the navbar and images, and removing some built-in ugliness of the
default browser styles, e.g., by thinning out horizontal rules to a single line.&lt;/p&gt;

&lt;p&gt;I plan for the central index at the front page to evolve in a tree-like
structure of the whole site itself, but as the content outside the blog is
rather thin, it’s just a link to, well, this section.&lt;/p&gt;

        </description>
        <pubDate>Wed, 07 Oct 2020 08:51:53 +0000</pubDate>
        <link>http://ane.iki.fi/this-site/design.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/this-site/design.html</guid>
      </item>
    
      <item>
        <title>No more microblog</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;The &lt;a href=&quot;/micro&quot;&gt;microblog&lt;/a&gt; is no more. I got this idea due to a sudden
realization: there is no minimum length to a blog post. Any microblog post was
just a short blog post. Perhaps the idea with it was to participate in the 
&lt;a href=&quot;https://indieweb.org/&quot;&gt;IndieWeb&lt;/a&gt; zeitgeist, but in the end I realized I’m not
interested in posting that much short-form content. Twitter is just noise, why
would any federated version of it be less noise?&lt;/p&gt;

&lt;p&gt;So, the microblog is gone. I’ll keep the &lt;a href=&quot;/micro&quot;&gt;page&lt;/a&gt; around but
this page will be the only place linking to it.&lt;/p&gt;

&lt;p&gt;Perhaps this will affect my blogging frequency, perhaps not. One thing that will
be different is the blog will focus on informal writings, perhaps even to just
say &lt;em&gt;I ate a nice pizza today&lt;/em&gt;, and I’ll start working on having a content
vs. journal style separation between the blog.&lt;/p&gt;

&lt;p&gt;Maybe.&lt;/p&gt;

        </description>
        <pubDate>Tue, 06 Oct 2020 13:56:28 +0000</pubDate>
        <link>http://ane.iki.fi/2020/10/06/no-more-microblog.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2020/10/06/no-more-microblog.html</guid>
      </item>
    
      <item>
        <title>Between two Lisps</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;Out of all Lisps the ones I’ve come to appreciate the most are &lt;a href=&quot;https://en.wikipedia.org/wiki/Scheme_(programming_language)&quot;&gt;Scheme&lt;/a&gt; and &lt;a href=&quot;https://common-lisp.net/&quot;&gt;Common
Lisp&lt;/a&gt;. &lt;!--break--&gt;These two languages are fundamentally very different: Scheme
is a minimalist language built on the foundations of &lt;a href=&quot;https://en.wikipedia.org/wiki/Lambda_calculus&quot;&gt;lambda calculus&lt;/a&gt;, while
Common Lisp is a multi-paradigm synthesis of many Lisps before it. Common Lisp
is a large standard with many implementations, Scheme is a collection of an
evolving but minimalistic standard with many implementations. The core of Scheme
is quite small compared to Common Lisp. The latest standard &lt;a href=&quot;http://www.r6rs.org/final/r6rs-lib.pdf&quot;&gt;R6RS&lt;/a&gt; is about 65
pages, while the ANSI Common Lisp standard from 1994 is about 1100 pages. The
&lt;a href=&quot;https://srfi.schemers.org/&quot;&gt;Scheme Requests for Implementation&lt;/a&gt; process aims to standardize additional
features (like &lt;a href=&quot;https://srfi.schemers.org/srfi-64/srfi-64.html&quot;&gt;test suites&lt;/a&gt;) that implementations may implement.&lt;/p&gt;

&lt;p&gt;Common Lisp has some wonderful features, &lt;a href=&quot;http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html&quot;&gt;conditions and restarts&lt;/a&gt;, the &lt;a href=&quot;https://lispcookbook.github.io/cl-cookbook/clos.html&quot;&gt;Common
Lisp Object System (CLOS)&lt;/a&gt;, &lt;a href=&quot;http://www.paulgraham.com/onlisp.html&quot;&gt;the macro system&lt;/a&gt;, among many other things. The &lt;a href=&quot;http://joaotavora.github.io/sly/&quot;&gt;SLY
IDE for Emacs&lt;/a&gt; is &lt;em&gt;amazing&lt;/em&gt;, and the &lt;a href=&quot;http://www.sbcl.org/&quot;&gt;Steel Bank Common Lisp&lt;/a&gt; compiler is really
great. It has &lt;a href=&quot;https://www.quicklisp.org/index.html&quot;&gt;Quicklisp&lt;/a&gt; and &lt;a href=&quot;https://common-lisp.net/project/asdf/&quot;&gt;ASDF&lt;/a&gt; for package and build management,
respectively. I find the developer experience of Common Lisp to be superior to
almost anything imaginable, and this is not an empty statement: having used all
sorts of IDEs and editors for over 25 years, I have seen &lt;em&gt;many&lt;/em&gt;.&lt;/p&gt;

&lt;h3 id=&quot;tastes-differ&quot;&gt;Tastes differ&lt;/h3&gt;

&lt;p&gt;That said, Common Lisp is &lt;em&gt;weird&lt;/em&gt;. What I find particularly jarring is that
functions and variables live in different namespaces: if you put a function into
a variable, you can’t just use it like a function, you have to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;funcall&lt;/code&gt; it.
Having programmed in lots of languages of the ML family this is just, well, odd;
but this is due to historical reasons and there are &lt;a href=&quot;http://www.nhplace.com/kent/Papers/Technical-Issues.html&quot;&gt;sound technical reasons for
it&lt;/a&gt;.  There are other
oddities, some strange things like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(cdr '())&lt;/code&gt; is not an error (in Scheme it
is), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt; are equal (in Scheme &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#f&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt; are separate things), and
so on.&lt;/p&gt;

&lt;p&gt;This isn’t really a fault in Common Lisp: other languages have impacted my taste
and preferences to bias me in the direction of Scheme, but that is not to say I
cannot work with Common Lisp’s idiosyncracies. Actually, I don’t mind them, I
just &lt;em&gt;notice&lt;/em&gt; them.&lt;/p&gt;

&lt;p&gt;I like the naming styles of Scheme more, as well. It has &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string?&lt;/code&gt; vs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string-p&lt;/code&gt;
for predicate functions, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set!&lt;/code&gt;  for state modifying functions, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo-&amp;gt;bar&lt;/code&gt; for
conversions, these make code quite easier to read. Scheme has hygienic macros,
Guile has the traditional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;defmacro&lt;/code&gt; as well.&lt;/p&gt;

&lt;p&gt;Many nice Scheme features are available in Common Lisp libraries. Pattern match
is available in the &lt;a href=&quot;https://github.com/guicho271828/trivia&quot;&gt;trivia&lt;/a&gt; library. Named lets are easy to implement with a macro.&lt;/p&gt;

&lt;p&gt;Common Lisp aficionados are quick to point out things Scheme &lt;em&gt;doesn’t&lt;/em&gt; have:
keyword arguments, docstrings, rest arguments, but my Scheme implementation of
choice Guile has these built into the language.&lt;/p&gt;

&lt;h3 id=&quot;productivity-matters&quot;&gt;Productivity matters&lt;/h3&gt;

&lt;p&gt;Guile is in a strange niche is that its primary &lt;em&gt;raison d’être&lt;/em&gt; is to be an
extension language for the GNU project. Like Emacs Lisp is for extending Emacs,
Guile is the &lt;em&gt;de facto&lt;/em&gt; language for GNU programs for extension and scripting.&lt;/p&gt;

&lt;p&gt;Guile doesn’t have Quicklisp and its package manager and build system is
basically nonexistent for the first and &lt;a href=&quot;https://www.gnu.org/software/autoconf/&quot;&gt;Autoconf&lt;/a&gt; for the second. There is
&lt;a href=&quot;https://lists.gnu.org/archive/html/guile-user/2017-03/msg00168.html&quot;&gt;sentiment&lt;/a&gt; in the Guile community to have &lt;a href=&quot;https://guix.gnu.org/&quot;&gt;Guix&lt;/a&gt; as the package manager for
Guile. This might sound a bit onerous, since Guix is also a complete package
management for many other things than Guile, but consider this: as Andy Wingo
points out in his message that Guile libraries often come with C extensions,
Guile packages need some sort of managed build system for building the C
extensions. Since it doesn’t have one, to solve the problem of building a
package manager you’d also have to build a build system that can manage C code
and packages needed by the C code bits. To do this elegantly is a gargantuan
task, for instance, &lt;a href=&quot;https://wiki.call-cc.org/man/5/Extensions#installing-eggs-that-use-libraries&quot;&gt;chicken-install just asks you to put compiler/linker flags
on the command line before calling it&lt;/a&gt;, so it obviously is a hard problem.&lt;/p&gt;

&lt;p&gt;Now, Guix solves all that, and more, in a manner that is quite elegant and
interesting. But it’s not as lightweight as something like Quicklisp or
&lt;a href=&quot;https://wiki.call-cc.org/man/5/Extensions&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chicken-install&lt;/code&gt;&lt;/a&gt; from &lt;a href=&quot;http://call-cc.org/&quot;&gt;CHICKEN Scheme&lt;/a&gt;. What is more, Guix works only on GNU/Linux
systems really, so macOS and Windows users won’t be able to do use your library
if you plan on distributing it via Guix. Duh, it’s the GNU project, but
portability is always nice.&lt;/p&gt;

&lt;p&gt;But in Common Lisp I can write &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(ql:quickload :alexandria)&lt;/code&gt; and voilà, it will
automatically install the &lt;a href=&quot;http://quickdocs.org/alexandria/&quot;&gt;Alexandria&lt;/a&gt; library that I can use. Then again, in
Common Lisp it’s somewhat rarer to have C extensions, so I don’t know how ASDF
handles that.&lt;/p&gt;

&lt;p&gt;It is unfair to compare &lt;a href=&quot;http://joaotavora.github.io/sly/&quot;&gt;SLY&lt;/a&gt; to &lt;a href=&quot;https://www.nongnu.org/geiser/&quot;&gt;Geiser&lt;/a&gt;, the best Emacs Scheme integration
package.  SLY is based on &lt;a href=&quot;https://common-lisp.net/project/slime/&quot;&gt;SLIME&lt;/a&gt; which has &lt;em&gt;decades&lt;/em&gt; of man-years of work behind
it. Geiser is able to support multiple Scheme implementations and it is quite
impressive in this regard. But SLY obviously has much more (e.g. an interactive
debugger). That said, Geiser has nice Guile support, and Guile is in general the
most Common Lisp-y of all Schemes, in fact, it has&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;an imitation of CLOS in the form of &lt;a href=&quot;https://www.gnu.org/software/goops/&quot;&gt;GOOPS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;docstrings and keyword, rest, and optional arguments for function
definitions&lt;/li&gt;
  &lt;li&gt;an interactive REPL and a mutable top-level (unlike many Schemes)&lt;/li&gt;
  &lt;li&gt;a nice module system&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/guile/manual/html_node/Defmacros.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;defmacro&lt;/code&gt;&lt;/a&gt; and exceptions somewhat &lt;a href=&quot;https://www.gnu.org/software/guile/manual/html_node/Raising-and-Handling-Exceptions.html&quot;&gt;similar to Common Lisp restarts &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and some nice things Common Lisp doesn’t have like first-class
continuations. But then again I would use those rarely.&lt;/p&gt;

&lt;h3 id=&quot;when-would-i-pick-one-over-the-other&quot;&gt;When would I pick one over the other?&lt;/h3&gt;

&lt;p&gt;If I were to write an extensible C/C++/Rust program that I &lt;em&gt;know&lt;/em&gt; will need to use
a low-level language, I might do the low level bits using a low level language
and then write the rest in Guile. Guile makes it very easy to spin up a REPL
socket to do something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;myprogram --repl=12345&lt;/code&gt; that you can connect to, and
the interop between C and Guile is fantastic, it has to be, as it’s primarily an
extension language.&lt;/p&gt;

&lt;p&gt;On the other hand, if were to build a wholly standalone application, the choice is
not as obvious. I could do the whole thing in either language. Common Lisp can
build native executables, although their size will be large (who cares?) since
the binary will include the whole Lisp implementation. Guile cannot compile to
native code so you’ll have to write a script executable, but that doesn’t really
matter.&lt;/p&gt;

&lt;p&gt;Scenarios where I would pick Guile:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;when I’m making an extensible program that has to have some C/C++ bits but I
want to make it scriptable by users&lt;/li&gt;
  &lt;li&gt;when I want to write a native binary but not write too much C/C++ code&lt;/li&gt;
  &lt;li&gt;I just want to write Scheme, because Scheme is a bit more elegant&lt;/li&gt;
  &lt;li&gt;the project has something to do with the &lt;a href=&quot;https://www.gnu.org/software/autoconf/&quot;&gt;GNU project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the other hand, Common Lisp makes the most sense if I just want to enjoy a
seriously rapid development experience, a large standard library and language,
and I don’t mind having 50MB binaries (again, who cares?) if I were to write
standalone programs. Guile can’t do that, but it’s easy to either write Guile
scripts or a C program that essentially bootstraps a binary to load a Scheme
runtime. This is how &lt;a href=&quot;http://lilypond.org/&quot;&gt;LilyPond&lt;/a&gt; is written, for example.&lt;/p&gt;

&lt;p&gt;So the answer to which one is decidedly &lt;strong&gt;both&lt;/strong&gt;! Both languages are really fun to
write. At the moment I don’t do Lisp at my day job so it’s all for fun
anyway. If this were for professional purposes, I don’t know. Very often a
strict requirement for professional work is to be able to be productive. In that
regard I think Common Lisp has a significant edge, not only due to its superior
development experience, but its history as a real production language. There are
actual companies doing stuff in Common Lisp. I have not heard of any
professional (in the industrial sense) uses of Guile, notwithstanding that many
projects powered by Guile (Guix, etc.)  are &lt;em&gt;extremely&lt;/em&gt; professional in the way
they are written and maintained. But Common Lisp has &lt;em&gt;more&lt;/em&gt; libraries and
companies behind it.&lt;/p&gt;

&lt;h3 id=&quot;what-about-clojure&quot;&gt;What about Clojure?&lt;/h3&gt;

&lt;p&gt;I’ve actually had the pleasure to use Clojure for personal fun, and a little bit
of professional use. I wrote a couple of libraries (&lt;a href=&quot;https://github.com/ane/vigil&quot;&gt;vigil&lt;/a&gt; and &lt;a href=&quot;https://github.com/ane/task&quot;&gt;task&lt;/a&gt;) and my
experience with has always been positive and its development experience is
excellent. Clojure isn’t a true Lisp, or well, it is part of the &lt;em&gt;Lisp
family&lt;/em&gt;. Its ability to interface with the JVM makes it easy to leverage the
thousands of JVM libraries out there.&lt;/p&gt;

&lt;p&gt;I’d gladly do it again, though I feel that Common Lisp with CLOS and its module
system makes it somewhat easier to practice &lt;a href=&quot;https://en.wikipedia.org/wiki/Programming_in_the_large_and_programming_in_the_small&quot;&gt;&lt;em&gt;programming in the large&lt;/em&gt;&lt;/a&gt;. Clojure
explores interesting territories with &lt;a href=&quot;https://clojure.org/guides/spec&quot;&gt;spec&lt;/a&gt;, so it is interesting to see what
direction the language will take in the future.&lt;/p&gt;

&lt;h3 id=&quot;final-words-emacs-lisp&quot;&gt;Final words: Emacs Lisp&lt;/h3&gt;

&lt;p&gt;There’s also a parenthetical elephant in the room here: Emacs Lisp! An old
descendant of &lt;a href=&quot;https://en.wikipedia.org/wiki/Maclisp&quot;&gt;MacLisp&lt;/a&gt;, it’s actually quite fun to write, and the fact that Emacs
itself is the interpreter, you have superb introspectability for any Elisp
code. Most of the Lisp I write these days is probably Emacs Lisp. It’s very
close to Common Lisp. &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_mono/cl.html#Overview&quot;&gt;cl-lib&lt;/a&gt; adds a sufficient amount of convenience from
Common Lisp to make Elisp writing quite enjoyable. &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_mono/eieio.html#Top&quot;&gt;EIEIO&lt;/a&gt; adds a subset of CLOS
that can be used seamlessly with cl-lib. The condition system is missing.&lt;/p&gt;

&lt;p&gt;I’ve also done a fair bit of &lt;a href=&quot;https://fennel-lang.org/&quot;&gt;Fennel&lt;/a&gt;, a Lisp that compiles to Lua. I used it to
write a &lt;a href=&quot;https://github.com/ane/mudrally&quot;&gt;small game&lt;/a&gt; and it was fun to write since you could develop the game in a
REPL.&lt;/p&gt;

&lt;p&gt;All in all, Lisp in all its variants is the most fun I’ve ever had while
programming a computer. Guile and Common Lisp are definitely the most fun I’ve
had programming in &lt;em&gt;Lisp&lt;/em&gt;.&lt;/p&gt;

        </description>
        <pubDate>Mon, 05 Oct 2020 14:03:41 +0000</pubDate>
        <link>http://ane.iki.fi/2020/10/05/between-two-lisps.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2020/10/05/between-two-lisps.html</guid>
      </item>
    
      <item>
        <title>Back to Rmail</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;While I initially &lt;a href=&quot;/micro/202009041242&quot;&gt;wrote about switching to mu4e&lt;/a&gt;, I was initially
pleased by it, but then I found out about &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/emacs/Rmail.html#Rmail&quot;&gt;Rmail&lt;/a&gt;. &lt;!--break--&gt;Rmail is
kind of like the standard Emacs email reader. &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/gnus/index.html#Top&quot;&gt;Gnus&lt;/a&gt; is pretty
comprehensive in terms of features but I was kind of put off by its
complexity.&lt;/p&gt;

&lt;p&gt;So, eventually, my setup became the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.offlineimap.org/&quot;&gt;offlineimap&lt;/a&gt; to synchronize an IMAP mailbox on my machine&lt;/li&gt;
  &lt;li&gt;Rmail configured using a &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/emacs/Movemail.html#Movemail&quot;&gt;maildir&lt;/a&gt; where offlineimap syncs the data&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/rc0/mairix&quot;&gt;mairix&lt;/a&gt; as the search backend, using the Emacs &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_mono/mairix-el.html&quot;&gt;frontend for mairix&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rmail has surprisingly good automatic &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/emacs/Rmail-Output.html#Rmail-Output&quot;&gt;filing capabilities&lt;/a&gt; so that I
can keep a mostly empty index and things can be manually filed into
separate folders as they appear into the inbox.&lt;/p&gt;

&lt;p&gt;The only gripe I have with it is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mairix-search&lt;/code&gt; works using &lt;a href=&quot;https://en.wikipedia.org/wiki/Mbox&quot;&gt;mbox&lt;/a&gt;
files, i.e. when I search for something, the search produces a mailbox
result (the same file every time), and to view that I have to open
that in Rmail using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rmail-input&lt;/code&gt;. A possible improvement would be to
write an &lt;a href=&quot;https://github.com/abo-abo/swiper&quot;&gt;Ivy&lt;/a&gt; backend that would update results on the fly.&lt;/p&gt;

        </description>
        <pubDate>Wed, 09 Sep 2020 10:55:56 +0000</pubDate>
        <link>http://ane.iki.fi/2020/09/09/rmail.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2020/09/09/rmail.html</guid>
      </item>
    
      <item>
        <title>Inside the machine</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;One of the most interesting aspects of programming is the ability to inspect &lt;em&gt;and
modify&lt;/em&gt; programs while they are running. &lt;!--break--&gt;We all know debuggers, but
there are lots of programs which let you interact with them directly while they
are running. Some programs let you run scripts via embedded interpreters, which
let you extend the program, but in some instances the programs themselves &lt;em&gt;are&lt;/em&gt;
the interpreters.&lt;/p&gt;

&lt;p&gt;The famous story of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Deep_Space_1&quot;&gt;Deep Space 1&lt;/a&gt; probe is an interesting one:&lt;/p&gt;

&lt;blockquote&gt; 
  The Remote Agent software, running on a custom port of Harlequin Common
  Lisp, flew aboard &lt;a href=&quot;http://nmp.jpl.nasa.gov/ds1/&quot;&gt; Deep Space 1&lt;/a&gt;
  (DS1), the first mission of NASA's &lt;a href=&quot;http://nmp.jpl.nasa.gov/index_flash.html&quot;&gt; New Millennium
  program&lt;/a&gt;.  Remote Agent controlled DS1 for two days in May of
  1999.  During that time we were able to debug and fix a race condition
  that had not shown up during ground testing.  (Debugging a program
  running on a $100M piece of hardware that is 100 million miles away is
  an interesting experience.  Having a read-eval-print loop running on the
  spacecraft proved invaluable in finding and fixing the problem.  The &lt;a href=&quot;http://ti.arc.nasa.gov/m/pub-archive/176h/0176%20(Havelund).pdf&quot;&gt;story of the
  Remote Agent bug&lt;/a&gt; is an interesting one in and of itself.)
  &lt;cite class=&quot;text-right d-block mt-1&quot;&gt;
    &amp;mdash; Ron Garret, &lt;a href=&quot;kakka&quot;&gt;Lisping at JPL&lt;/a&gt;, (2002)
  &lt;/cite&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;examples-emacs-stumpwm-nyxt&quot;&gt;Examples: Emacs, StumpWM, Nyxt&lt;/h3&gt;

&lt;p&gt;Famous examples of programs being nothing but interpreters with a function are
the &lt;a href=&quot;https://en.wikipedia.org/wiki/Emacs&quot;&gt;&lt;strong&gt;Emacs&lt;/strong&gt;&lt;/a&gt; family of text editors. Essentially, Emacs itself is a Lisp
interpreter acting as a text editor. You may at any time open a &lt;a href=&quot;https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop&quot;&gt;read-eval-print
loop&lt;/a&gt; inside the editor and actually interact with the program directly.&lt;/p&gt;

&lt;p&gt;For instance, if I open an Emacs Lisp REPL inside GNU Emacs using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x ielm&lt;/code&gt;,
opening and type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(next-buffer)&lt;/code&gt;, I actually end up selecting the next buffer!&lt;/p&gt;

&lt;p&gt;Something similar to this is &lt;a href=&quot;http://stumpwm.github.io/&quot;&gt;&lt;strong&gt;StumpWM&lt;/strong&gt;&lt;/a&gt;, a tiling &lt;a href=&quot;https://www.x.org/wiki/&quot;&gt;X11&lt;/a&gt; &lt;a href=&quot;https://en.wikipedia.org/wiki/X_window_manager&quot;&gt;window manager&lt;/a&gt; that is built
entirely in &lt;a href=&quot;https://lisp-lang.org/&quot;&gt;Common Lisp&lt;/a&gt;. Somewhat similar to Emacs, you can install &lt;a href=&quot;https://www.cliki.net/Swank&quot;&gt;Swank&lt;/a&gt;, a
REPL over a network connection, as an &lt;a href=&quot;http://www.kaashif.co.uk/2015/06/28/hacking-stumpwm-with-common-lisp/index.html&quot;&gt;extension inside StumpWM&lt;/a&gt;, and then you can
connect to the REPL using your client of choice. From there, any function inside
the StumpWM Lisp image is available to you!&lt;/p&gt;

&lt;p&gt;Another program that you can REPL into is &lt;a href=&quot;https://nyxt.atlas.engineer/&quot;&gt;&lt;strong&gt;Nyxt&lt;/strong&gt;&lt;/a&gt;, an extensible web browser built
on WebKit. By running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h s&lt;/code&gt; you can start up a Swank session and then you can
connect to it from, e.g., &lt;a href=&quot;https://common-lisp.net/project/slime/&quot;&gt;SLIME&lt;/a&gt;. Nyxt itself is written in Common Lisp, so
offering REPLability via Swank is pretty much a no-brainer. I’ve only tried Nyxt
very briefly, but from what I’ve seen it’s pretty interesting!&lt;/p&gt;

&lt;p&gt;I actually tried something similar years ago with Common Lisp, it turned out to
be super simple. I was building a Lisp-customizable &lt;a href=&quot;https://i3wm.org/i3status/&quot;&gt;i3 status bar&lt;/a&gt; program (I
ended up &lt;a href=&quot;https://github.com/ane/tila&quot;&gt;writing it&lt;/a&gt; writing it in &lt;a href=&quot;https://www.call-cc.org/&quot;&gt;CHICKEN Scheme&lt;/a&gt;, though). Turns it didn’t
require much: Swank is available via &lt;a href=&quot;https://www.quicklisp.org/beta/&quot;&gt;Quicklisp&lt;/a&gt;, so you can just add it to your
Common Lisp program and voilà, you have a REPL connection available. I &lt;a href=&quot;https://shell.wilan.org/~ane/repl_live.webm&quot;&gt;recorded
the thing in action&lt;/a&gt; via video to
demonstrate how simple and powerful this concept is.&lt;/p&gt;

&lt;p&gt;These days I work with a multitude of application platforms and the &lt;a href=&quot;https://en.wikipedia.org/wiki/Java_virtual_machine&quot;&gt;Java Virtual
Machine&lt;/a&gt; is one of them. Java has powerful introspectability, from its native
debugger support to protocols like &lt;a href=&quot;https://www.oracle.com/java/technologies/javase/javamanagement.html&quot;&gt;JMX&lt;/a&gt; and even the more modern (and seriously
amazing!) &lt;a href=&quot;https://docs.oracle.com/javacomponents/jmc-5-4/jfr-runtime-guide/about.htm&quot;&gt;Java Flight
Recorder&lt;/a&gt;.
I’ve actually been able to find bugs using JMX, a web server was routinely
freezing during high traffic hours – but only for 0.5% of the requests or so,
still, this (barely) under the &lt;a href=&quot;https://en.wikipedia.org/wiki/Service-level_agreement&quot;&gt;SLA&lt;/a&gt; we had for the service. Turns out there was a
thread starvation issue: when traffic was sufficiently large, other background
processes were exhausting the thread pool reserved for incoming connections,
causing the web server to not be able to receive incoming connections for a
short period of time. Long story short, I found these incidents via JMX, and was
able to pinpoint the issue. The fix was to use separate thread pools for the web
server HTTP traffic and then background I/O.&lt;/p&gt;

&lt;p&gt;Of course the Java Virtual Machine is not a Lisp interpreter, far from it, but
it offers things that are &lt;em&gt;similar&lt;/em&gt;. Hot code swapping, dynamic class reloading,
etc. make it quite a powerful platform in terms of introspectability. But it’s a
far cry from being a Lisp interpreter and a text editor, or a window manager, or
a web browser.&lt;/p&gt;

&lt;h3 id=&quot;blazing-fast-development-cycles&quot;&gt;Blazing fast development cycles&lt;/h3&gt;

&lt;p&gt;I think there is a crucial difference between allowing extensibility via scripts
(or &lt;em&gt;plugins&lt;/em&gt;) and the ability to actually interact completely via a live
process. The former usually does not offer total control over the program, the
latter offers total control over the process, because the interpreter &lt;em&gt;is&lt;/em&gt; the
program.&lt;/p&gt;

&lt;p&gt;There is something admittedly fascinating about programs being, in a certain
manner of speaking, living things. Not only does it give you a feeling of
control, but it’s even more personal: you’re not just using the program, you’re
inside it.&lt;/p&gt;

&lt;p&gt;Having tried Clojure and Figwheel where you can directly REPL into your browser,
the speed of development if you’re building some application while it’s running
is quite something. I’ve also tried &lt;a href=&quot;http://fennel-lang.org/&quot;&gt;Fennel&lt;/a&gt;, a Lisp that compiles to &lt;a href=&quot;https://www.google.com/search?client=firefox-b-d&amp;amp;q=lua&quot;&gt;Lua&lt;/a&gt;, using
the &lt;a href=&quot;https://love2d.org/&quot;&gt;LÖVE&lt;/a&gt; game engine using a Fennel REPL &lt;a href=&quot;https://gitlab.com/alexjgriffith/min-love2d-fennel&quot;&gt;connected directly into the LÖVE game
engine&lt;/a&gt;. The result is quite &lt;a href=&quot;https://github.com/ane/mudrally&quot;&gt;unfinished&lt;/a&gt; but the speed of development was
astounding – I could change the game physics on the fly just by evaluating Lisp
expressions in Emacs and the game would change instantly!&lt;/p&gt;

&lt;p&gt;If I’m ever after building some sort of hyper-customizable program I will
definitely try building it around a Lisp interpreter, possibly using Common
Lisp.&lt;/p&gt;

        </description>
        <pubDate>Thu, 03 Sep 2020 06:34:03 +0000</pubDate>
        <link>http://ane.iki.fi/2020/09/03/inside-the-machine.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2020/09/03/inside-the-machine.html</guid>
      </item>
    
      <item>
        <title>Winding down</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;I find it curious I can get paid for programming and still practise programming
in my spare time and it feels like fun. It doesn’t stress or tire me at all.
Superficially,  the line between what is work and what is fun is not that
obvious. I’m at a computer, bashing its keys, programming it to do what I want.
Of course, at work I program the computer to do different things, but you’d have
to know what my job entails to know the difference.&lt;/p&gt;

&lt;p&gt;I doubt it is possible to enjoy work so much that your &lt;em&gt;work&lt;/em&gt; is relaxing, to
the extent that it &lt;em&gt;alone&lt;/em&gt; can guarantee a means for winding down. In that case,
one’s work would be so fulfilling and relaxing that it one is calmed by it. This
is not impossible. It is just unlikely.&lt;/p&gt;

&lt;p&gt;How does one recognize when you enjoy work or when you enjoy nothing &lt;em&gt;but&lt;/em&gt; work?
Suppose one eats properly, sleeps properly, and then works all the rest of the
time. To me, a common observation for which I offer no scientific basis, is that
this is &lt;em&gt;still too much&lt;/em&gt;. The brain can’t cope with continuous stimulation, and
eventually such a person will either burn out, lose interest, or suffer from
some other crash, and end their ability to perform in a job.&lt;/p&gt;

&lt;p&gt;The crash comes sometimes from within, sometimes from outside. Families and
friends – if you have any – will probably notice before too long that you
might be working too much. But a person so engrossed in their passion can
sometimes ignore their environment, and power on. Then at some point, their
passion crashes. The stack overflows, and everything grinds to a halt.&lt;/p&gt;

&lt;p&gt;I’ve been playing with computers for as long as I remember. I began programming
at an early age or so, at the age of six, I think. Eventually what was just for
fun became not just for fun, I turned my hobby into a profession. I doubt I am
unique in this in our field, I know many have started their careers before they
were — careers. Many also convert to our profession from other fields by
learning the basics in their spare time.&lt;/p&gt;

&lt;p&gt;I still program for fun. Occasionally, intermittently, whenever, I don’t keep a
stable routine. And I don’t necessarily do anything meaningful. I play with new
languages, new technologies, experiment with something vaguely work-related, but
in general the striking difference between the programming-as-a-job and
programming-as-a-hobby are that in hobby projects I don’t have&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;deadlines,&lt;/li&gt;
  &lt;li&gt;commitments,&lt;/li&gt;
  &lt;li&gt;schedules,&lt;/li&gt;
  &lt;li&gt;requirements, and&lt;/li&gt;
  &lt;li&gt;any pressure to achieve anything meaningful.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From that it is glaringly obvious what makes a hobby a hobby and a job a job.
You might enjoy your job, but eventually come to realize that you’re obviously
not there voluntarily, you have outside commitments, and you are bound to
schedules and deadlines. Essentially, fun has fewer rules than work.&lt;/p&gt;

&lt;p&gt;This is subjective, however. For some, the &lt;em&gt;absence&lt;/em&gt; of such rules is stressful.
They might enjoy a structured hobby: learning a new language with a
predetermined schedule, follow a training routine to become a better runner,
lift weights using a personalized program. So what &lt;em&gt;work&lt;/em&gt; is for some
is not work to others.&lt;/p&gt;

&lt;p&gt;But for me it’s not just computers. I spend time with my wife and our baby
daughter, I exercise, I read, cook, play music, whatever. There are many ways
for me to wind down. But funnily enough, if someone asks me to list what I do
for fun, I can include something that’s very close to my work. This is a common
theme in creative professions. Musicians play music for fun, athletes also
exercise for fun, graphic designers draw in their spare time, and so on.&lt;/p&gt;

&lt;p&gt;A sport, although a hobby, can be stressful. Some years ago I was &lt;em&gt;very&lt;/em&gt; into
road cycling. I had a rigorous training schedule and was actively considering
doing some competition. Before long, I realized I had only room for one rigorous
schedule in my head. It was either work or something else. I chose work. Cycling
had to be a hobby for me to enjoy it, not something serious. But before I could
stop it, I crashed. I completely lost interest in road cycling because it felt
&lt;em&gt;too much like work&lt;/em&gt;. The distance I have cycled in road since can be counted
with a three-digit number. This excludes commuting to work, naturally.&lt;/p&gt;

&lt;p&gt;The weird part is that going I &lt;em&gt;knew&lt;/em&gt; I didn’t enjoy having a strict structure
in my spare time activities. I had figured this out a long time ago, when I was
a teenager. Yet, I created a strict structure for a hobby. I lost interest.
Perhaps I thought having grown older had given me the ability to manage this
structure in such a way it didn’t feel overpowering. It hadn’t.&lt;/p&gt;

&lt;p&gt;There is a sweet spot in this. I can find a hobby in which I have &lt;em&gt;some&lt;/em&gt;
structure but not too much. I’ve been going to the gym for a decade. For that,
I’ve found going 2-3 times a week is the sweet spot in which I can keep myself
in shape and see continuous improvement, with emphasis in the former. Any gains
are just rewards, but not the ultimate objective. I suppose in weightlifting the
ultimate objective for me is the physical health improvement. Whether I can add
kilograms to my squat is not that interesting in the long run, though I strive
to maintain an upward trend. Again, the same patterns emerge: I have no real
schedule, no requirements, no commitments.&lt;/p&gt;

&lt;p&gt;I guess, for me, personally, the absences of schedules, requirements and
commitments is what defines &lt;em&gt;fun&lt;/em&gt; for me. But this is just me. A colleague of
mine trains in trail running rigorously, with strict schedules and diets. He
said the structure helps him relax, because he has a fix point to follow in his
spare time. Perhaps one of the strangest discoveries of myself was that a
character trait like this ran very deeply. It is pervasive, it affects me in all
areas. When travelling for fun, I ask my wife that we do not commit to a serious
structure or schedule. We can visit that interesting cultural site, yes, and see
that other place, but if you gave me a calendar with meticulously planned daily
objectives and places to visit, I would rather stay home.&lt;/p&gt;

&lt;p&gt;Some structure in non-work life is inevitable, and more often than not,
necessary. Some hobbies require structure, things like choir practise, group
sports, dinner with friends occur usually at  fixed times. Family life and all
it entails requires structure, and so do many aspects of one’s personal life.
It’s not a bad thing. But the amount of structure is much smaller than in
professional environments.&lt;/p&gt;

&lt;p&gt;At the same time, my work is very structured. I organize my work into a to-do
list and try to minimize ad-hoc work, instead knowing in advance what I should
do the next day. That way I don’t have to think in the previous evening or night
what I should do the next day. I get to work, open up the to-do list, and start
from there. Of course, with meetings and collegial chats I can’t follow the list
to the letter, and this to-do list is not the absolute authority, rather, it is
a &lt;em&gt;foundation&lt;/em&gt;. With this foundation, I never have to spend time wondering what I
should do next. And this is just &lt;em&gt;my&lt;/em&gt; work, my calendar is filled with meetings
of various sorts. A big part of my job is figuring out the structure of &lt;em&gt;other
people’s&lt;/em&gt; work.&lt;/p&gt;

&lt;p&gt;Knowing what is work and what isn’t makes it very easy for me to keep a good
work and life balance. Maintaining that balance is extremely important to me. It
is the single most important goal in my professional life to maintain this
balance. That way, I can avoid stress and burning out, and enjoy being
&lt;em&gt;employed&lt;/em&gt; until I’m old. It’s not that I feel I have a duty to enjoy my job, or
that enjoying working is somehow a goal in itself, it’s that I don’t want &lt;em&gt;not&lt;/em&gt;
to enjoy working.&lt;/p&gt;

&lt;p&gt;I am incredibly privileged to have had turned my hobby into a profession.
Sometimes work is so much fun it literally feels like I get paid to have fun. I
am extremely aware that this is rare. Most of humanity considers work to be,
well, work. We spend a significant portion of our days, of our lives, doing
things we’d rather not do, in order to provide for ourselves.&lt;/p&gt;

&lt;p&gt;I don’t think it’s possible for everyone everywhere to enjoy working, or rather,
enjoy their job. It would be naive to think otherwise. Most of humanity is
employed because they have to be. They are forced into jobs they had no choice
in, they work in conditions they can’t control. Similarly, I don’t think it’s
even possible for the majority to even enjoy being good at what they do, because
for many even the ability to even enjoy a job is such an alien concept.&lt;/p&gt;

&lt;p&gt;Even to those like me, who &lt;em&gt;had&lt;/em&gt; a choice, I don’t think thoroughly enjoying
one’s work is a worthy goal. To me, it’s not a measure of success whether you’re
passionate about your job. You don’t need to enjoy your work to be a successful
person. In fact, it is very common to be rather neutral about it. I think it is
a good objective to not &lt;em&gt;not&lt;/em&gt; enjoy your work, rather than to enjoy it. That is,
being somewhat neutral, with a slight bias towards the positive, is probably the
optimal position. You don’t &lt;em&gt;hate&lt;/em&gt; what you do and you don’t &lt;em&gt;love&lt;/em&gt; it too much
in order to maintain a balance with your other life.&lt;/p&gt;

&lt;p&gt;In fact, for me, a measurement of success is how healthy one’s relationship to
work is. Fundamentally, work is service. You can serve whomever, even yourself,
but should life be service? Maybe work is just some necessary evil we all do to
survive? Work is what you do to &lt;em&gt;fund&lt;/em&gt; the fun parts of your life. At the end of
the day, we all go home, back to our families, friends, and hobbies. Work is
transient like that.&lt;/p&gt;

&lt;p&gt;Yet, I believe most of us would work even if not forced to. I think humans have
an innate need to be useful, to have a purpose. That quest for purpose can be
satisfied in many ways, work being one of them. I doubt many of us would work
like we currently do, but it would be some sort of service to some entity. But
it would be different. It wouldn’t be your average 40 hours a week five days a
week. It could be more, it could be less, but I believe the terms on how we do
it would be different.&lt;/p&gt;

&lt;p&gt;So work is, well, work. It’s not always about what you do, it’s sometimes also
the how. An artist could characterize work as the drawing they do primarily for
someone else. Some other artist’s characterization might be different. There are
most likely as many people as there are characterizations of work.&lt;/p&gt;

&lt;p&gt;I’m happy that I have been able to understand what the difference is for me.
What lets me enjoy programming in my spare time is that I keep it fun. I don’t
do it rigorously, I don’t do it for someone else. Hobby programming is fun
because it doesn’t feel like work. Yet, it’s sometimes &lt;em&gt;very&lt;/em&gt; close to what I do
at work. Most of the time it’s something completely different – embedded stuff,
games, interpreters for toy programming languages, and so on. I suppose I could
even pull off doing work-related stuff. It’s not the &lt;em&gt;what&lt;/em&gt;, but the &lt;em&gt;how&lt;/em&gt;.&lt;/p&gt;

        </description>
        <pubDate>Sat, 07 Mar 2020 00:00:00 +0000</pubDate>
        <link>http://ane.iki.fi/2020/03/07/winding-down.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2020/03/07/winding-down.html</guid>
      </item>
    
      <item>
        <title>Embedded Rust and WiFi</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;Earlier this year, in May or so, I started having fun with hobby electronics,
and ended up playing around with Rust in embedded devices, microcontrollers and
the like. Actually it’s the other way around, I first wanted to write some Rust,
and found out that Rust has a thriving embedded ecosystem, and proceeded to buy
some microcontroller dev boards (and upgrading my “lab” equipment from 2003),
and started writing Rust on them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It’s fun!&lt;/strong&gt; The last time I did any embedded was in 2003, when I was 15 or so,
and things were &lt;em&gt;way&lt;/em&gt; different back then. The affordable microcontrollers were
8-bit turds like PIC8, and the hot stuff was AVR. C was the only language that
was around and information on the net was scarce. Then, Arduino happened, and
things started improving.&lt;/p&gt;

&lt;p&gt;Now in 2019, sixteen years later, things are &lt;em&gt;much&lt;/em&gt; easier. &lt;a href=&quot;https://circuitpython.org/&quot;&gt;You can program
MCUs in Python!&lt;/a&gt; Clock speeds run in the hundreds of MHz and there are tens
of kilobytes of RAM. The internet is full of tutorials.&lt;/p&gt;

&lt;p&gt;Rust, given its nice high-level abstractions and package management, has &lt;a href=&quot;https://github.com/rust-embedded/awesome-embedded-rust&quot;&gt;an
amazing embedded ecosystem&lt;/a&gt;. All you need is their build tool and GDB with
ARM support. Using a HAL is actually a real abstraction: implement a single HAL
API, like &lt;a href=&quot;https://docs.rs/embedded-hal/0.2.3/embedded_hal/blocking/i2c/index.html&quot;&gt;I&lt;sup&gt;2&lt;/sup&gt;C&lt;/a&gt;, and your device is usable by anyone. As of
writing some things are still missing from the Rust HAL library, like USB and
CAN support, but it’s slowly building up.&lt;/p&gt;

&lt;p&gt;Anyway, WiFi. Wireless connectivity on a little microcontroller is an extremely
nice way of getting your toy device on the internet. Most likely the most
popular WiFi microcontroller devboard is the ESP32, which costs about 10 EUR. If
you want to write Rust on this thing though, there are problems: the ESP32 is
using a Xtensa LX6 processor, which doesn’t (yet) have mainline LLVM support,
you’ll have to use C or CircuitPython.&lt;/p&gt;

&lt;figure class=&quot;w-25 ml-3 float-sm-right&quot;&gt;
  &lt;img src=&quot;/images/esp32_wroom.jpg&quot; alt=&quot;ESP32-WROOM-32&quot; /&gt;
  &lt;figcaption&gt;ESP32-WROOM-32&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Fine, if your goal is to get something &lt;em&gt;working&lt;/em&gt;, it’s probably not a good idea
to use Rust for WiFi enabled toy devices. But if you want to do something &lt;em&gt;fun&lt;/em&gt;,
doing this with Rust is a &lt;strong&gt;great&lt;/strong&gt; idea!&lt;/p&gt;

&lt;p&gt;So how to get WiFi working with embedded Rust? The answer is simple: use a
microcontroller where you &lt;em&gt;can&lt;/em&gt; use Rust and a WiFi &lt;em&gt;coprocessor&lt;/em&gt;, where one
microcontroller runs your Rust program and the WiFi coprocessor runs its custom
firmware which has WiFi support. The firmware has its own TCP stack so the
interface between the two processor is fairly high-level, at the level of
“here’s a password, connect to this network”. The two microcontrollers would use
SPI or some other interface to talk to each other and transfer data.&lt;/p&gt;

&lt;p&gt;So you need a microcontroller with WiFi support and a firmware to boot! Turns
out there are a few good choices: the &lt;a href=&quot;https://www.google.com/search?client=firefox-b-d&amp;amp;q=esp-wroom32&quot;&gt;ESP-WROOM32&lt;/a&gt; from Espressif running
the &lt;a href=&quot;https://www.google.com/search?client=firefox-b-d&amp;amp;q=esp-wroom32&quot;&gt;Adafruit NINA-W102&lt;/a&gt; firmware or &lt;a href=&quot;https://www.microchip.com/wwwproducts/en/ATwinc1500&quot;&gt;ATWINC1500&lt;/a&gt; from Microchip running
its own firmware. The nice thing about the Adafruit firmware is that there’s a
&lt;a href=&quot;https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI&quot;&gt;CircuitPython implementation with SPI&lt;/a&gt;, so reimplementing this in Rust looks
to be straightforward. The ATWINC1500 libraries are hidden somewhere in Atmel
Studio so I’m not going to dig that out just yet!&lt;/p&gt;

&lt;figure class=&quot;figure float-sm-right w-25 ml-3&quot;&gt;
  &lt;img src=&quot;/images/airlift_breakout.jpg&quot; alt=&quot;The ESP32-WROOM-32 is also available as a breakout with SPI support from &amp;lt;a
href=&amp;quot;https://www.adafruit.com/product/4201&amp;quot;&amp;gt;Adafruit&amp;lt;/a&amp;gt;&quot; /&gt;
  &lt;figcaption&gt;The ESP32-WROOM-32 is also available as a breakout with SPI support from &lt;a
href=&quot;https://www.adafruit.com/product/4201&quot;&gt;Adafruit&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The alternative would be to build WiFi support yourself on some microcontroller
that has WiFi. With the ESP32 being badly supported by LLVM and thus Rust, the
other option is ATWINC1500 which is built on the Cortus APS3, building Rust for
that is another here-be-dragons I’d rather not explore. Lastly, there’s the
&lt;a href=&quot;https://www.acalbfi.com/be/IoT-and-Wireless/WiFi-802-11/p/WiFi-IoT-Module--IEEE-802-11-b-g-n/0000008OKP&quot;&gt;WM-N-BM-09&lt;/a&gt; from USI that is a STM32F205RG paired with a Broadcom 43362 WiFi
module. This is available in the &lt;a href=&quot;https://www.adafruit.com/product/3056&quot;&gt;Adafruit WICED Feather&lt;/a&gt; and the &lt;a href=&quot;https://docs.particle.io/photon/&quot;&gt;Particle
Photon&lt;/a&gt;. With STM32 being widely supported in embedded Rust, it should be
possible to write a WiFi program on such a microcontroller. Then there’s the
&lt;a href=&quot;https://www.u-blox.com/en/product/nina-w10-series&quot;&gt;u-blox NINA W102&lt;/a&gt; which is another ESP32 based WiFi microcontroller, used in
various &lt;a href=&quot;https://store.arduino.cc/arduino-wifi-shield&quot;&gt;Arduino WiFi products&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That said, building a WiFi “firmware” in Rust is quite a Herculean task, though
not impossible! You essentially need a functioning TCP/IP stack and implement a
WiFi layer on top. That would be possible with &lt;a href=&quot;https://www.googlpe.com/search?client=firefox-b-d&amp;amp;q=smoltcp&quot;&gt;smoltcp&lt;/a&gt;, a Rust TCP/IP stack
suitable for embedded devices.&lt;/p&gt;

&lt;p&gt;However, for the time being, I think I will stick with using ESP32-WROOM or
ATWINC1500 with preloaded WiFi ready firmware. Here’s a comparison table of the
different WiFi microcontrollers I found:&lt;/p&gt;

&lt;table class=&quot;table table-bordered table-sm&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Microcontroller&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Architecture&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;“Coprocessor” firmware&lt;/th&gt;
      &lt;th&gt;Interface&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Free SDK/library&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ESP-WROOM32&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Xtensa LX6&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Several&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;
      &lt;td&gt;SPI&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;WiFiSpi (C), Adafruit CircuitPython&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;u-blox W102&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Xtensa LX6&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Several&lt;/td&gt;
      &lt;td&gt;SPI&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;em&gt;ditto&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ATWINC1500&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Cortus APS3S&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Yes, proprietary&lt;/td&gt;
      &lt;td&gt;SPI, UART&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Arduino WiFi101 (C)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;WM-N-BM-09&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;ARM (STM32F205)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Several&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;
      &lt;td&gt;SPI&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Several&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;figure class=&quot;float-sm-right w-25 ml-3&quot;&gt;
  &lt;img src=&quot;/images/atwinc1500.jpg&quot; alt=&quot;There's also a breakout for the ATWINC1500.&quot; /&gt;
  &lt;figcaption&gt;There's also a breakout for the ATWINC1500.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Based on the chart I would go either with the ESP32-WROOM-32 or the
ATWINC1500. The ESP32-WROOM-32 is both cheaper and easier to develop for compared
to the ATWINC1500, but the ATWINC1500 seems to be a bit more performant and
reliable.&lt;/p&gt;

&lt;p&gt;Anyway, this led me to choose ESP32-WROOM-32 as the WiFi “coprocessor”. What’s
next is writing a Rust library that can control the ESP32 over SPI. This should
be fairly straightforward, since I can essentially reimplement the &lt;a href=&quot;https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI&quot;&gt;Adafruit
CircuitPython ESP32-SPI driver&lt;/a&gt; in Rust. That’s going to be fun! First I’ll
need a development board, I’ll most likely use the &lt;a href=&quot;https://www.adafruit.com/product/4285&quot;&gt;Adafruit AirLift Shield&lt;/a&gt;
on top of a &lt;a href=&quot;https://www.adafruit.com/product/3505&quot;&gt;Adafruit Metro M0&lt;/a&gt;. Why the Metro M0? Well, it has a JTAG header
so I can use SWD to debug what’s going on, instead of repeatedly flashing the
binary to the bootloader.&lt;/p&gt;

&lt;p&gt;Once I have the board, the next step is to build the SPI interface and some sort
of socket abstraction that works over the SPI interface. Seems like there is no
&lt;a href=&quot;https://github.com/rust-embedded/embedded-hal/issues/146&quot;&gt;real abstraction for sockets&lt;/a&gt;, and there’s
no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#![no_std]&lt;/code&gt; library for things like HTTP let alone MQTT… this is going to
be interesting!&lt;/p&gt;

&lt;p&gt;To put it simply, the Rust embedded ecosystem isn’t super mature yet. It’s
getting there. That’s not a problem, if I really need to get my toy device (like
a temperature sensor over WiFi), I can write the necessary Python/Arduino C++ in
a few hours, and I have something that works. But a large part of my resurgent
hobby electronics adventures is being able to write Rust in bare-metal
systems. The breadboarding and soldering parts are fun as well, but my main
interest is in programming. Anyway, this looks like a pleasant challenge!&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;There’s &lt;a href=&quot;https://github.com/arduino/nina-fw&quot;&gt;Arduino NINA&lt;/a&gt; (&lt;a href=&quot;https://github.com/adafruit/arduino-esp32&quot;&gt;Adafruit’s
fork for ESP32-WROOM-32&lt;/a&gt;),
&lt;a href=&quot;https://nodemcu.readthedocs.io/en/master/&quot;&gt;NodeMCU&lt;/a&gt; and so on. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Depends on the vendor, Adafruit is based on 
&lt;a href=&quot;https://www.digikey.com/en/resources/wiced-iot-platform&quot;&gt;Cypress WICED&lt;/a&gt;
which is proprietary, but the Particle Photon uses FreeRTOS. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;

        </description>
        <pubDate>Wed, 20 Nov 2019 00:00:00 +0000</pubDate>
        <link>http://ane.iki.fi/2019/11/20/embedded-rust-wifi.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2019/11/20/embedded-rust-wifi.html</guid>
      </item>
    
      <item>
        <title>Useless interfaces</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;A feature that often frustrates me in object-oriented code is the prevalence of useless
interfaces. Interface isn’t meant literally here: this applies to traits of Rust/Scala and protocols
of Clojure as well.
&lt;!--break--&gt;&lt;/p&gt;

&lt;p&gt;The advice of &lt;em&gt;planning for the interface&lt;/em&gt; is just and solid, but people tend to follow this tip to
the extreme. It is not uncommon to see people design a module or class by defining its interface
first, with an actual implementation following later.&lt;/p&gt;

&lt;p&gt;One eagerly designs an interface as follows:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mediator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;validate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;postpone&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Postponed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;frobnicate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Frobnicated&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, the implementation, in a class called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MainMediator&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DefaultMediator&lt;/code&gt;, in a separate
directory, implements the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mediator&lt;/code&gt; interface:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MediatorImpl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mediator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;validate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;postpone&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Postponed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;frobnicate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Frobnicated&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dependents of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mediator&lt;/code&gt; trait then naturally get their dependency provided with a constructor
argument:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Resequencer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Mediator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Clock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;resequence&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Postponed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;postpone&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;randomDelay&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mediator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Clock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This pattern is older than the sun, and has been a characteristic of modern, inheritance-based
object-oriented programming for ages. Fundamentally, it is alright to separate implementation from
specification, but where it goes wrong is the &lt;em&gt;overuse&lt;/em&gt; of this paradigm, or when this separation is
superfluous.&lt;/p&gt;

&lt;p&gt;This separation is superfluous when it serves no purpose. You could as well call it dependency
injection on the toilet. There is no fundamental reason why a class or module like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mediator&lt;/code&gt;
warrants an interface &lt;em&gt;when it is likely that there will never be an alternative implementation&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;At a glance, Guy Steele’s influential &lt;em&gt;plan for growth&lt;/em&gt; idea from his “Growing a Language” talk
seems to contradict what I just said. Shouldn’t defining an interface help us plan for future,
alternative implementations of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mediator&lt;/code&gt;? Perhaps a different kind of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mediator&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Removing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mediator&lt;/code&gt; trait and simply renaming its only implementation will still keep the code
working, with the benefit that there are fewer lines of code now, and it isn’t any harder to extend.&lt;/p&gt;

&lt;p&gt;This is actually more in line with Steele’s idea. It doesn’t say anywhere a trait or interface
cannot be &lt;em&gt;distilled&lt;/em&gt; from a set of basic implementations. In other words, when our intuition says
to &lt;em&gt;prepare&lt;/em&gt; for repetition, we should &lt;em&gt;identify&lt;/em&gt; them. The Gang of Four book was never a
recipe book for building great programs. It was a catalog! They observed several kinds of
large-scale systems and programs and extracted repetetive behaviours in the code, patterns. They
never said that to do things right, one ought to use the visitor pattern, or this other pattern,
otherwise your programs will be bad.&lt;/p&gt;

&lt;p&gt;Back to interface distillation. Programming is about getting rid of repetition. The more experienced
the programmer, the better they get at noticing patterns of repetition. The downside is that this
may also lead to overengineering for repetition.&lt;/p&gt;

&lt;p&gt;So, an experienced programmer thinks, this behaviour I have specificed may be repetitive, let me
&lt;em&gt;first&lt;/em&gt; create a construct that lets me share the repetition (an interface), and then proceed with
the implementation. This is fine if the actual code is known to be repeated, but by seeing
interfaces as a hammer and every bit of code as a nail, you will soon bury yourself in pointless
dependency injection scenarios.&lt;/p&gt;

&lt;p&gt;It may be just as easy to first create a base implementation and once you must duplicate its
behaviour, only &lt;em&gt;then&lt;/em&gt; create the abstract implementation. You might actually need to spend &lt;em&gt;less&lt;/em&gt;
total time wiring up the interface, since you observed the repetition. Creating an abstract
implementation first always involves a deal of speculation and this is not reliable.&lt;/p&gt;

&lt;p&gt;The more experienced programmer understands that you don’t always need to plan for repetition. In
fact, repetition is good sometimes. Not every shared functionality needs to be extracted to its own
module, because sometimes, shared dependencies will be bad.&lt;/p&gt;

&lt;p&gt;The approach I suggest is to in order to produce modularity as a side effect, structure your program
into small, reusable pieces. Don’t create huge, monolithic interfaces. Functional programming shows
us that dependency injection can be done just by passing a function.&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;postponer&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Postponed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;delayer&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;resequence&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Postponed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;postponer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;delayer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mediator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Clock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;postpone&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;randomDelay&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;One sees that a higher-order function like the above can be just as well represented by a trait with
a single method. If you only need that method, you should depend only on that. With a structural
type system it is easy to decompose types. An alternative is to stack traits, and in languages like
Scala this is fairly easy. You could as well decompose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mediator&lt;/code&gt; into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Validator&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Postponer&lt;/code&gt;, et
cetera, ideally interfaces should be fairly homogenous in their purpose: if your interface defines
methods for reading, keep that interface separate from the writing interface, and if you need read
and write just compose the interfaces together, and so on.&lt;/p&gt;

&lt;p&gt;It also helps if your language is powerful enough to do without excessive DI – the reason why
horrors like Spring exist is that Java simply wasn’t expressive enough to do dependency injection
the traditional way without setting your hair on fire. That, and for some odd reason, people thought
writing constructor arguments was so painful it warranted a gigantic framework for it.&lt;/p&gt;

&lt;p&gt;Overall, it’s usually a good idea to toy around first with the concrete, and then extract the
abstraction. Going the other way around is a dangerous swamp. It’s certainly something I’ve used to
do – overengineer for patterns &lt;em&gt;a priori&lt;/em&gt; – but I found better results by getting my hands dirty,
by writing repetitive code first and then cleaning it up.&lt;/p&gt;

        </description>
        <pubDate>Thu, 23 Mar 2017 00:00:00 +0000</pubDate>
        <link>http://ane.iki.fi/2017/03/23/useless-interfaces.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2017/03/23/useless-interfaces.html</guid>
      </item>
    
      <item>
        <title>Implicit power</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;Scala gets lots of flak for implicits. Some of the feedback is justified: implicits in Scala can be
quite intimidating or confusing for beginners. That does not justify their dismissal, as implicits,
in all of their flavours, when used correctly, can be actually quite simple and powerful.&lt;/p&gt;

&lt;p&gt;I recently had to do a refactoring for large program. The codebase was old, and wasn’t designed to
cope with the sort of change I was going to introduce, and I didn’t have much time either. Pressed
for time, but compelled by a modicum of professional pride, I didn’t want to half-ass the task by
adding jury-rigged solutions that would have left me feeling dirty and empty inside, at worst,
leaving a rotting mess to future developers—me.
&lt;!--break--&gt;
The codebase itself was simple, but large. Its task was more or less to serve as a REST API in front
of a high-availability, fast database (Cassandra). One part of the program provided abstractions
called &lt;em&gt;collections&lt;/em&gt; of database tables. Each collection had a set of methods (such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get&lt;/code&gt;) that
were then translated to a database query to fetch &lt;em&gt;entities&lt;/em&gt;. An entity is a piece of data
encapsulating some value. Using a fictional and simplified example of an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bork&lt;/code&gt; from a database:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Bork&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ZonedDateTime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;frobnicate&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Decimal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Borks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// find a bork by id&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;by&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bork&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// ... in another place, another module&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BorksImpl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Borks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;by&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bork&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// fetch by UUID from the database&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Each collection trait was implemented by a real class (like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RealEntries&lt;/code&gt;), hiding database logic
behind a concrete implementation. Other parts of the program accessed these entities via the
collection trait, like the API front here:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;borks&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Borks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// spray dsl&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;pathNamespace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;borks&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IntNumber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;complete&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;borks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;toJson&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The database in question was Cassandra, in which this &lt;em&gt;database&lt;/em&gt; abstraction doesn’t really exist,
as databases in Cassandra are actually just prefixes called &lt;em&gt;keyspaces&lt;/em&gt; that map to physical
directories on the disk. These keyspaces have some properties that separate one keyspace from
another, but the point is that they are unlike traditional SQL databases: you need not &lt;em&gt;connect&lt;/em&gt; to
a database, you can simply switch your query for the table &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt;, in keyspace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt;, by
switching &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A.Foo&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B.Foo&lt;/code&gt;. So, in Cassandra, these keyspaces are opaque and you can simply choose
the appropriate keyspace with the right namespace in the table name part of the query.&lt;/p&gt;

&lt;p&gt;The task was to support multiple, concurrent databases of entries. Previously, this program operated as a
monolith, i.e. there was ever only &lt;em&gt;one&lt;/em&gt; database it was operating on. Support was needed for
concurrent access to several (possibly non-finite) databases, and the support had to come quickly.&lt;/p&gt;

&lt;p&gt;Turns out the simple solution – instantiate one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BorksImpl&lt;/code&gt; for each keyspace – was not available,
as there could be entities in one &lt;em&gt;shared&lt;/em&gt; keyspace mapping to other keyspaces. So, one collection
like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BorksImpl&lt;/code&gt; needed to know which keyspaces it was supposed to query, because this information
is unavailable to the caller.&lt;/p&gt;

&lt;p&gt;A way around the splitting and namespacing was consolidation, but this introduced security
problems. We couldn’t simply consolidate all the entries into the same database, as we had access
limitations – callers of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get&lt;/code&gt; acting on keyspace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt; were not allowed to see the data in
keyspace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bar&lt;/code&gt;. This justified the creation of a split by keyspace, isolating data for the purposes
of permission control. This also destroyed the possibility of the above solution, i.e., instantiate
one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BorksImpl&lt;/code&gt; for each keyspace, because &lt;em&gt;one&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BorksImpl&lt;/code&gt; might have needed to query for data
from many keyspaces.&lt;/p&gt;

&lt;p&gt;So, a request with an id &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;123&lt;/code&gt; comes in at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/borks/123&lt;/code&gt;, the application uses the central lookup
table to find the target keyspace. The initial implementation looked like this.&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Borks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// find a bork by id&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;by&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bork&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// ... in another place, another module&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BorksImpl&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Borks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;by&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bork&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// fetch by UUID from the database&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And update the caller API:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;borks&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Borks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;pathPrefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;borks&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IntNumber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;queryNamespace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;complete&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;borks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;borkId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;toJson&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This was fairly simple, but painful, as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get&lt;/code&gt; methods of collections like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Borks&lt;/code&gt; may have
called other methods on other collections, nesting calls ever downward, as shown below in the
example, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Borks&lt;/code&gt; calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;barks.get&lt;/code&gt; and so forth.  As a result, I had to deal with adding the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;namespace: String&lt;/code&gt; parameter to &lt;em&gt;all&lt;/em&gt; methods on all collections. Remember, adding the namespace
method as a &lt;em&gt;field&lt;/em&gt; was not an option – the namespace was an extra parameter to every method
invocation.&lt;/p&gt;

&lt;p&gt;So I was dealing with transforming code that looked like this:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;barksImpl&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Barks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;aggregateWithBarks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;barks&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Borks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;aggregates&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
     &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bork&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; 
       &lt;span class=&quot;n&quot;&gt;barks&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flatMap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bark&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;barksImpl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bark&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
         &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and by adding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;namespace&lt;/code&gt; everywhere, I had to transform it into&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;barksImpl&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Barks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;aggregateWithBarks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;barks&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Borks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;aggregates&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
     &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bork&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; 
       &lt;span class=&quot;n&quot;&gt;barks&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flatMap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bark&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;barksImpl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;bark&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
         &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
     &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So I had to add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;namespace: String&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;barks.get&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;borks.aggregateWithBarks&lt;/code&gt;. Sounds tedious?
Well, imagine there weren’t just one call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;barksImpl.get&lt;/code&gt;, but tens, and imagine there weren’t
just two collections, but a hundred – and tens of thousands of lines to refactor.&lt;/p&gt;

&lt;p&gt;Specifically, I didn’t want to keep adding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;namespace, &lt;/code&gt; into every method call inside a method call,
but chose to make it implicit instead.  This way, I needed only pass the implicit parameter around,
and I didn’t need to modify any of the nested method calls. I typed the namespace with a custom case
class and added it as an implicit argument:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Namespace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Borks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Namespace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;aggregateWithBarks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;barks&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Namespace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Barks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Namespace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, that was one particularly nice use case for implicit parameters. The good thing is that if the
datastore is redesigned cleanly so that you cannot access from one namespace (keyspace) to another,
all you need is to instantiate BorksImpl and set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implicit val namespace = ...&lt;/code&gt; upon instantiation, and
the code will work just fine. Implicit parameters let me implement a painful refactoring very
quickly.&lt;/p&gt;

&lt;p&gt;Naturally, had I had more time, I would’ve done the separation properly, implemented namespacing
rules more clearly, completely redesigning the database, and so forth. Anyway, with Scala implicits,
I was able to do a non-proper solution in a way that did not elicit a “jesus christ what a hack”
feeling. It didn’t pollute my code too much and it will be easy to &lt;em&gt;refactor out&lt;/em&gt; when it’s no
longer needed.&lt;/p&gt;

&lt;p&gt;And, it turned out, I was able to benefit from other implicits: conversions and arguments. I needed
the ability to convert from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Namespace&lt;/code&gt; entity into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt;, as I had in the querybuilder
syntax. I needed only to insert &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;namespace&lt;/code&gt; instead of having to write &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;namespace.namespace&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Namespace&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;namespace2String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Namespace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;namespace&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;Session&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;prepare&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;QueryBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;insertInto&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(...))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Another nice thing was using implicit arguments. The REST API gets the namespace from the URI segment
as a parameter to the anonymous function. If I called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;borks.get&lt;/code&gt; I would have needed to put an
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implicit val n: Namespace = namespace&lt;/code&gt;. I avoided that using the implicit argument method:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;borks&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Borks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;pathPrefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;borks&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IntNumber&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;queryNamespace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Namespace&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;complete&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;borks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;borkId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;toJson&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implicit namespace: Namespace =&amp;gt;&lt;/code&gt; is equivalent to having &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;namespace =&amp;gt; implicit val n:
Namespace = namespace; ...&lt;/code&gt;. Very useful if you’re calling methods requiring implicits in closures,
though potentially hazardous, if you’re not typing your implicits! A simpler example:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Vyx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;frobnicate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// contrived example, makes no sense&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vyx&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Vyx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;vyx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;frobnicate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;one&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;two&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;three&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Vyx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s a good idea to type your implicit values as defining an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implicit x: X&lt;/code&gt; will yoink any implicit
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X&lt;/code&gt; in scope, and if this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X&lt;/code&gt; happens to be a basic type like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt;, and you’re not careful, you
end up with the wrong implicit value.&lt;/p&gt;

&lt;p&gt;Implicits weren’t a new thing to me, this was just a scenario where I was able to simultaneously
benefit from many kinds of implicits Scala has to offer (parameters, conversions and
arguments). They let me perform an annoying refactoring quickly and painlessly, in a manner that was
also future-proof.&lt;/p&gt;


        </description>
        <pubDate>Wed, 15 Mar 2017 00:00:00 +0000</pubDate>
        <link>http://ane.iki.fi/2017/03/15/implicit-power.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2017/03/15/implicit-power.html</guid>
      </item>
    
      <item>
        <title>Apache Camel and the price of abstractions</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;&lt;a href=&quot;http://camel.apache.org/&quot;&gt;Apache Camel&lt;/a&gt; is a routing and mediation engine. If that doesn’t say
anything to you, let’s try this: Camel lets you connect endpoints together. These endpoints can
vary. They can simple local components, like files, or external services like ActiveMQ or web
services. It has a common language format for the data, so that your data can be
protocol agnostic, and an intuitive DSL for specifying the connections and how the data should be
processed between messages.
&lt;!--break--&gt;&lt;/p&gt;

&lt;p&gt;The common language consists of &lt;em&gt;exchanges&lt;/em&gt; and &lt;em&gt;messages&lt;/em&gt;. These are translated into
protocol-specific formats (like a HTTP request) by components, which provide the technical
implementation of that service, i.e., the translation of a simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Message&lt;/code&gt; into an actual HTTP
request.&lt;/p&gt;

&lt;p&gt;The connection method is an intuitive DSL that speaks in terms such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;from&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;to&lt;/code&gt;. Informally,
you can create a route that can, for example, read messages &lt;em&gt;from&lt;/em&gt; ActiveMQ, and write them &lt;em&gt;to&lt;/em&gt; a
file. The language is much richer than this, grouping together things like aggregation, filtering,
routing, splitting, load balancing, the list goes on.&lt;/p&gt;

&lt;p&gt;Choosing what component to instantiate is done using an URI. An URI will identify the target
component, e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rabbitmq://myserver:1234/...&lt;/code&gt; instantiates
the &lt;a href=&quot;https://www.rabbitmq.com/&quot;&gt;RabbitMQ&lt;/a&gt; &lt;a href=&quot;http://camel.apache.org/rabbitmq.html&quot;&gt;component&lt;/a&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file:...&lt;/code&gt; instantiates the &lt;a href=&quot;http://camel.apache.org/file2.html&quot;&gt;file component&lt;/a&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;netty4:...&lt;/code&gt;
instantiates the Netty component (version 4.0). As long as the component is available in the
classpath, it will be instantiated in the background by Camel. The total number of
available &lt;a href=&quot;http://camel.apache.org/components.html&quot;&gt;components&lt;/a&gt; is huge! You have e.g.:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ActiveMQ, RabbitMQ, Kafka, AVRO connectors&lt;/li&gt;
  &lt;li&gt;Files and directories&lt;/li&gt;
  &lt;li&gt;REST, SOAP, WSDL, etc.&lt;/li&gt;
  &lt;li&gt;More esoteric ones like SMPP – yes, you can send SMSes with Camel!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So what’s the point? Let’s assume we need to integrate an upstream system Xyz into Bar. Xyz provides
data to you using a binary JSON format, using some known protocol, like ActiveMQ. Then you need to
apply some transformations to the data, finally sending it to Bar, which accepts XML, and requires
the information to be POSTed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;someURL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In a non-camel setting, using your favorite language, to do this, you&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Using an ActiveMQ connector, you build your queue reader and de-serializer&lt;/li&gt;
  &lt;li&gt;Apply your business logic (whatever that is) to the de-serialized data&lt;/li&gt;
  &lt;li&gt;Transform into XML&lt;/li&gt;
  &lt;li&gt;POST the data towards &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;someURL&lt;/code&gt; using some HTTP library&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Fairly straightforward, right? All you need are an ActiveMQ library, a HTTP library and something
that works with JSON and XML.&lt;/p&gt;

&lt;p&gt;Here’s where it gets hairy. Three months in, you are informed that the upstream source is converting
to RabbitMQ. Oh well, you think, it’s nicer, faster, and implements a saner version of AMQP, why
not. So you refactor ActiveMQ to RabbitMQ and there it is.&lt;/p&gt;

&lt;p&gt;The point of Camel is this. The previous step requires you to manually refactor your ActiveMQ logic
to RabbitMQ. But you’re just sending messages, you don’t really care about the protocol. You’re just
sending messages to an endpoint, it’s the &lt;em&gt;data&lt;/em&gt; you should care about, nothing else.&lt;/p&gt;

&lt;p&gt;So here’s when Apache Camel comes in. It let’s you specify an URL like&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rabbitmq://localhost/blah?routingKey=Events.XMC.*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;to use the RabbitMQ component, and to painlessly switch to Kafka, you’d add a dependency to the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;camel-kafka&lt;/code&gt; artifact and specify the URL as&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kafka:localhost:9092?topic=test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and the Camel Kafka component handles message delivery for you. Since you’re sending canonical camel
messages, you needn’t trouble yourself on how this message is already sent. It is likely that you
will have to add or remove some message headers though.&lt;/p&gt;

&lt;p&gt;Now, you may be asking, &lt;em&gt;is that it&lt;/em&gt;? Is it really that simple?&lt;/p&gt;

&lt;p&gt;The answer is that it depends. Some components are better than others. If you want to be truly
protocol and component agnostic, and you want to refactor from protocol &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bar&lt;/code&gt; just by
switching the URL of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo://...&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bar://&lt;/code&gt;, you need to make sure that&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;You can configure everything for that endpoint using the URI&lt;/li&gt;
  &lt;li&gt;Message exchanges do not require extra shenanigans to work (no custom headers or a special format
required)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Case in point, let’s compare switching from &lt;a href=&quot;http://camel.apache.org/activemq.html&quot;&gt;ActiveMQ&lt;/a&gt;
to &lt;a href=&quot;http://camel.apache.org/rabbitmq.html&quot;&gt;RabbitMQ&lt;/a&gt;. The first glaring difference is that the
ActiveMQ component does not accept the host part in the URI. So we need to do something like&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;CamelContext&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DefaultCamelContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addComponent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;activemq&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;nc&quot;&gt;ActiveMQComponent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;activeMQComponent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tcp://USER:PASS@HOSTNAME?broker.persistent=false&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This makes any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activemq:...&lt;/code&gt; URI in the context &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctx&lt;/code&gt; connect to the parameters configured.&lt;/p&gt;

&lt;p&gt;Conversely, the RabbitMQ component lets you directly set this in the URI part (multiple addresses can be
given with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addresses&lt;/code&gt; parameter). So if you’re going with ActiveMQ to RabbitMQ, your code
actually becomes simpler, but the complexity merely moves to the URI. The other way around, you have
to move your URI-configuration to actual code (or XML, but please, &lt;em&gt;don’t&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;So where does this lead us? Ideally, the situation is that given between a choice between three
components, you could use an external configuration file that configures a simple URI. The right
component is identified based on the URI, pulled out of the classpath. This assumes that, in order
of importance,&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;the endpoints are volatile and &lt;em&gt;finite&lt;/em&gt; and can vary between different implementations,&lt;/li&gt;
  &lt;li&gt;each implementation has a Component which is in the classpath, and&lt;/li&gt;
  &lt;li&gt;said volatility varies often enough it warrants dynamic configurability via configuration editing
and app restarts.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If &lt;strong&gt;all&lt;/strong&gt; of the above hold true, Camel might a good fit for you. Otherwise, I’d be careful: the
abstraction isn’t free! What this leads to is a kind of &lt;em&gt;complexity shoveling&lt;/em&gt;: although with the
RabbitMQ component we don’t need to use &lt;em&gt;code&lt;/em&gt; to configure it, we move it to the URI. So it’s still
a configuration point. Yet, it’s a &lt;em&gt;nicer&lt;/em&gt; configuration point. As in the example above, we see that
the connection contains three configurable variables &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USER&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PASS&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HOSTNAME&lt;/code&gt;. So, &lt;em&gt;in
addition&lt;/em&gt; to having to configure the system using code, we have to still configure it otherwise,
lest we hard-code the values into the application.&lt;/p&gt;

&lt;p&gt;The above approach suffers from decentralization: you now have &lt;em&gt;two&lt;/em&gt; places where you customize your
system. The first is defining the custom component for a system in &lt;strong&gt;code&lt;/strong&gt;. The second is
configuring said custom component via other means.&lt;/p&gt;

&lt;p&gt;Our ability to centralize configuration – any configuration, not just that of Camel – depends on
the power of the configuration language. Too powerful, you end up in DSL hell. Not powerful enough,
people write their &lt;a href=&quot;http://camel.apache.org/spring.html&quot;&gt;own horror shows&lt;/a&gt; to add power.&lt;/p&gt;

&lt;p&gt;Lastly, we run in the problem of universal pluggability, or universal composition. We imagine that
systems like Camel let us “run anything” and “connect everything”, but the reality is
different. Systems are usually made of a finite set of components. For practical purposes, it makes
no sense to depend on every Camel component. Therefore, you need to pick your dependencies from this
finite set of known endpoints. This effectively shatters the myth of universal pluggability.&lt;/p&gt;

&lt;p&gt;Most importantly though, nobody really &lt;em&gt;needs this&lt;/em&gt;. What really matters is the simplicity of
extension. A well designed component is completely configurable through its URI parameters. These
are easy to add to your Camel-based system: you only need to understand the new configuration, add
the dependency and you’re done.&lt;/p&gt;

&lt;p&gt;In summary, if you’re considering Apache Camel, make sure you check both of these, of which the
second is most important.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The components are volatile and you need to change them often, so that you can justify the
pluggable hole (the changing URI!)&lt;/li&gt;
  &lt;li&gt;The components you want &lt;em&gt;exist&lt;/em&gt; and are completely configurable via that pluggable hole&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you’re unsure of the first item, you can still treat Camel as a lazy way to future-proof the
system, e.g., by using one component now, while knowing that another may be used in the future. To
that end, you need to make sure that the components fit the above requirements.&lt;/p&gt;

&lt;p&gt;I’m currently working on a
&lt;a href=&quot;http://github.com/ane/llama&quot;&gt;Clojure library&lt;/a&gt; for a Clojure-based routing DSL. It’s shaping up to
be quite nice! Here’s an example of the routing DSL:&lt;/p&gt;

&lt;div class=&quot;language-clojure highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;route&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;netty4-http:localhost:80/foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; 
         &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;comp&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;rabbitmq://localhost:5672/foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;My goal is to make the DSL terse and functional (which the current model really isn’t) and to add
&lt;a href=&quot;http://doc.akka.io/docs/akka/current/scala/camel.html&quot;&gt;Akka Camel&lt;/a&gt; Consumers and Producers to
it. The nice thing about Clojure is that the macro system lets me define these really easily!&lt;/p&gt;

&lt;p&gt;Overall, Camel is a nice abstraction, well worth the effort and years that has been put into
it. It’s not a &lt;em&gt;free&lt;/em&gt; abstraction, since there’s always a slight compatibility or configuration
overhead. If it works, it removes programmers from the protocol level, moving them to
the data level. This is the level where you should be working at, if your goal is to shuffle data
around. For this purpose, when it works, Camel is excellent.&lt;/p&gt;

&lt;p&gt;Conversely, if it doesn’t, it puts programmers at an awkward position: you’re still
working with both data and protocol, &lt;em&gt;and&lt;/em&gt; you have the overhead of the framework to deal
with. Worse, your code is now polluted by the requirements of &lt;em&gt;Camel endpoints&lt;/em&gt;, when the goal of
Camel is to completely remove the requirements imposed by endpoints in general.&lt;/p&gt;

&lt;p&gt;That said, in integration scenarios, Camel works &lt;em&gt;most of the time&lt;/em&gt;, so you should always have a
think about it before you start using it.&lt;/p&gt;

        </description>
        <pubDate>Wed, 08 Mar 2017 00:00:00 +0000</pubDate>
        <link>http://ane.iki.fi/2017/03/08/camel-abstractions.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2017/03/08/camel-abstractions.html</guid>
      </item>
    
      <item>
        <title>Half stack web frameworks</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;In my previous post, I discussed &lt;a href=&quot;/2016/10/25/web-development-has-become-weird.html&quot;&gt;how web development had become weird&lt;/a&gt;. In this post, I will discuss what exactly is it
that makes it so weird. I will also present an alternative to JavaScript-based SPAs that look and
behave like them, yet at the base are built using standard full-stack frameworks. They can leverage
modern JavaScript libraries like React and compilers like Babel while simultaneously avoiding the
confusing tooling ecosystem and providing a rich and responsive user experience, all the
while retaining an pleasant developer experience.
&lt;!--break--&gt;&lt;/p&gt;

&lt;h2 id=&quot;what-exactly-is-wrong-with-the-tooling-ecosystem&quot;&gt;What exactly is wrong with the tooling ecosystem?&lt;/h2&gt;

&lt;p&gt;I think, largely, the reason why web development has become weird was that front-end development
cannot figure itself out. We are wasting effort and time by building more and more elaborate
abstractions that fundamentally exist only because of an unhappy accident: the web is the &lt;em&gt;only&lt;/em&gt;
cross-platform application container. It is also a very accessible medium. To create a web
application, fundamentally, one needs to present the right kind of mark-up to a browser that renders
it.&lt;/p&gt;

&lt;p&gt;Let’s stop here. Just because the web became what it is by accident, doesn’t make it a bad thing in
itself. Everybody &lt;em&gt;loves&lt;/em&gt; platform independence. Everybody loves accessibility. The web is easy to
develop for and it can reach almost everybody. This is a reality we have to deal with, a reality in
which web development is (a) popular, (b) ubiquitous and (c) easy.&lt;/p&gt;

&lt;p&gt;The combination of those properties creates an interesting melting pot of rapidly evolving
technologies. Rapid progress is a nice thing in itself, but a bad thing to the ecosystem when it
evolves blindly. Web development doesn’t evolve blindly, rather, it is myopic.&lt;/p&gt;

&lt;h2 id=&quot;progress-progress-progress&quot;&gt;Progress, progress, progress!&lt;/h2&gt;

&lt;p&gt;To put this into context, we must understand that currently, most software is disposable. Because
software is disposable, we eagerly toss a half-functioning solution into the bin and rewrite it,
rather than taking it apart and rebuilding a better version. This leads to programs getting
rewritten and rewritten, sometimes doing things differently but most of the time it’s just the same
thing under a different layer of paint.&lt;/p&gt;

&lt;p&gt;But I digress. That is more of a problem with software development in general. We can review a more
concrete example: the JavaScript tooling ecosystem. To develop front-end in JS, you need three
different tools;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A package manager - npm, bower or yarn&lt;/li&gt;
  &lt;li&gt;A module bundler - webpack, rollup or browserify&lt;/li&gt;
  &lt;li&gt;A task runner - gulp, grunt, brunch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these segments work completely differently. So to get started with, that’s three different
tooling systems you have to learn. Better yet, each individual tool inside each system is unique in
its configuration syntax. So if you learn how to configure Grunt you will have to learn Gulp and
Brunch from scratch. Joy.&lt;/p&gt;

&lt;p&gt;Yeah, yeah, I get it. Bower was cool because it built flattened trees when npm didn’t. Gulp had a
nicer configuration syntax, and Brunch was easy to get started with. Yarn is more secure and more
reliable than npm. Webpack can inline your CSS and images and is more configurable than Browserify.&lt;/p&gt;

&lt;h2 id=&quot;not-about-killing-innovation&quot;&gt;Not about killing innovation&lt;/h2&gt;

&lt;p&gt;At this point, you may be wondering that I desire a world in which there is but one alternative to
every task. This is not the case. I only ask for reservation: if there are no fundamental
ideological differences, if there are no personal incompatibilities between the developing
organizations, is there any valid argument for building your own version of a tool, instead of
contributing to an existing system?&lt;/p&gt;

&lt;p&gt;I don’t think this is the case &lt;strong&gt;at this scale&lt;/strong&gt; — obviously, a world with just one kind of tool
or library for one thing is stupid, but the sweet spot does definitely not lie at &lt;em&gt;seven&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So if the answer is no, does that mean JavaScript developers are so strange that they cannot get
their heads together and agree on something? Do they really think people enjoy keeping up with the
Joneses all the time and learning a new tool every year?&lt;/p&gt;

&lt;p&gt;When it comes to the first question, remember Joyent and the io.js schism. &lt;em&gt;Oops&lt;/em&gt;. As to the second,
I doubt it. Still, this is what we have to live with. A
&lt;a href=&quot;https://github.com/verekia/js-stack-from-scratch&quot;&gt;guide&lt;/a&gt; for building a modern JS front-end app
consists of &lt;em&gt;twelve&lt;/em&gt; distinct steps, all of them quite elaborate. I applaud the author for the
gargantuan effort in that tutorial: it’s the best I’ve seen so far. But seriously, take a look at
it! What the fuck?! I could have just rewritten my previous post with a link to that guide and
rested my case!&lt;/p&gt;

&lt;p&gt;I remember a &lt;a href=&quot;http://www.charlespetzold.com/pw5/&quot;&gt;book&lt;/a&gt; about Windows programming using C, and parts
of this guide are arcane enough to evoke memories of &lt;em&gt;that&lt;/em&gt;. I think one can enumerate the type
system of Scala using less. Or how to write a Scheme interpreter.&lt;/p&gt;

&lt;p&gt;The usability of the tooling ecosystem is absolutely disgraceful. No other developer segment has
this many hoops to jump through and nobody else has to learn so many different tools just to get a
simple web application running.&lt;/p&gt;

&lt;p&gt;Why do we put up with this? Why isn’t any effort being put into simplifying the tooling stack,
instead of making it more elaborate, powerful, and verbose? Consider webpack. It is a powerful
utility that is supposed to combine all your assets — that is, code, CSS, images — into a single
module that is used in your application. This is a powerful thing. The only problem is that its
configuration is &lt;em&gt;hell&lt;/em&gt;. I work with SBT every day, and my goodness, even SBT is easier to configure
than Webpack. Ask any Scala developer what it means to say that. You will get funny looks. Even Java
folks will consider this crazy, although, in fairness, they’ve
&lt;a href=&quot;http://microprofile.io/&quot;&gt;moved into the post-framework age&lt;/a&gt;, and consider us mortals rather quaint.&lt;/p&gt;

&lt;h2 id=&quot;spa-development-is-more-than-just-tools&quot;&gt;SPA development is more than just tools&lt;/h2&gt;

&lt;p&gt;The problems don’t stop here. A SPA must effectively handle client state &lt;em&gt;entirely&lt;/em&gt; in the browser,
though in &lt;del&gt;isomor&lt;/del&gt;universal SPA apps part of the rendering and client state is processed on the
server. This requires the use of architectural patterns
like &lt;a href=&quot;https://github.com/reactjs/react-redux&quot;&gt;Redux&lt;/a&gt;
and &lt;a href=&quot;https://github.com/ReactTraining/react-router&quot;&gt;React Router&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These libraries are nice and intelligent, but I feel they are a wasted abstraction. Using the trick
below I can create React apps that can approximate the performance of a real SPA app, without having
to rely on these complicated architectural patterns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caveat lector&lt;/strong&gt;. This is largely a matter of taste. If you really like Redux and React Router, by
all means use them, but I find their usability to be sub-par to the MVC architecture of any
full-stack framework. The architectural pattern — Flux — is a message-based event loop. The
views generate user actions (button clicks) that are dispatched to stores (state containers) which
update themselves (increment a number) then deliver state changes (an incremented number) to the
views which re-render themselves. If a request is sent to the server, it must be split into two
parts: first, a button click is registered, and its effect is rendered; second, a request is sent to
the back-end and when it completes, an action describing a completed request is sent to the message
dispatcher. So any interaction with the back-end requires two actions. Sounds complicated? Yeah, this
is why I prefer a dumb MVC architecture (or Relay).&lt;/p&gt;

&lt;h2 id=&quot;in-summary&quot;&gt;In summary&lt;/h2&gt;

&lt;p&gt;So, to put this argument into a more cogent form, I’ll summarize them below.&lt;/p&gt;

&lt;h3 id=&quot;1-lack-of-emphasis-on-usability-a-myopic-focus-on-adding-features&quot;&gt;1. Lack of emphasis on usability, a myopic focus on adding features.&lt;/h3&gt;
&lt;p&gt;Why doesn’t anyone integrate dependency management, module bundling and task running under the
same program? Why do we have to use three different programs that are getting replaced every year?
Tool “monoliths” like SBT may be ugly in parts, but they can do package management, compilation,
debugging, testing – even if it’s DSL is garish and confusing, still, once you’re familiar with it,
you don’t have to master six other horrifying DSLs. Just one.&lt;/p&gt;

&lt;h3 id=&quot;2-chasing-novelty-with-little-care-about-its-impact-on-maintainability&quot;&gt;2. Chasing novelty with little care about its impact on maintainability.&lt;/h3&gt;
&lt;p&gt;Babel lets us write JS in eleventy different dialects. While that is a cool thing in itself, it a
horror show for developers. You ask, who wouldn’t want to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;await&lt;/code&gt;, or ES6 classes? Well, how
about the person who doesn’t want to &lt;em&gt;learn how to use Babel&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;With Babel, you can write in any version of JavaScript you want,
since it all gets compiled down to ES5 anyway. This is great for building your
flavor-of-the-month hack, but it’s also a terrific way of building unmaintainable software. For
this zany &lt;em&gt;hack&lt;/em&gt; to work, you need &lt;del&gt;tra&lt;/del&gt;compilers that translate your modern code to old code. The
requirement of that tool is too high a price to pay for some fancy language features.&lt;/p&gt;

&lt;h3 id=&quot;3-snubbing-full-stack-frameworks-for-their-want-novelty-although-they-generally-feature-exemplary-usability&quot;&gt;3. Snubbing full-stack frameworks for their want novelty, although they generally feature exemplary usability&lt;/h3&gt;

&lt;p&gt;Clojure developers have found a way of eschewing frameworks over composable
libraries. For some reason, everybody else is really bad at this, so we build frameworks, i.e., sets
of libraries that govern the design of your program in a certain way. Monolithic frameworks like
Rails or Django are fundamentally dated — though this is easily fixed — but they are
usable. Setting up a functional application with these takes a few minutes, and it just works.&lt;/p&gt;

&lt;h2 id=&quot;a-new-direction-renovate-not-rewrite&quot;&gt;A new direction: renovate, not rewrite&lt;/h2&gt;

&lt;p&gt;In my opinion, front-end development can be done in an alternate, saner way. It doesn’t mean going
back to the stone age of Apache or Rails with ActiveRecord. Rather, it means refurbishing these old,
battle-tested technologies with modern components without tossing the whole chassis into the
bin.&lt;/p&gt;

&lt;p&gt;In other words, there is an alternative to the current JavaScript SPA horror show. Using the
following technologies, as an example:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;A REST API built in a scalable and performant language&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;Examples: Scala, Haskell, Go, Clojure, Java, Rust, OCaml, Elixir&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;This gives us a clear advantage when scaling and deploying our application. Data access is made
opaque and is in no way tied to the front-end - which is ultimately just presentation and some
client state. The language needs the following:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;A stable library ecosystem, especially for data access, e.g., database drivers&lt;/li&gt;
      &lt;li&gt;A functioning web server and associated libraries&lt;/li&gt;
      &lt;li&gt;Speed, multi-threading, performance&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;With these properties, you should be quite comfortable in your back-end development.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Client state, presentation and back-end communication handled using a monolithic framework&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;Examples: Ruby on Rails, Django, Pyramid, MeteorJS, Udash, Play&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;Rails may be dated in some parts — coupling your front-end with data access is one thing — but
as an infrastructure it is functional, mature, easy to understand and &lt;em&gt;stable&lt;/em&gt;. The Ruby ecosystem
is large and is well documented, even the secondary documentation (StackOverflow etc.) is abundant.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;A wrapper that turns ordinary HTTP page requests into XHRs&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;Examples: Turbolinks (for Ruby on Rails and Django)&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;Turbolinks is perhaps a hack but it is clever: any HTTP request that would normally cause a page
reload, like a link or a form submission, is converted into an XHR. Then, the page redraws itself
by swapping out the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;body&amp;gt;&lt;/code&gt; element from the returned response.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Turbolinks is a “pseudo-SPA” application in that it simply reroutes ordinary page requests (links,
form submissions) as XHRs and then from the new page, it &lt;strong&gt;merges&lt;/strong&gt; the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;head&amp;gt;&lt;/code&gt; element and &lt;strong&gt;swaps&lt;/strong&gt;
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;body&amp;gt;&lt;/code&gt; element. By using a gem like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;react-rails&lt;/code&gt; you can combine this with react, however, it
does &lt;strong&gt;not&lt;/strong&gt; use React’s virtual DOM when redrawing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;body&lt;/code&gt; content. It only mounts and unmounts the
components when the page swaps, retaining the actual DOM bindings.&lt;/p&gt;

&lt;h2 id=&quot;what-your-answer-is-rails-in-2016&quot;&gt;What?! Your answer is &lt;em&gt;Rails&lt;/em&gt;? &lt;em&gt;In 2016&lt;/em&gt;?&lt;/h2&gt;

&lt;p&gt;Just because these frameworks aren’t making headlines doesn’t mean they are stuck in the stone
age. These monolithic frameworks still, after years of maturation, possess novelty value in one,
unparalleled aspect: usability. These frameworks may not lend themselves to universal applications,
but they’re still capable of absorbing new technologies like
&lt;a href=&quot;http://edgeguides.rubyonrails.org/action_cable_overview.html&quot;&gt;websockets&lt;/a&gt; and
&lt;a href=&quot;https://github.com/rmosolgo/graphql-ruby&quot;&gt;GraphQL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Some parts of them are stuck in the past, of which the most striking one is combining data access
with data control and presentation in the same program. This is easily fixed: make your Rails
controllers call an external, opaque service to render is data. The job of the full-stack framework
is reduced to managing client state and data presentation, which go together.&lt;/p&gt;

&lt;p&gt;So, what can be done? Here’s an example.&lt;/p&gt;

&lt;h2 id=&quot;a-rest-backed-rails-app-with-react-as-the-templating-engine&quot;&gt;A REST-backed Rails app with React as the templating engine&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/reactjs/react-rails&quot;&gt;react-rails&lt;/a&gt; is a Rails gem that gives us React components
in the asset pipeline, supporting server-side rendering and Turbolinks (caveat: see above)&lt;/p&gt;

&lt;p&gt;Under the hood, when rendering on the server, react-rails uses
&lt;a href=&quot;https://github.com/babel/ruby-babel-transpiler&quot;&gt;Babel&lt;/a&gt; and
&lt;a href=&quot;https://github.com/sstephenson/execjs&quot;&gt;ExecJS&lt;/a&gt; to prerender the content. Better yet, your content
is still rendered by a simple Rails controller like the following.&lt;/p&gt;

&lt;p&gt;The controller lives in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app/controllers/foos_controller.rb&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FoosController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# maps to GET /foos (on the front-end)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# incurs a GET /foos on the back-end&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@foos&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_json&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; 
  
  &lt;span class=&quot;c1&quot;&gt;# maps to POST /foos (on the front-end)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# this is a POST /foos on the back-end&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:bar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'bar'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# turbolinks turns this into a XHR&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;redirect_to&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/foos'&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The model is just a &lt;a href=&quot;https://github.com/remiprev/her&quot;&gt;Her&lt;/a&gt; model, an ORM that uses a REST API, which
you can customize. In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apps/models/foo.rb&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Her&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Model&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;attributes&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo.find(1)&lt;/code&gt; maps to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GET /foos/1&lt;/code&gt; in the back-end, and so forth.&lt;/p&gt;

&lt;p&gt;The view is generated by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app/views/foos/index.html.erb&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-erb highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; 
&lt;span class=&quot;n&quot;&gt;react_component&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;s1&quot;&gt;'Foos'&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;ss&quot;&gt;foos: &lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@foos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;token: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;form_activity_token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;action: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;action: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'create'&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;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;prerender: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&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;cp&quot;&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This maps to a React component &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app/assets/javascripts/components/foos.es6.jsx&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Foos&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;render&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;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;foos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
           &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/li&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;})}&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/ul&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;// dataRemote is a Rails trick that makes the form make an XHR&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;form&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;action&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;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;POST&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dataRemote&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;hidden&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;authenticity_token&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;value&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;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Blah blah&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;submit&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Add!&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/form&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/div&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Try doing that with less code in any JS app! The controller looks like any standard Rails
controller. In fact, it is exactly like one, yet the magic of React &amp;amp; Turbolinks lets us wrap this
into a SPA-like experience.&lt;/p&gt;

&lt;p&gt;Combining these elements, we get &lt;strong&gt;an application that can reach nine-tenths of the performance and
responsiveness of a 100% JavaScript SPA, while simultaneously avoiding the messy tooling ecosystem&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;A total absence of extraneous tooling, the framework has these built-in. No need for Webpack or
Babel, these are just another gems you add to your dependency list.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A boring, but familiar, framework that handles routing, message dispatch and API integration for
us. Routing and state management are the worst parts of SPA development. Now our state is just
another Rails&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Responsiveness close enough to that of a real SPA. It will never match a real SPA in speed, since
the requests map to Rails controllers, but it will be extremely pleasant to develop in.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A scalable back-end without any data access logic in the front-end (the usual front-end back-end
split), the framework handles only UI state and presentation logic.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are some obvious compromises in such a solution, which are both good and bad.&lt;/p&gt;

&lt;h4 id=&quot;compromises-made&quot;&gt;Compromises made&lt;/h4&gt;

&lt;p&gt;The biggest compromise is in performance, which is due to the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Does not use React’s DOM to its full power&lt;/strong&gt;. Turbolinks just swaps the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;body&lt;/code&gt; element. This
could be improved by making it use the React virtual DOM. This is the bad part. The good part is
that we don’t have to create XHRs ourselves in React components.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Forces the user to use JSX, throws ERB/HAML in the bin&lt;/strong&gt;. It is true that the example
application could be indeed built without JSX — just don’t use react-rails — but I find JSX to
be a nicer templating syntax than ERB. advantage of React&lt;/p&gt;

    &lt;p&gt;But it would be naïve to assume this brings us the whole of &lt;em&gt;React&lt;/em&gt;. It brings us the &lt;em&gt;templating
syntax&lt;/em&gt; and binding mechanisms, but since Turbolinks effectively causes a re-rendering of the
&lt;em&gt;whole&lt;/em&gt; HTML page, this doesn’t fully leverage the server-side rendering aspect of React.&lt;/p&gt;

    &lt;p&gt;So, overall, the good part of this compromise is that we get to use JSX, which has a nicer,
functional approach compared to ERB, but the bad part is that we don’t harness the full power of
React.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Turbolinks effectively reverses React server-side rendering&lt;/strong&gt;. Whereas in a normal SPA app the
server-side rendering is the “base” template, in this case a &lt;em&gt;new&lt;/em&gt; server-side rendering is
produced on every interaction. In a normal SPA app, one just updates the DOM with new &lt;em&gt;state&lt;/em&gt; —
i.e., props — not with a new &lt;strong&gt;DOM&lt;/strong&gt;.&lt;/p&gt;

    &lt;p&gt;There is a solution: skip Turbolinks and use XHRs in React components. A simple solution in a
controller:&lt;/p&gt;

    &lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:bar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;xhr?&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# send a JSON of all the Foos&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:json&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_json&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# send HTML with a React component&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;redirect_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;action: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'index'&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If the request is made from a component, it’s can now use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setState&lt;/code&gt; (or a store) to update its
new state. In this paradigm, Rails is acting as the state store.&lt;/p&gt;

    &lt;p&gt;A better example would be to make the Rails app support GraphQL and use Relay to communicate with
the Rails part, see below.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think, given the simplicity of the above application, I think it’s fair to say that these
compromises are warranted. If the actual set-up were any more complicated I wouldn’t be so
certain. But, for the simplicity, we must trade performance.&lt;/p&gt;

&lt;h3 id=&quot;a-functioning-example&quot;&gt;A functioning example&lt;/h3&gt;

&lt;p&gt;I’ve created a functioning example and put it into two repositories:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Front-end – Rails 5 &amp;amp; react-rails &amp;amp; Her – &lt;a href=&quot;https://github.com/ane/rails-react-frontend&quot;&gt;https://github.com/ane/rails-react-frontend&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;A Rails 5 app combining react-rails and Her to talk to the back-end.&lt;/p&gt;

    &lt;p&gt;To install, clone the repo, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundle install&lt;/code&gt;, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foreman start&lt;/code&gt;. This will start the Rails
server and the live re-loader.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Back-end – &lt;a href=&quot;https://github.com/ane/rails-react-backend&quot;&gt;https://github.com/ane/rails-react-backend&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;It’s a dead simple Sinatra REST API that uses Sqlite3. This is obviously not suitable for
production.&lt;/p&gt;

    &lt;p&gt;To install, clone the repo, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundle install&lt;/code&gt;, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rackup&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This application will &lt;em&gt;never&lt;/em&gt; match a real SPA. A part of the front-end is not in the browser, so we
will rely on a second web-server to run it. So it is an &lt;em&gt;illusion&lt;/em&gt;, but as an illusion it is close
enough, and it is &lt;em&gt;easy to use&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;JavaScript front-end development, as it currently stands, is painful to develop in. One has to
master many command line tools that instead of being unified as a single tool, each continue to
diverge and grow larger and more powerful. The result is a confusing developer experience.&lt;/p&gt;

&lt;p&gt;In this post, I showed that we can scrape the good parts of modern JS developments and use them to
modernize an older application stack that mimics the user experience of a SPA, but is not one. The
application uses a clever library — Turbolinks — to convert page requests into XHRs, creating an
illusion of a single-page application.&lt;/p&gt;

&lt;p&gt;The end result is a &lt;em&gt;half stack web framework&lt;/em&gt;: we yank data access from a monolithic full-stack
framework (Rails) and make it use a REST API and we replace its presentation logic (ERB) with
React. The framework is left to handle client state, routing and asset pipelining, which are the
painful parts of SPA development, and the UI is rendered using React. So the Model–View–Controller
is distributed into three places: Rails for UI state, React for UI rendering, and the REST API is
the actual business logic. Effectively, this reduces Rails to a thin SPA-like front-end over a REST API!&lt;/p&gt;

&lt;p&gt;Where to go from here? Here are some interesting things that could be explored:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Turbolinks with React&lt;/strong&gt;. Use React to parse the HTML returned by Turbolinks (if rendered on the
server) and use the React virtual DOM to update the DOM, instead of blindly swapping the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;body&lt;/code&gt; element.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;GraphQL&lt;/strong&gt;. Although Her is nice, we could use &lt;a href=&quot;http://graphql.org/&quot;&gt;GraphQL&lt;/a&gt; when communicating
with the backend &lt;strong&gt;and&lt;/strong&gt; also use it as a communication method between Rails and React.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;TypeScript&lt;/strong&gt;. I like static typing, but currently react-rails doesn’t really work that well with TypeScript.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;React On Rails&lt;/strong&gt;. A
different &lt;a href=&quot;https://github.com/shakacode/react_on_rails&quot;&gt;kind of React &amp;amp; Rails integration&lt;/a&gt;, which
lets you use Webpack. React On Rails is more flexible than react-rails: you get the full power of
Webpack and NPM here, so this is both good and bad.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All in all, this solution is a compromise.&lt;/p&gt;

&lt;p&gt;Compared to a full-stack Rails app, we have to do extra work in creating a REST API backend, but the
result is an app that’s easier to manage due to the separation of concerns. With a separate data
access layer — the REST API — complex business logic is contained in a single place. It is easy
to couple several clients to such a front-end, and our Rails app is just one of these.&lt;/p&gt;

&lt;p&gt;But, compared to a full-fledged SPA, this app will never be as quick, it will never be as fluid, and
it may not be what cutting-edge front-end development this day represents, but it is is &lt;em&gt;simple&lt;/em&gt;,
there is &lt;em&gt;one&lt;/em&gt; build tool (bundler), and it is &lt;em&gt;fun&lt;/em&gt; to develop in.&lt;/p&gt;

&lt;p&gt;I might miss fancy things like state hydration and Redux, but the insanity of Webpack, Gulp, Babel
and NPM, I will &lt;strong&gt;not&lt;/strong&gt; miss.&lt;/p&gt;

        </description>
        <pubDate>Wed, 02 Nov 2016 00:00:00 +0000</pubDate>
        <link>http://ane.iki.fi/2016/11/02/half-stack-web-frameworks.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2016/11/02/half-stack-web-frameworks.html</guid>
      </item>
    
      <item>
        <title>Web development has become weird</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;Call me old-fashioned, call me a curmudgeon, but I think web development has become stupid and
superficial. The unending quest towards single-page apps (SPAs) has made web development extremely
painful and the current trend is diverging towards seven different directions at once. On one end,
we have rich SPAs that can be built as native applications, on the other we have
something &lt;a href=&quot;https://github.com/ampproject/amphtml&quot;&gt;completely orthogonal&lt;/a&gt;, of which
a &lt;a href=&quot;https://timkadlec.com/2016/02/a-standardized-alternative-to-amp/&quot;&gt;schism&lt;/a&gt; is beginning to form.&lt;/p&gt;

&lt;!--break--&gt;

&lt;p&gt;The underlying problem is unfortunately that the web is being misused as an application container
instead of the original text transport protocol it was made to be. It’s no use crying over spilled
milk; the web has been subverted, transformed, improved upon, so much so we don’t know what the
original even &lt;a href=&quot;http://wiki.c2.com/&quot;&gt;looked like&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;how-it-was&quot;&gt;How it was&lt;/h2&gt;

&lt;p&gt;In 2006, the hot new thing was Ruby on Rails or Django. If you weren’t using them, odds were you
were using PHP or ASP.NET. Most intranet software ran on SharePoint or, I kid you not,
WordPress. Users didn’t really care either way.&lt;/p&gt;

&lt;p&gt;People liked Rails and Django because they made web development stupidly simple. No more SQL, just
create your models and migrations. An architecture that made sense, MVC, was applied, and web apps
became a little bit better. Meanwhile, the overall web development experience got a &lt;em&gt;lot&lt;/em&gt; better.&lt;/p&gt;

&lt;p&gt;Of course, the web was slower back then. Chrome wasn’t around, so JavaScript usage was very
limited. Google began prototyping under-the-hood requests in Gmail around 2006, but before that
nobody had heard of AJAX. The concept of doing more than one page request per page load was
completely unheard of. The users liked faster page loads, so when Chrome came around with V8,
customers started suddenly giving a shit about what browser they used.&lt;/p&gt;

&lt;h2 id=&quot;where-it-all-began&quot;&gt;Where it all began&lt;/h2&gt;

&lt;p&gt;On the surface, the appeal in SPAs was obvious. It started with Gmail and AJAX. No more slow page
loads, the applications behaved like native applications, and soon they even
&lt;a href=&quot;http://getbootstrap.com&quot;&gt;looked&lt;/a&gt; like them! Innovative as that was, now we’re beginning to use so many
web applications that are in the web &lt;em&gt;only&lt;/em&gt; that we’re slowly starting to forget what the native app
experience &lt;em&gt;was&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The problem was that it wasn’t enough, you needed a &lt;em&gt;backend&lt;/em&gt;. Before, when there was one
application, now there were &lt;em&gt;two&lt;/em&gt;, and they usually were completely different from each other. The
backend–front-end split was fuzzy to begin with, this introduced an uncertainty and a possibly
pointless abstraction. Put the “slow” and “heavy” things to the backend, let the front-end handle
rendering and the user interface, all the backend had to do was supply serialized data. Even back then, people started asking
questions about the SEO effects of rendering a page entirely in JavaScript. No solution was given,
although one solution &lt;a href=&quot;https://www.meteor.com/&quot;&gt;existed, but was weird&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So while the backend folks built eleventy versions of &lt;a href=&quot;http://www.sinatrarb.com/&quot;&gt;Sinatra&lt;/a&gt;, the
front-end folks got busy. In a short time we had Backbone, Angular, and Knockout, then we got
frameworks like Durandal and Meteor.js. Finally, Facebook looked at the performance of desktop applications, then looked
at the performance of web applications, thought, “holy shit”, and
&lt;a href=&quot;https://facebook.github.io/react/&quot;&gt;did something about it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;People got scared. It was mixing business and presentation logic, they said. It was mixing JavaScript
with something eerily like XML, and everyone said XML sucked. Then people got over their
usual trepidation towards $newTechnologyOfTheYear and got on with their lives. Now React is being
used &lt;a href=&quot;http://www.facebook.com&quot;&gt;left&lt;/a&gt; and &lt;a href=&quot;https://www.reddit.com/r/reactjs/comments/4iei7s/twitters_new_mobile_site_is_using_react_redux_and/&quot;&gt;right&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The only problem was, React was a templating engine at heart. Facebook did not build a bridge for
existing front-end frameworks, so that people could have just dropped in React instead of say,
Handlebars or even ERB. Facebook did not do this because they already had their
&lt;a href=&quot;http://hacklang.org/&quot;&gt;own way of rendering content&lt;/a&gt;. They didn’t need one. Build your own, they
said.&lt;/p&gt;

&lt;p&gt;Faced with just a templating engine, developers got confused. “How do I do routes with this?” they
asked. So we built &lt;a href=&quot;https://github.com/ReactTraining/react-router&quot;&gt;routing engines&lt;/a&gt; and
&lt;a href=&quot;https://github.com/reactjs/redux&quot;&gt;state containers&lt;/a&gt;, and got on with our lives. Soon after that,
someone understood
&lt;a href=&quot;http://jamesknelson.com/universal-react-youre-doing-it-wrong/&quot;&gt;React ran quite fine on a Node.js server&lt;/a&gt;,
and people started
&lt;a href=&quot;https://scotch.io/tutorials/react-on-the-server-for-beginners-build-a-universal-react-and-node-app&quot;&gt;rendering pages in two places: the backend &lt;em&gt;and&lt;/em&gt; the front-end&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, people are using React – a JavaScript library to be run inside a browser – to create
&lt;a href=&quot;https://facebook.github.io/react-native/&quot;&gt;native mobile applications&lt;/a&gt;. Meanwhile, other folks
think, all of this, this excession, is simply too much, and want &lt;a href=&quot;https://www.ampproject.org/&quot;&gt;pages to load quickly&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Couple this with the at least
&lt;a href=&quot;https://medium.com/@kitze/how-it-actually-feels-to-write-javascript-in-2016-46b5dda17bb5#.jnsf71d1l&quot;&gt;bizarre&lt;/a&gt;
experience of JavaScript development in 2016, things are looking weird. The tooling iterates at an
impossible speed, a new build system emerges every year, and developers must stay on top of things.&lt;/p&gt;

&lt;p&gt;Having to stay on top of things is, generally, a good thing. Software progresses, it progresses so
fast that we &lt;em&gt;must&lt;/em&gt; constantly learn for us to stay employable and the profession to stay
enjoyable. But at this speed, when it seems we’re not really learning from the past, it’s not doing
anyone any good. React took a good idea from desktop applications, event-driven user interface
rendering, and executed it brilliantly as they ported it to the web.&lt;/p&gt;

&lt;p&gt;The thing is, it’s still &lt;em&gt;nothing&lt;/em&gt; new. Ten years ago we were building crappy and weird-looking
software in C#, now we’re building crappy and broken software in a mix of JavaScript and other
languages, and they run in the browser, or on smartphones, and they’re responsive, so that when you
tilt your tablet sideways, that big fat menu disappears. Huh.&lt;/p&gt;

&lt;p&gt;That’s what they call the churn.&lt;/p&gt;

&lt;p&gt;The churn. New technologies come and they kill the old technologies, but in the midst of it all,
stand you and I, wondering what the hell to do with this mess. From the other side of it all, from
the ivory tower of the real world, the business analysts cast their shadow and remind us these
technologies are tools, they’re meant to be replaced, they’re &lt;em&gt;disposable&lt;/em&gt;. So are we, if we can’t
learn new ones, they remind keep reminding us.&lt;/p&gt;

&lt;h2 id=&quot;so&quot;&gt;So?&lt;/h2&gt;

&lt;p&gt;I make it sound as if web development is impossible, but that couldn’t be further from the
truth. Browsers are getting better and faster. Our applications are prettier, faster, more
accessible, more usable. The web is replacing desktop applications and this trend is accelerating –
whether this is a good or bad thing, I don’t know.&lt;/p&gt;

&lt;p&gt;The only problem is that the development experience keeps reinventing itself at such a pace you may
as well put yourself into stasis and wait for things to settle. Wait for front-end development to
become &lt;em&gt;boring&lt;/em&gt;. Odds are you can sleep for quite a bit until that happens. The second option is
just to pick whatever works &lt;em&gt;right now&lt;/em&gt; and use it.&lt;/p&gt;

&lt;p&gt;The optimistic part is that we, as web developers, are learning, we’re doing some
&lt;a href=&quot;https://clojurescript.org/&quot;&gt;cool things&lt;/a&gt; and &lt;a href=&quot;http://udash.io/&quot;&gt;unifying&lt;/a&gt; two halves of the same
thing. The backend guys are &lt;a href=&quot;http://mbrace.io/&quot;&gt;innovating&lt;/a&gt; and tooling progress is
&lt;a href=&quot;http://mesos.apache.org/&quot;&gt;insane&lt;/a&gt; and &lt;a href=&quot;http://kubernetes.io/&quot;&gt;exciting&lt;/a&gt;. So I cannot state that we
haven’t gotten anywhere, we &lt;em&gt;have&lt;/em&gt; innovated, learned, and improved the Web. But by how much? Are
our end users happier?&lt;/p&gt;

&lt;h1 id=&quot;a-concrete-solution&quot;&gt;A concrete solution&lt;/h1&gt;

&lt;p&gt;Given the task of implementing a web application, what would I do, given the state of the art in
2016? I spent about four years developing SPAs with many frameworks. I hate them all. Given that
sentiment, this is what I would do:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Using a language of your choice, build a business logic API that can be used via REST or some
other RPC protocol. The language and its associated tooling should be performant and support
rapid iteration.&lt;/li&gt;
  &lt;li&gt;Use a &lt;a href=&quot;http://rubyonrails.org/&quot;&gt;batteries-included&lt;/a&gt; web framework, spiced with
a &lt;a href=&quot;https://github.com/reactjs/react-rails&quot;&gt;rendering framework&lt;/a&gt; of your choice, to create front-end.&lt;/li&gt;
  &lt;li&gt;Build many front-ends, not just for the web, but for mobile and perhaps even desktop, and keep
them thin.&lt;/li&gt;
  &lt;li&gt;The web front-end can be spiced up (but not replaced) using JavaScript. Come to think of it, I
would have done the same thing in 2006.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Point 4. originates from my experiences of creating and maintaining SPA applications. I think SPAs
are, by and large, a bogus concept. A web application loading another page isn’t intrinsically a bad
idea, if your application is fast enough. Conversely, if your SPA is slow, you’re doing it
wrong. SPAs were invented for speed, because conventional web frameworks were slow. This is not the
case anymore. Sure, you won’t see Rails, Django or Play beat the TechEmpower benchmarks, but we’ve
come a long way from five years ago, which is when people started to play around with SPAs.&lt;/p&gt;

&lt;p&gt;Given the speed improvements, why not go full-stack? Why a front-end and a back-end?&lt;/p&gt;

&lt;p&gt;The answer for this is not simple. It is because we’re dealing with two incompatible abstractions:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Building your application as an API means you need a client application to provide the user
interface.&lt;/li&gt;
  &lt;li&gt;To build such an interface, your application has to deal with the fact that HTTP, and thus REST,
is stateless.&lt;/li&gt;
  &lt;li&gt;Web applications are usually stateful.&lt;/li&gt;
  &lt;li&gt;This leads inevitably to the requirement of building an abstraction in the middle that handles
client state, which your API does not support.&lt;/li&gt;
  &lt;li&gt;Building such an abstraction – the front-end – requires a lot of work, e.g. by using a MVC (or
MVVM whatever) model. Double the work, half the fun.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, the back-end abstraction is incompatible with client state, but the front-end application
requires client state. Conversely, a full-stack application is often a heavy monolith: it needs to
handle data access, its modification and its presentation in the same package. Here, as they say, be
dragons. We want to keep business logic and presentation logic separate, hence, a full-stack
framework does not work on its own.&lt;/p&gt;

&lt;p&gt;As a solution, I offer a synthesis. It’s mixing a REST back-end with a full-stack frontend. The
back-end can be built using whatever language is performant and maintainable. Build your front-end
with a boring framework like Rails, Django or Pyramid; let it fetch its data from the REST API,
i.e., treat the API as the data source. Let the front-end handle client state on its own. What you
get in return:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The ease of use of said framework. These frameworks were invented for a reason. You get routing,
templating, asset pipelines etc. out-of-the-box.&lt;/li&gt;
  &lt;li&gt;You can still do AJAX
requests &lt;a href=&quot;http://guides.rubyonrails.org/working_with_javascript_in_rails.html&quot;&gt;easily&lt;/a&gt; to build
rich user interfaces.&lt;/li&gt;
  &lt;li&gt;A reusable API in the backend you can use in other applications, keep your web front-end an equal
citizen.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you don’t want to deal with framework bloat, or if you’re scared of non-JavaScript applications,
be my guest, build your own front-end using the essentials. Splurge in Gulp, ES6, React, and
Redux. Or use TypeScript. But I dare say, after having worked with both full-stack frameworks
(e.g. Rails) and SPA+REST frameworks, the compromise above is much more pleasant.&lt;/p&gt;

&lt;p&gt;In the end though, it doesn’t really matter: with the exception of a few, our end users couldn’t
care less. They really don’t give a shit. So, pick whatever technology works for you and your
users. The above is just one option.&lt;/p&gt;

        </description>
        <pubDate>Tue, 25 Oct 2016 00:00:00 +0000</pubDate>
        <link>http://ane.iki.fi/2016/10/25/web-development-has-become-weird.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2016/10/25/web-development-has-become-weird.html</guid>
      </item>
    
      <item>
        <title>Communicators: Actors with purely functional state</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;In Scala, Akka actors, as in the traditional &lt;a href=&quot;http://en.wikipedia.org/wiki/Actor_model&quot;&gt;Actor model&lt;/a&gt;, may
modify private state. The accepted convention is to have a mutable object (e.g. a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Map&lt;/code&gt;), a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var&lt;/code&gt;, and mutate it like so:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Library&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Actor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;collection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;mutable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;receive&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Receive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Library&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is a bad idea. There are several reasons for this. First, Scala eschews &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var&lt;/code&gt;s, they should
only be used when absolutely necessary (read: never). There is also an additional need for
thread-safety for the collection, not because of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;receive&lt;/code&gt; method itself. &lt;!--break--&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;receive&lt;/code&gt; method
is
&lt;a href=&quot;http://doc.akka.io/docs/akka/2.4.11/general/jmm.html&quot;&gt;guaranteed to run inside a single thread&lt;/a&gt;. However,
an unsuspecting user might still launch a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Future&lt;/code&gt; and modify the collection, leading to
unpredictable behaviour. Such concurrent mutations on a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var&lt;/code&gt; put strain on the garbage collector,
in fact, it often necessitates the existence of a garbage collector.&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; Lastly, as with any mutable
state and possible lack of referential transparency, the code can become hard to reason about.&lt;/p&gt;

&lt;p&gt;Thankfully, Akka actors offer a possibility to do this completely functionally. The function
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context.become&lt;/code&gt; allows an Actor to change its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;receive&lt;/code&gt; method on-the-fly. In other words, it lets
the Actor change its state and communication model. Here’s the above implemented using this
paradigm:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Library&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Actor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Receive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// for immutable maps, += returns a new collection&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)))&lt;/span&gt; 
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;active&lt;/code&gt; function returns a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Receive&lt;/code&gt;, receiving the current actor &lt;em&gt;state&lt;/em&gt; as its
parameter. Adding logic to it is now easy:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Library&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Actor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Receive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)))&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Too many books&quot;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The above code is now thread-safe and doesn’t use mutable collections, but what if our logic gets
more complicated? What if we need to talk to another Actor, or talk to the sender of the message?
This is where we stumble upon a design feature of Akka: &lt;em&gt;all&lt;/em&gt; of its Actors are actually compiled
down into a callback-based implementation. There is no guarantee that a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Future&lt;/code&gt; launched in a
receive case will be running in the same thread as the next! One could argue that this is not a
feature but a &lt;em&gt;flaw&lt;/em&gt;, but I won’t go that far. Hence, code dealing with Futures in Akka actors needs to deal with the unforgiving reality that there is no
guarantee of thread safety. Case in point:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Library&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;popReservation&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Actor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Receive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// as before&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AskForBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nf&quot;&gt;popReservation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// AAH!!!&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Here you go: $i&quot;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Why am I screaming in the comments? First, as calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; for our Future launches a new thread, we
have no idea whether &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sender()&lt;/code&gt; returns the same value in the new thread, and second, we may be
modifying the books collection concurrently with other threads - leaving the garbage collector to
collect our mess. So we strain the GC &lt;em&gt;and&lt;/em&gt; risk giving the book to the wrong caller!&lt;/p&gt;

&lt;p&gt;Since the actual execution of a Future is left to the execution context, which in the case of Actors
is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ActorSystem&lt;/code&gt;s dispatcher, we may or may not be invoking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sender()&lt;/code&gt; in the right thread
— there is simply no guarantee. We can’t reason about it, it has been hidden from us.&lt;/p&gt;

&lt;p&gt;To deal with this, Akka has introduced the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pipe&lt;/code&gt; pattern, which is an implicit given to Futures
which solves this:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Library&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;popReservation&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Actor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Receive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// as before&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AskForBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// launch another thread&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;reservation&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;popReservation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Here you go: $i&quot;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// AAH!&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// but sender() is still the same&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;reservation&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pipeTo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Another option is to fix the reference of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sender&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;reservation&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;popReservation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Here you go: $i&quot;&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// AAH!&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok, now we’ve fixed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sender()&lt;/code&gt;, but what about the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;books&lt;/code&gt; collection? Let’s add a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PopBook(isbn:
String)&lt;/code&gt; case class, and handle that for removals:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Library&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;popReservation&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Actor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Receive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// as before&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PopBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;become&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AskForBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// launch another thread&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;reservation&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;popReservation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Here you go: $i&quot;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PopBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// but sender() is still the same&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;reservation&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pipeTo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sending messages to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;self&lt;/code&gt; is always thread-safe - the reference does not change over time. So, at
this point, it seems clear that making actor code thread-&lt;em&gt;sane&lt;/em&gt; involves the use of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;immutable state - call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context.become&lt;/code&gt; with a closure over the new actor state,&lt;/li&gt;
  &lt;li&gt;converting asynchronous state modifications as messages to be handled later, and&lt;/li&gt;
  &lt;li&gt;making sure the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sender()&lt;/code&gt; reference is consistent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What about complicated states? What if we need to react differently to these messages, e.g., when
the library is closed? I sense that you’re about to mention Akka’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FSM&lt;/code&gt; construct, which
builds a state machine, encapsulating state and transitions to what is essentially syntactic sugar,
and on the surface, seems like a good idea.&lt;/p&gt;

&lt;h2 id=&quot;enter-akka-fsms&quot;&gt;Enter Akka FSMs&lt;/h2&gt;

&lt;p&gt;At a closer look, it essentially leads us to repeat the same mistakes as above, and the arguments
against it are argumented &lt;a href=&quot;https://github.com/alexandru/scala-best-practices/blob/master/sections/5-actors.md#55-should-not-use-akka-fsm&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;. In
summary, it boils down to:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Akka FSM’s is too restrictive. You cannot handle multi-step or complicated state transitions, and
modeling undeterministic behaviour is impossible.&lt;/li&gt;
  &lt;li&gt;You are tied to Akka completely, you must use Akka testkit for your tests. Anyone who has worked
with testkit knows this to be a burden.&lt;/li&gt;
  &lt;li&gt;State transitions have identity instead of being truly functional, that is, FSMs alter the
&lt;em&gt;current&lt;/em&gt; state instead of &lt;em&gt;producing&lt;/em&gt; a new one.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Moreover, and I think this is the biggest shortcoming, the Akka FSM are finite-state &lt;em&gt;automata&lt;/em&gt;
— they are characterised by the state transition function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(Input, State) =&amp;gt; State&lt;/code&gt;. Since we
know actors are more about communication than anything else, this model is insufficient, and what we
need is a state machine that can produce &lt;em&gt;output&lt;/em&gt;: a finite state &lt;em&gt;transducer&lt;/em&gt;. Its state transition
function has the signature &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(Input, State) =&amp;gt; (Output, State)&lt;/code&gt; - every transition produces an
output, and Scala can model this efficiently:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FSA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;Input&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;Output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With all these flaws, despite being a nice idea at a glance, it’s obvious that for any complicated
logic Akka FSM’s aren’t sufficient.&lt;/p&gt;

&lt;p&gt;Let’s envision a radical version of actors, accounting for all the flaws described above:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;State transitions should be about producing a new state, i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(Input, State) =&amp;gt; (Output, State)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Actor computations will deal with asynchronous code, we must deal with this intelligently&lt;/li&gt;
  &lt;li&gt;Keep I/O logic out of actors - the actor only communicates with the external world&lt;/li&gt;
  &lt;li&gt;Actors should only mutate their state with with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;context.become&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last bullet point is especially important, as it constrains state changes
to be entirely functional, as you can simply make a function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;def foo(state:
State): Receive&lt;/code&gt;, and keep calling it recursively, by transitioning states
thusly:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Receive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;someInput&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Input&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;become&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This idea is not new. Erlang actors have worked like this for actual decades,
and arguments for using this method in Scala can be found left and right, summarized particularly well in
Alexandru Nedelcu’s &lt;a href=&quot;https://github.com/alexandru/scala-best-practices/blob/master/sections/5-actors.md#52-should-mutate-state-in-actors-only-with-contextbecome&quot;&gt;Scala best practices&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-erlang highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;receive&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;From&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;GetValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;From&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Sum&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;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Putting emphasis on the last point, I’ve come up with a moniker called &lt;em&gt;communicators&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;actor-meet-communicator&quot;&gt;Actor, meet communicator&lt;/h2&gt;

&lt;p&gt;Let’s define the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Communicator&lt;/code&gt; trait first independently:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Communicator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;Input&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;Output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Actor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;cm&quot;&gt;/** This is the initial actor state */&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initial&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;

  &lt;span class=&quot;cm&quot;&gt;/** The state transition function */&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)]&lt;/span&gt;

  &lt;span class=&quot;cm&quot;&gt;/** The output processing function */&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ActorRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Unit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initial&lt;/code&gt; is simply the initial state machine state, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process&lt;/code&gt; is the state transition function and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;handle&lt;/code&gt; is the function that will deal with dispatching the result of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process&lt;/code&gt;. Because we’re
producing content in another thread, we want to make sure the reference of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sender&lt;/code&gt; is fixed, and by
using this with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pipeTo&lt;/code&gt; pattern, we get thread safety. Let’s extend the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Actor&lt;/code&gt; trait to get
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;receive&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Communicator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;Input&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;Output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Actor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;cm&quot;&gt;/** This is the initial actor state */&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initial&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;

  &lt;span class=&quot;cm&quot;&gt;/** The state transition function */&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ActorRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Unit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;cm&quot;&gt;/** The output processing function */&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)]&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;initial&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  
  &lt;span class=&quot;cm&quot;&gt;/** I/O handling which the deriving class must implement */&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newState&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Receive&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;active&lt;/code&gt; function is the actual output-producing function. The user is left to define three
things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the initial actor state in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initial&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;the output dispatch function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;handle&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;the state transition function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;active&lt;/code&gt; function which handles input and output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To see this in action, first, let’s define the application states.&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Library&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Library state&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LibraryState&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;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Input alphabet&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;sealed&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LibraryInput&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SetOpen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;                  &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Input&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Input&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GetBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;                &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Input&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Output alphabet&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;sealed&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LibraryOutput&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SorryWeAreClosed&lt;/span&gt;                        &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Output&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DoNotHaveIt&lt;/span&gt;                             &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Output&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SorryReserved&lt;/span&gt;                           &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Output&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Output&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Reservation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Output&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The actual state is just a case class: this gives us the nice &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copy&lt;/code&gt; function for easy updates. Then
we use polymorphism to implement the input and output alphabets. Then we implement the actor itself:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Library&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getReservation&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Communicator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LibraryState&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;LibraryInput&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;LibraryOutput&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Library._&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initial&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;collection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;immutable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newState&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LibraryState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Receive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LibraryOutput&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ActorRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LibraryInput&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;origin&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;nf&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SetOpen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;successful&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;copy&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;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)))&lt;/span&gt;

      &lt;span class=&quot;nf&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;GetBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;open&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;successful&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;SorryWeAreClosed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GetBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;book&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;getReservation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reserved&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
              &lt;span class=&quot;nf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reserved&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;SorryReserved&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;book&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getOrElse&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;successful&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DoNotHaveIt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;successful&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))))&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ActorRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Unit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Future&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;decoupling-akka&quot;&gt;Decoupling Akka&lt;/h2&gt;

&lt;p&gt;So, now we’ve made a very thin actor, with little I/O logic inside it, but it’s still an
actor. Let’s decouple it entirely from actor semantics. First, we define a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StateMachine[I, O]&lt;/code&gt;
trait:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StateMachine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;I&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;StateMachine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;I&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And excise the state logic from the Communicator, moving it to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;State&lt;/code&gt; case class:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LibraryState&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;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getReservation&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])(&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ExecutionContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StateMachine&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LibraryInput&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;LibraryOutput&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LibraryInput&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LibraryOutput&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;LibraryState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SetOpen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;successful&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;copy&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;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)))&lt;/span&gt;

      &lt;span class=&quot;nf&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;GetBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&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;k&quot;&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;successful&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;SorryWeAreClosed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()))&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GetBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;book&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;getReservation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reserved&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
              &lt;span class=&quot;nf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reserved&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;SorryReserved&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
              &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;book&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getOrElse&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;successful&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Some&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DoNotHaveIt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()))&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddBook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;successful&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isbn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))))&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You may be wondering: wait, where’s the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;handle&lt;/code&gt; implementation? We kept that out from the state
machine class since it’s not its responsibility - so we keep that in the Communicator:&lt;/p&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Library&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getReservation&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Future&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Communicator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;LibraryInput&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;LibraryOutput&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;LibraryState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;context.dispatcher&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initial&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LibraryState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;collection&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;immutable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getReservation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LibraryOutput&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ActorRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newState&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LibraryState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Receive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LibraryOutput&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ActorRef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LibraryState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;become&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LibraryInput&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;origin&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;newState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&amp;gt;&lt;/span&gt; 
            &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, all state is kept neatly in a separate entity that’s entirely unit testable in its own right
without having to rely on Akka testkit or the like – input and output dispatch and state
transitions are done in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;active&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;I know the state case class manipulation introduces more boilerplate, but as long as that
boilerplate isn’t complicated, I think this is a fair compromise. Plus, one can
use &lt;a href=&quot;https://github.com/julien-truffaut/Monocle&quot;&gt;lenses&lt;/a&gt; to remove some of the boilerplate, e.g., 
by defining handy update functions. One could cook up something doggedly interesting using &lt;a href=&quot;http://typelevel.org/cats&quot;&gt;Cats&lt;/a&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StateT&lt;/code&gt; - as long as you provide a function of the kind &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(I, S) =&amp;gt; (Option[O], S)&lt;/code&gt;, the sky is the limit.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to Jaakko Pallari (@jkpl) for previewing this.&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This is actually false, as Aaron Turon, a core Rust developer, proves in his article about &lt;a href=&quot;demonstrates&quot;&gt;getting lock-free structures without garbage collection&lt;/a&gt;. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;

        </description>
        <pubDate>Fri, 14 Oct 2016 00:00:00 +0000</pubDate>
        <link>http://ane.iki.fi/2016/10/14/communicator-functional-actors.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2016/10/14/communicator-functional-actors.html</guid>
      </item>
    
      <item>
        <title>Focus</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;Focus is a design element in programming languages that I think deserves more attention than it
gets.&lt;/p&gt;

&lt;p&gt;A focused language puts emphasis on a set of coherent idioms. Multi-paradigm languages like C++ or
C# are unfocused because they lack a certain principle.&lt;/p&gt;

&lt;p&gt;Take C, for instance. You &lt;em&gt;can&lt;/em&gt; do OOP in C, but it’s awkward. You need structures full of function
pointers and the language wasn’t designed for it: it’s not a good idea to do it. The point is that
you &lt;em&gt;can&lt;/em&gt; but you shouldn’t. 
&lt;!--break--&gt;&lt;/p&gt;

&lt;p&gt;Focus is not so much of what a language &lt;em&gt;has&lt;/em&gt; but something that it &lt;em&gt;embodies&lt;/em&gt;. A single-paradigm
language can still be unfocused, because there can be several ways to wield the singular paradigm. A
multi-paradigm language can be focused if the multi-paradigm languages connect at a higher
level. Focus can be implemented as a coding standard or it can be something that everybody
understands as the idiomatic way of doing things.&lt;/p&gt;

&lt;p&gt;Focus is not always a positive trait but it rarely is a negative trait. On the other hand, a lack of
focus is more often negative than positive.&lt;/p&gt;

&lt;p&gt;Take Haskell, a pure functional language, effectively single-paradigm; it is a very special
case. The language itself is absolutely focused to the point of extreme autism, but its flexible
type system and vibrant community, there are many ways to program Haskell. Do you absolutely need
state? Use state, but be careful. Do you want IO without monads? Well, sure, but be careful.&lt;/p&gt;

&lt;p&gt;At a high level, Haskell code is &lt;em&gt;pure&lt;/em&gt;. It permits some inconsistencies with its principal paradigm
but it eschews them and this is the key difference.&lt;/p&gt;

&lt;p&gt;A bigger problem with focus is that it often is intangible. It’s easier to point out languages that
are unfocused than those that are. Focus is about philosophy. Some language are very
philosophical. For instance, Clojure is just as much about its particular approach to concurrency,
state and identity, that is a language implementing those ideas. The language caught on because
Rich Hickey, the author, did not market it as the tool that would have solved everybody’s problems,
but because he marketed the &lt;em&gt;ideas&lt;/em&gt; that Clojure represented as a solution to common programming problems.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“If you want to build a ship, don’t drum up the men to gather wood, divide the work and give
orders. Instead, teach them to yearn for the vast and endless sea.”&lt;/p&gt;

  &lt;footer class=&quot;blockquote-footer&quot;&gt;Antoine de Saint-Exupéry&lt;/footer&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this context, Clojure can be seen as a focused language. These core philosophies are what
constitute the language, the fact that Clojure happens to be a Lisp dialect implementing the
philosophies is secondary in my mind. With that in mind, I acknowledge being a Lisp is also a core
part of Clojure, but its principles about state and identity can be implemented in any
language. Clojure does &lt;em&gt;let&lt;/em&gt; you do OOP but it feels awkward. When you grok Clojure you understand
what that means: the language can be bent for that purpose, but it doesn’t want to be. Its
philosophy is like a memory-foam, if you tamper with it, it will coalesce back into its original
form. When you see &lt;em&gt;that&lt;/em&gt;, it’s the moment you understand what Clojure—or any other language—is
about.&lt;/p&gt;

&lt;p&gt;Some languages double down on philosophy by making it a part of a coding standard and enforcing it:
Go. Go embodies simplicity and intuition, intentionally eschewing things that are not modern, but
complex, opting to keep the core language simple. Some chalk this down as a negative trait, others
love it; I find it to be both good and bad. Good, because I can jump into any Go codebase and get
its purpose in minutes; bad, because sometimes I want to use abstractions for which Go is
unsuitable. I respect its design philosophy, because it has one, and absolutely flaunts it. It’s not
just a structural type system, it’s an &lt;em&gt;idea&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Scala is another beast. It began as an experiment, trying to augment and fix the deficiencies of
Java. It was designed by brilliant PLT theorists and the language is a beautiful and magnanimous
behemoth. Scala has so many features that it eschews focus either intentionally or
unintentionally. On the other hand, Scala is capable of many great things. But if you ask two Scala
programmers what Scala represents to them, you may get different answers.&lt;/p&gt;

&lt;p&gt;It can be a technical aspect. To some, it might be about Shapeless or all the cool things that go
with it. Macros. DSLs. Code generation. Or it could be how Akka or Spark are amazing tools.  It
could also be a philosophical difference. Some people want an advanced type system and don’t want to
be constrained by the laziness and purity of Haskell. Others want the JVM. Some just want a better
Java. Some just happen to use it for Spark.&lt;/p&gt;

&lt;p&gt;I would choose the simpler Scala, the better Java. Trait-based generics, sum types, implicits, and
functional programming, to name a few. This is not just because it’s less complicated, from a
business perspective, it makes it easier to hire new programmers.&lt;/p&gt;

&lt;p&gt;As a professional Scala developer and a long-time functional programming enthusiast, I fear that I
may never comfortably jump to another company, confident that since I’ve written Scala, I can
understand their Scala. That, or years of experience, but who knows what’s enough? Their, whoever
they may be, Scala might not be the simple Scala I and my colleagues prefer.&lt;/p&gt;

&lt;p&gt;This is scary. For the future of the language, this is an untenable position. While I absolutely
enjoy working with the language, I’m afraid that it is fated to be like Macbeth from Shakespeare:
“thou shalt get kings, though thou be none”. Thus, Scala will inspire a great language and then
die. Maybe it already did, and the clock is ticking. Some purport Kotlin as the successor, but I
wouldn’t bet on it just yet.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Ah, but a man’s reach should exceed his grasp, or what’s a heaven for?”&lt;/p&gt;

  &lt;footer class=&quot;blockquote-footer&quot;&gt;Robert Browning&lt;/footer&gt;
&lt;/blockquote&gt;

&lt;p&gt;The thing about Scala is that this is a conscious design decision. The language is &lt;em&gt;meant&lt;/em&gt; to have
everything and the kitchen sink. Programming languages don’t have to be simple. Powerful languages
are powerful tools. Use them well, you can achieve greatness. You have to &lt;em&gt;choose&lt;/em&gt; your tool set and
hone it.&lt;/p&gt;

&lt;p&gt;But for Haskell, Go, and Clojure, you’re using them, and you’re thinking, what is the natural way to
do this? Once you find it, you find yourself implementing ideas using that philosophy, that natural
way, and you’re no longer just using a tool. You’re using an &lt;em&gt;idea&lt;/em&gt;.&lt;/p&gt;

        </description>
        <pubDate>Fri, 25 Mar 2016 00:00:00 +0000</pubDate>
        <link>http://ane.iki.fi/2016/03/25/focus.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2016/03/25/focus.html</guid>
      </item>
    
      <item>
        <title>Imprecision and abstraction</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;What is the point of abstractions?&lt;/p&gt;

&lt;p&gt;We want to hide things. We want to generalize things. We want to extend things.&lt;/p&gt;

&lt;p&gt;Why are mathematical abstractions so intractable? Why is the 
&lt;a href=&quot;https://en.wikipedia.org/wiki/Functor&quot;&gt;Wikipedia page on functors&lt;/a&gt; incomprehensible to someone not
used to mathematical formalisms? Why does it sound so vague?&lt;/p&gt;

&lt;p&gt;When approaching abstractions, for educational purposes, it is sometimes easier to think of
analogies or similes. We can conceptualize the idea of functors of “procedures” that operate on things inside
“boxes”, or we can study relational algebra using Venn diagrams.&lt;!--break--&gt;&lt;/p&gt;

&lt;p&gt;These analogies are dangerous, because they are vague. Formalisms leave no room for interpretation
because they are exact not whimsically, but because of the pervasive imprecision of the human mind.&lt;/p&gt;

&lt;p&gt;Let’s take an analogy that’s very approachable but quite dangerous. Explaining modular arithmetic
can done with clocks. The analogy would go like this:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;You see, when you have a number modulo 12, think of it as a clock. If x is over 12, think
of like like the hand of a clock looping over, and you’re back where you started.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The problem with such an analogy is that not everybody uses 12-hour clocks. Most of Europe uses a
24-hour clock with no distinction between AM and PM. Of course, they are also taught to understand
that “sixteen” means “four” since nobody builds 24-hour analog clocks (yet). That aside, it’s still
very possible, that when explaining the above analogy to someone accustomed to 24-hour clocks,
they’ll get confused since what comes after 12, is 13, not 0.&lt;/p&gt;

&lt;p&gt;This is a basic but fundamental example: things like functors, semigroups, monads, and categories,
are a bit intractable for a reason: there’s no room left for interpretation.&lt;/p&gt;

&lt;p&gt;Mathematical formalisms pare fundamental ideas into pure forms. Your intuition can’t get in the way
and corrupt them.&lt;/p&gt;

&lt;p&gt;The obvious downside is that these formalisms are harder to understand. I wager that this is for the
better because down the road there are concepts so high-level one can’t even begin to think in
analogies, and it will only slow one down.&lt;/p&gt;

&lt;p&gt;There was a turning point in my math studies when I stopped trying to grok things using
analogies. My approach to topology was geometrical. I tried to visualize
&lt;a href=&quot;https://en.wikipedia.org/wiki/Limit_point&quot;&gt;limit points&lt;/a&gt; in my mind and in vain, because the mind
can’t bend itself around more than three spatial dimensions. Granted, visualizing
&lt;a href=&quot;https://en.wikipedia.org/wiki/Hypercube&quot;&gt;hypercubes&lt;/a&gt; was possible (“like a cube is made of sides, a
hypercube is made of cubes”)… kind of.&lt;/p&gt;

&lt;p&gt;Stopping this perilous habit, I started to memorize laws instead. That changed the language of maths
for me, forever. I wasn’t understanding relations via shapes or arrows, but by basic axioms and
mathematical laws. It wasn’t too long before I started to visualize concepts using these laws.&lt;/p&gt;

&lt;p&gt;I stopped staring concepts in the eye, looking for hidden meanings behind
&lt;a href=&quot;https://en.wikipedia.org/wiki/Bounded_set&quot;&gt;bounded sets&lt;/a&gt;. I simply read
the definition, thought “huh”, and memorized it. Slowly, by building towards other related concepts
and set theory I quickly understood what the law meant, without trying to grok the hidden meaning.&lt;/p&gt;

&lt;p&gt;Once that became a habit, it became easy and changed my approach forever: let go of
intuition. Abstract ideas are hard by definition and they need to be understood piece by piece, from
the ground up.&lt;/p&gt;

&lt;p&gt;This is why any explanation of a precise thought, like a mathematical formalism, using something
imprecise like an analogy, is a fallacy doomed to fail.&lt;/p&gt;

&lt;p&gt;When functional programmers try to explain basic ideas like semigroups or functors, they often find
themselves in an apologetic mire of simplifications. This is doomed to fail. Give concrete examples
of how a functor works. Don’t illustrate them as operations that can map stuff in boxes to other
boxes. Invent a problem and solve it using a functor. After all, they’re such a basic concept, even
those writing non-functional code end up doing them all the time.&lt;/p&gt;

&lt;p&gt;Let the abstraction sink in, it’s the only thing that will survive.&lt;/p&gt;


        </description>
        <pubDate>Thu, 17 Mar 2016 00:00:00 +0000</pubDate>
        <link>http://ane.iki.fi/2016/03/17/imprecision-and-abstraction.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2016/03/17/imprecision-and-abstraction.html</guid>
      </item>
    
      <item>
        <title>Are my services talking to each other?</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;I am faced with an interesting thought experiment, which asks:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;If I can see two of my friends, and I know they should be communicating to each other, what is the
simplest way of making sure they are doing so?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your first instinct is to &lt;em&gt;look&lt;/em&gt; at them and &lt;em&gt;listen&lt;/em&gt;. What if the communication method is
subtler than that? What if you are, metaphorically speaking, &lt;em&gt;deaf&lt;/em&gt;, and cannot eavesdrop on their
conversation?
&lt;!--break--&gt;&lt;/p&gt;

&lt;p&gt;A problem like arises when you have a non-trivial amount of distributed components talking to each
other, forming a complex network. Let’s start from the basics and consider a simple one:&lt;/p&gt;

&lt;p class=&quot;text-center&quot;&gt;&lt;img src=&quot;/images/are-my-services-1-simple.png&quot; alt=&quot;A simple example&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;text-center&quot;&gt;&lt;em&gt;arrows indicate flows of information, i.e. x → y means x sends information to y&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You could assume &lt;strong&gt;A&lt;/strong&gt; is an event log, for example, of financial transactions; &lt;strong&gt;B&lt;/strong&gt; is a message
queue and &lt;strong&gt;C&lt;/strong&gt; is a fast queryable cache for the transactions. We want to be able to query the
cache quickly for log events and rely on the message queue of transporting them from &lt;strong&gt;A&lt;/strong&gt; to &lt;strong&gt;C&lt;/strong&gt;,
while preferably not having a hard software dependency from &lt;strong&gt;A&lt;/strong&gt; to &lt;strong&gt;C&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The illusion is that while there are neither code nor protocol dependencies between &lt;strong&gt;A&lt;/strong&gt; and &lt;strong&gt;C&lt;/strong&gt;,
a semantic dependency exists: the one in our heads! &lt;strong&gt;A&lt;/strong&gt; is content on dumping information
towards &lt;strong&gt;B&lt;/strong&gt;, but what we’re really interested in is messages getting through all the way to
&lt;strong&gt;C&lt;/strong&gt;. So in reality, if we superimpose our perceived dependencies on top of information flows, we
end up with this:&lt;/p&gt;

&lt;p class=&quot;text-center&quot;&gt;&lt;img src=&quot;/images/are-my-services-3-simple.png&quot; alt=&quot;A simple example, part two.&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;tolerating-faults&quot;&gt;Tolerating faults&lt;/h2&gt;

&lt;p&gt;What if the chain breaks? What happens when A can’t push messages onward to B, and we get a
blackout? Who gets notified? C doesn’t know what’s happening in A, it’s just not getting
information! In line of the original question, if I can see both A and C are doing fine, but they’re
not talking to each other, where is or &lt;em&gt;who&lt;/em&gt; is the broken phone?&lt;/p&gt;

&lt;p&gt;With such a simple case as above, pointing this out is easy, so let’s make our network a bit more
complicated.&lt;/p&gt;

&lt;p class=&quot;text-center&quot;&gt;&lt;img src=&quot;/images/are-my-services-2-not-so-simple.png&quot; alt=&quot;A slightly more complex example&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;text-center mx-5&quot;&gt;&lt;small&gt;
&lt;em&gt;A - an event log; B - a message queue; C - a cache; E - app back-end; P - a user-facing
application; I - a business intelligence system; S - a storage system&lt;/em&gt;
&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Let’s assume each one of these components is an independent service, each load balanced and with
redundancies that aren’t visible beyond the node itself&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, and that communication is done over a
computer network using some protocol.&lt;/p&gt;

&lt;p&gt;The depicted network consists of a set of applications that all in one way or the other build on top
of an event log, A. In one branch, there’s a fast queryable cache for the transaction log, the app
back-end is an interface for the cache (like a REST API), and the storage acts as a long-term backup
system. The second branch consists of a business intelligence system that analyzes the event log
data and does something with it.&lt;/p&gt;

&lt;p&gt;Indirectly, there are dependency arrows emanating from the root of the network tree (A) to its
leaves S, P and I. From an observer’s perspective, these are the relationships that matter. These
are the &lt;em&gt;implicit dependencies&lt;/em&gt;. Furthermore, we can see those dependencies, but we build the code
in such a way that it does not! The event log simply dumps data to a message queue, and that’s
it. What is worse, is that the implicit dependencies each propagate up the chain. Not only does the
leaf node depend on the root node, it also depends on the intermediate nodes.&lt;/p&gt;

&lt;p class=&quot;text-center&quot;&gt;&lt;img src=&quot;/images/are-my-services-4-not-so-simple.png&quot; alt=&quot;A slightly more complex example&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;text-center&quot;&gt;&lt;small&gt;
&lt;em&gt;Implicit dependencies&lt;/em&gt;
&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;The inherent hazard in all this, of course, is that there’s a communication error. Even though we
(hopefully) built the system following the
&lt;a href=&quot;https://en.wikipedia.org/wiki/Robustness_principle&quot;&gt;robustness principle&lt;/a&gt;, data isn’t flowing from
the root node to the leaf nodes and we have to quickly identify where the disconnect happened.&lt;/p&gt;

&lt;h2 id=&quot;seeing-is-not-enough&quot;&gt;Seeing is not enough&lt;/h2&gt;

&lt;p&gt;Our first instinct is to peer at the logs. So we go through each &lt;em&gt;edge&lt;/em&gt; in the network and see if
there’s a fault. This means for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; nodes looking at least at &lt;em&gt;n-1&lt;/em&gt; edges for each fault! Moreover,
the problem isn’t fixed by using something that gives me &lt;em&gt;visibility&lt;/em&gt; of the nodes, like ZooKeeper
or other service discovery tools. This is because I am interested in the flow of information from
one node to another. The thought experiment already assumes that the nodes are there, only the
communication between them is broken.&lt;/p&gt;

&lt;p&gt;In the Internet world, with the
&lt;a href=&quot;https://en.wikipedia.org/wiki/Transmission_Control_Protocol&quot;&gt;Transmission Control Protocol&lt;/a&gt; ,
communication is made reliable using error-checking and acknowledgments. That means, if A were a
network element and wanted to send things over to C, in case of a successful delivery C will
acknowledge this back to A.&lt;/p&gt;

&lt;p&gt;For various reasons, it may be that in a distributed service network this approach is not
feasible. This is the cost of abstractions: when you enforce loose coupling, you have to deal with
the consequences of looseness. We &lt;em&gt;could&lt;/em&gt; build the transaction log aware of the user-facing
Application but that may be overkill.&lt;/p&gt;

&lt;p&gt;For the particular problem of &lt;em&gt;acknowledging&lt;/em&gt; from a message queue root to a consumer leaf, there
are various solutions. You either implement this on your own, which while laborious, essentially
follows the principle of error-checking. The caveat is this grows in complexity with every new node.
Another option is to use a message queue
(&lt;a href=&quot;https://en.wikipedia.org/wiki/Apache_Kafka&quot;&gt;one of these things is not like the others&lt;/a&gt;) that supports
this natively.&lt;/p&gt;

&lt;h2 id=&quot;the-rescue-signal&quot;&gt;The rescue signal&lt;/h2&gt;

&lt;p&gt;We could build a centralized logging system to which each node logs its events. This centralized
system contains &lt;em&gt;all&lt;/em&gt; events from &lt;em&gt;all&lt;/em&gt; nodes. To make the data meaningful, you need to construct a
way to determine the flow of information, that is, grouping events together semantically. Worse, the
system will require manual or semi-automated inspection to determine when any event is missing its
acknowledgment, that is, A logged an event of sending &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt; to message queue but the user
application back-end &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;E&lt;/code&gt; never processed it.&lt;/p&gt;

&lt;p&gt;A system like this could work using a
&lt;a href=&quot;https://en.wikipedia.org/wiki/Functional_reactive_programming&quot;&gt;FRP&lt;/a&gt; approach: since FRP signals map
&lt;em&gt;exactly&lt;/em&gt; to discrete events, one could build a rule engine. By
&lt;a href=&quot;https://wiki.haskell.org/Functional_Reactive_Programming&quot;&gt;integrating time flow and compositional events&lt;/a&gt;,
a centralized system could use its rule engine to listen to signals. A signal can be any event,
e.g., a financial transaction that was logged into the event log. You can combine this signal with
another event in a system that &lt;em&gt;consumes&lt;/em&gt; transactions and does something with them, like the
business intelligence system. The sum of these two signals imply that “a financial transaction was
consumed by the business intelligence system”. This is also a signal!&lt;/p&gt;

&lt;p&gt;Building a FRP-based rule engine isn’t easy, you’d need to construct a rule engine that can map
diverse data events into high-level &lt;em&gt;signals&lt;/em&gt; and then create additional logic for &lt;em&gt;summing&lt;/em&gt; the
signals.&lt;/p&gt;

&lt;p class=&quot;text-center&quot;&gt;&lt;img src=&quot;/images/are-my-services-5-frp.png&quot; alt=&quot;The FRP approach&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;text-center&quot;&gt;&lt;small&gt;
&lt;em&gt;The sum of two signals is another signal. (Oh hey, this makes it a &lt;a href=&quot;https://en.wikipedia.org/wiki/Semigroup&quot;&gt;semigroup&lt;/a&gt;!)&lt;/em&gt;
&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Once such a system is built, it can be queried to determine the state of the network quite
efficiently (and perhaps elegantly), but it does not introduce any fault tolerance and will only
tell you where data &lt;strong&gt;is&lt;/strong&gt; moving, but not where it isn’t.&lt;/p&gt;

&lt;h2 id=&quot;lurking-in-the-shadows&quot;&gt;Lurking in the shadows&lt;/h2&gt;

&lt;p&gt;I guess that most of this stuff underlines the difficulties of unraveling a monolith into a
microservice. Keeping track of network traffic is really hard, even at the hardware level (!), so
when we push this abstraction to the software level, it is not a surprise that this can cause
problems.&lt;/p&gt;

&lt;p&gt;Playing with some toy solutions I thought of something I call a &lt;em&gt;shadow network&lt;/em&gt;. Let’s say our
principal information source is an event monitor &lt;strong&gt;X&lt;/strong&gt; and we have a &lt;strong&gt;leaf node&lt;/strong&gt; in the
information dependency tree that is interested in data originating from &lt;strong&gt;X&lt;/strong&gt;.&lt;/p&gt;

&lt;p class=&quot;text-center&quot;&gt;&lt;img src=&quot;/images/are-my-services-6-shadow.png&quot; alt=&quot;Shadows&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;text-center&quot;&gt;&lt;small&gt;
&lt;em&gt;Each leaf node sends its data to the shadow node. The shadow node understands the data and can
tell where it originated from, thereby seeing the implicit dependencies. The shadow node is
effectively a &lt;em&gt;mirror&lt;/em&gt; of the root node(s).&lt;/em&gt;
&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;In the shadow network, &lt;strong&gt;X&lt;/strong&gt; does not receive any new dependencies nor do the intermediaries, but
the leaf nodes each push their actions to the &lt;em&gt;shadow node&lt;/em&gt;. The shadow node contains a &lt;em&gt;rule
engine&lt;/em&gt; that can parse leaf events. A &lt;em&gt;rule&lt;/em&gt; is something that identifies a &lt;strong&gt;source&lt;/strong&gt;. It could be
anything, from a simple parser (“this looks like Apache logs” → “it came from Apache!”) to something
more sophisticated. This introduces a dependency only to leaf nodes, but the problem is that the
shadow node has to be kept up to date on how to correctly map events to sources. When you change the
format of the data traveling across the network, you have to update the rule engine.&lt;/p&gt;

&lt;p&gt;Unfortunately, this doesn’t really help us: you can query the shadow node to get the &lt;em&gt;implied
dependencies&lt;/em&gt;, but that’s it. So while it requires less effort to develop, disregarding cases where
creating rules causes difficulties, it suffers from the same flaw than the centralized FRP engine:
it can only tell when data &lt;strong&gt;is&lt;/strong&gt; flowing but not when it &lt;strong&gt;isn’t&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;no-easy-answers&quot;&gt;No easy answers&lt;/h2&gt;

&lt;p&gt;This makes both solutions rather untenable for monitoring a microservice architecture, but they can
be used in cases where the service network grows large and you are working with opaque layers, that
is, you &lt;em&gt;don’t know&lt;/em&gt; what’s between the leaves and the root, and you want to construct the implicit
dependency graph.&lt;/p&gt;

&lt;p&gt;Bolting temporal awareness in the shadow network works if the data is supposed to be regular. If the
consuming leaf expects a tick from the origin(s) every &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; seconds, the shadow rule engine can be
built to be aware of this. If ticks aren’t happening when they are supposed to, you can create a
fault on the implicit dependency. Alas, only regularly occurring data works here, so we’re out of
luck for irregular events.&lt;/p&gt;

&lt;p&gt;Either way, the original problem is an interesting one. I suppose the only reliable way of doing
things is to do what the Internet Protocol does: acknowledgment and error checking. While certainly
a lot of work, it will be reliable. We all love reinventing wheels, don’t we?&lt;/p&gt;

&lt;p&gt;My opinion? Don’t fix what isn’t broken! While we all benefit from loose coupling, and while
microservices definitely are &lt;em&gt;most of the time&lt;/em&gt; an improvement over monoliths, both bring hurdles
and challenges of their own. The bottom line is that networking is not easy, and if one forgets
this, problems &lt;em&gt;will&lt;/em&gt; occur.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;So for all intents and purposes the nodes represent services as a whole instead of individual
physical units, whatever they may be. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;

        </description>
        <pubDate>Tue, 26 Jan 2016 00:00:00 +0000</pubDate>
        <link>http://ane.iki.fi/2016/01/26/are-my-services-talking-to-each-other.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2016/01/26/are-my-services-talking-to-each-other.html</guid>
      </item>
    
      <item>
        <title>The expression problem as a litmus test</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Expression_problem&quot;&gt;expression problem&lt;/a&gt; is a famous problem in
programming languages.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“The Expression Problem is a new name for an old problem. The goal is to define a datatype by
cases, where one can add new cases to the datatype and new functions over the datatype, without		
recompiling existing code, and while retaining static type safety (e.g., no casts).”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Using &lt;em&gt;interfaces&lt;/em&gt; (like in Java) as the datatype example, the problem simply asks whether it is
possible to derive the interface and add new methods to the interface, without having to recompile
existing code or to resort to using casts.&lt;!--break--&gt;&lt;/p&gt;

&lt;p&gt;Obviously, in a OOP language it’s easy to derive interfaces, but the problem uncovers the rigidity
of the type system: you can’t modify (i.e. extend) the interface, because you have to modify all the
classes classes that implement the interface.&lt;/p&gt;

&lt;p&gt;Conversely, in functional programming languages, adding new methods operating on the interface is
easy. Consider the canonical OCaml example:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Circle&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Rectangle&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;area&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Circle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;radius&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14159&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;radius&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;radius&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Rectangle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;height&lt;/span&gt;
  
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertices&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; 
    &lt;span class=&quot;nc&quot;&gt;Circle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;infinity&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Rectangle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So in FP, you could create a function called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;volume&lt;/code&gt; that computes the volume for the existing
types, and you needn’t touch the above code. However, as soon as you do that, you realize you’ve
made a silly mistake: our shapes are &lt;em&gt;flat&lt;/em&gt; so their volume is zero. Quickly, you realize you need a
three-dimensional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cube&lt;/code&gt; shape.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;volume&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Circle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Rectangle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Cube&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;        &lt;span class=&quot;c&quot;&gt;(* Cube isn't defined *)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Oops!&lt;/p&gt;

&lt;p&gt;Here’s the onion: to get the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cube&lt;/code&gt; working, you’ll have to modify the existing code in two places:
the definition of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shape&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; both methods &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;area&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vertices&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In OOP, this isn’t the case, since you can just derive the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IShape&lt;/code&gt; interface and be done with
it, but the problem arises when you’re adding the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;volume&lt;/code&gt; function, because you need to modify
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IShape&lt;/code&gt;, and thus every class that derives it.&lt;/p&gt;

&lt;p&gt;In FP, adding new functions over the datatypes is easy, but adding new cases to the datatype is
tricky, because you have to modify existing functions. In OOP, adding new functions over the
datatype is hard, because you need to modify each implementation; adding new cases to the datatype
is easy, since all you need to do is derive the interface. FP has invented a multitude of ways to
deal with this problem, ranging from type classes, traits to protocols; OOP usually solves with
either patterns or open classes. Ruby’s
&lt;a href=&quot;http://devblog.avdi.org/2015/05/20/so-whats-the-deal-with-ruby-refinements-anyway/&quot;&gt;refinements&lt;/a&gt;
can be used for this purpose as well.&lt;/p&gt;

&lt;h2 id=&quot;polymorphic-variants&quot;&gt;Polymorphic variants&lt;/h2&gt;

&lt;p&gt;That’s a quick introduction to the problem. I think the expression problem is a perfect
&lt;a href=&quot;https://en.wikipedia.org/wiki/Litmus#Uses&quot;&gt;litmus test&lt;/a&gt; of sorts for programming languages, that
is, the measure of the expressive power of the language is the quality of the solutions the language
presents to the expression problem.&lt;/p&gt;

&lt;p&gt;The expression problem is theoretically solvable in any language, but to varying degrees of
elegance. In Java one must resort to using the
&lt;a href=&quot;https://en.wikipedia.org/wiki/Visitor_pattern&quot;&gt;visitor pattern&lt;/a&gt;, and in my mind this is the most
inelegant way of going about it. I would rate the solutions on a spectrum: with the most &lt;em&gt;basic&lt;/em&gt;
solution being the visitor pattern, at the other end we have something like
&lt;a href=&quot;http://www.math.nagoya-u.ac.jp/~garrigue/papers/fose2000.html&quot;&gt;polymorphic variants&lt;/a&gt; and type
classes. Multimethods and protocols are somewhere in between.&lt;/p&gt;

&lt;p&gt;When you compare polymorphic variants of OCaml with Haskell’s type classes, there’s a marked
difference in brevity. Polymorphic variants are succincter than type classes but cannot provide the
same level of type safety.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shape&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;nt&quot;&gt;`Circle&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Rectangle&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&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;n&quot;&gt;area&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;`Circle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;radius&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;radius&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;radius&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14159&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Rectangle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertices&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;`Circle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;radius&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;infinity&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Rectangle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Not too different from the above declaration, the type is surrounded with brackets and the types are
preceded with backticks. Recreating the volume function is easy.&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;volume&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;`Circle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Rectangle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Cube&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So now I’ve extended the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shape&lt;/code&gt; type with another type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cube&lt;/code&gt;, and I haven’t touched &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vertices&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;area&lt;/code&gt; functions. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;volume&lt;/code&gt; function can be done even more succinctly:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;short_volume&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;(* no volume in two dimensions! *)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Cube&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is also possible to constrain the polymorphic variants:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flatten&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Cube&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Rectangle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The type of this function is
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[ &amp;lt; `Circle of float | `Cube of float | `Rectangle of float * float ] -&amp;gt; [&amp;gt; shape]&lt;/code&gt;. The
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&amp;lt; A | B]&lt;/code&gt; means a closed type: it can be only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt;, but nothing else, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&amp;gt; Foo]&lt;/code&gt; means
“Foo or something else”. So the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatten&lt;/code&gt; function accepts &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Circle&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rectangle&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cube&lt;/code&gt; and
returns a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shape&lt;/code&gt; (or possibly something else). Trying to run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatten (`Sphere 4)&lt;/code&gt; produces a
type error:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# flatten (`Sphere 3);;
Characters 8-19:
  flatten (`Sphere 3);;
          ^^^^^^^^^^^
Error: This expression has type [&amp;gt; `Sphere of int ]
       but an expression was expected of type
         [&amp;lt; `Circle of float
          | `Cube of float * float
          | `Rectangle of float * float ]
       The second variant type does not allow tag(s) `Sphere
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, the following code compiles:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;polytope&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;n&quot;&gt;shape&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Cube&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Octahedron&lt;/span&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;n&quot;&gt;frobnicate&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flattened&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flatten&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pt&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flattened&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Already flaaat!&quot;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Octagon&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Eight coorneeeeerss&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The compiles, although we didn’t tell the compiler that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatten&lt;/code&gt; does not return
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Octagon&lt;/code&gt;. There are two ways to fix this: either explicitly annotate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pt&lt;/code&gt; to be of type
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;polytope&lt;/code&gt;, which produces this error:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Error: This expression has type polytope
       but an expression was expected of type
         [&amp;lt; `Circle of float | `Cube of float | `Rectangle of float * float ]
       The second variant type does not allow tag(s) `Octahedron
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is possible to further constrain the type with type annotations. We can make sure that the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatten&lt;/code&gt; function returns &lt;em&gt;only&lt;/em&gt; flat shapes:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;safe_flatten&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&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;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Cube&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Rectangle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Sphere&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;`Circle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This produces the error:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Error: This pattern matches values of type [? `Octagon ]
       but a pattern was expected which matches values of type shape
       The second variant type does not allow tag(s) `Octagon
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;not-a-silver-bullet&quot;&gt;Not a silver bullet&lt;/h2&gt;

&lt;p&gt;Unfortunately, polymorphic variants are &lt;em&gt;problematic&lt;/em&gt;. The problem with polymorphic variants is you
quickly reach an absurd level of complexity and are forced to use annotations or subtyping to ensure
maximal type safety. So although polymorphic variants are &lt;em&gt;nice&lt;/em&gt;, and they do let us solve the
expression problem, they’re an unsteady compromise between type safety and brevity. You can
certainly make elegant abstractions with them but they get unwieldy quickly. They aren’t as
efficient compared to regular variants either.&lt;/p&gt;

&lt;p&gt;So what are the options? In OCaml 4.02, you can use &lt;em&gt;extensible variant types&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ocaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;boring_shape&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;boring_shape&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Circle&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Square&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt;
                                                   
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;boring_area&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Circle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;14159&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Square&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;boring_shape&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Rectangle&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;radical_area&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shp&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Circle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;boring_area&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Square&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;boring_area&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Rectangle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;An extensible variant is defined using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;..&lt;/code&gt;, and extension is done with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+=&lt;/code&gt; operator. The
caveat is that you must handle the default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt; case in pattern matching. Extensible variants are
another neat trick for solving the expression problem.&lt;/p&gt;

&lt;h2 id=&quot;a-measure-of-expressive-power&quot;&gt;A measure of expressive power&lt;/h2&gt;

&lt;p&gt;The expression problem is a great litmus test that measures the expressive power of a
programming language. The actual measurement of the test can be either the brevity of the code or
its type safety. The solutions range from the clumsy Visitor Pattern in Java to polymorphic and
extensible variants in OCaml and to type classes in Haskell. Clojure and Elixir have
&lt;a href=&quot;http://clojure.org/protocols&quot;&gt;protocols&lt;/a&gt; that are both quite nice but not so type-safe since both
are dynamically typed languages. What is more, since the expression problem is also about type
safety, then strictly speaking the problem isn’t valid in a dynamic language. Any Lisper knows that
Lisps &lt;em&gt;are&lt;/em&gt; super expressive anyway.&lt;/p&gt;


        </description>
        <pubDate>Fri, 08 Jan 2016 00:00:00 +0000</pubDate>
        <link>http://ane.iki.fi/2016/01/08/the-expression-problem-as-a-litmus-test.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2016/01/08/the-expression-problem-as-a-litmus-test.html</guid>
      </item>
    
      <item>
        <title>Before we begin</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;Now that the design of the site is finished, I can finally focus on the essentials.&lt;/p&gt;

&lt;p&gt;I’ve decided that this year I will be writing a bit more, here, and elsewhere. To that end, when it
comes to this site, I’ve had to perform a simple but challenging task: lowering my standards.&lt;/p&gt;

&lt;p&gt;Last year, I did not publish anything because I had absurd standards for content. In my mind, every
blog post had to be a thoroughly researched and carefully argued piece, capable of standing the test
of time.&lt;/p&gt;

&lt;p&gt;This was a monumental mistake.&lt;!--break--&gt;&lt;/p&gt;

&lt;p&gt;Researching something thoroughly requires an extraordinary amount of time, and writing opinionated
articles that can stand the test of time requires an extraordinary amount of foresight — neither
of which I yet have. I have already managed to delete one post which contained opinions I no longer
agreed with. I thought its content was rubbish and I was a moron for publishing it, so my only
recourse was to delete it, instead of learning from it.&lt;/p&gt;

&lt;p&gt;My desire for more content stems from the process of gradual improvement: the more you write the
better you get. I cannot do this unless I start from the very basics. I could, of course, simply
write guides on how to do XYZ with $THING, but I want to tell stories, not write recipes. This
doesn’t mean there won’t be any guides, however!&lt;/p&gt;

&lt;p&gt;Another reason for wanting to write more stems from the simple funny fact that somebody &lt;em&gt;reads&lt;/em&gt;
this. Besides Google Analytics telling me so, a few weeks ago I even received a
&lt;a href=&quot;https://github.com/ane/ane.github.io/pull/1&quot;&gt;pull request&lt;/a&gt; for typo fixes.&lt;/p&gt;

&lt;p&gt;So I know there’s at least &lt;em&gt;one&lt;/em&gt; guy who actually reads every word. Disclosure: according to GA,
most of the visits are “accidental redirects” (huh?), and that actual, longer visits aren’t common,
but there were enough for me to extrapolate that there were, at the very least, &lt;em&gt;two&lt;/em&gt; readers.&lt;/p&gt;

&lt;p&gt;So, that was the background. And now comes the disclaimer, of sorts.&lt;/p&gt;

&lt;p&gt;This site is a blog. As this site is a blog, the writings are, first and foremost, opinion pieces,
not research articles, and opinions change. You may find me advocating for stricter type systems one
day, and for looser the next. I will only guarantee that, at &lt;em&gt;the time of writing&lt;/em&gt;, I will argue my
points to the best of my abilities.&lt;/p&gt;

&lt;p&gt;Longer, more in-depth stories, if ever completed, will be available under the &lt;em&gt;articles&lt;/em&gt; category. This
is to mark a distinction. To qualify as an article, the writing will a) contain properly researched
writing and references b) be reviewed by somebody else. I’m currently
&lt;a href=&quot;http://ane.iki.fi/ebi&quot;&gt;working on something&lt;/a&gt; that may one day be considered something like that.&lt;/p&gt;

&lt;p&gt;You’re welcome to snoop into the &lt;a href=&quot;https://github.com/ane/ane.github.io/tree/master/_drafts&quot;&gt;drafts&lt;/a&gt;
folder of the GitHub repository of the site, but be warned, that stuff is obviously incomplete.&lt;/p&gt;

&lt;p&gt;To be continued.&lt;/p&gt;

        </description>
        <pubDate>Fri, 01 Jan 2016 00:00:00 +0000</pubDate>
        <link>http://ane.iki.fi/2016/01/01/before-we-begin.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2016/01/01/before-we-begin.html</guid>
      </item>
    
      <item>
        <title>Start-once software</title>
        <dc:creator>Antoine Kalmbach</dc:creator>
        <description>
          &lt;p&gt;Software development tools are in a state of flux. There are two competing
directions towards which static analysis tools—like linters and
type checkers—are heading.&lt;/p&gt;

&lt;p&gt;The traditional direction is to operate in a &lt;em&gt;batch&lt;/em&gt; model. Fire up, perform analysis, report
results, and die. This is a proven method. Batch-oriented software has been around for ages, and it
works really well if the data you’re working with isn’t large.&lt;!--break--&gt;&lt;/p&gt;

&lt;p&gt;The new direction is an &lt;em&gt;online&lt;/em&gt; model: an analysis tool starts, calculates its
data, reports results, and then stays &lt;em&gt;on&lt;/em&gt;, monitoring for changes. When changes
occur, the program analyzes the changes, and recomputes the effects. This
execution model is efficient: incremental updates are easier to calculate than
starting from scratch. This approach is arguably more modern&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, since we’re
leveraging the full potential of a client-server model.&lt;/p&gt;

&lt;p&gt;The obvious caveat is such a process will eat up memory. These days this is
becoming less and less of a problem, since a gigabyte of desktop-quality DDR3
memory costs about &lt;a href=&quot;http://www.newegg.com/Product/Product.aspx?Item=N82E16820231314&amp;amp;cm_re=ddr3-_-20-231-314-_-Product&quot;&gt;US$5&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, if the workload is large, say 100k-1M lines, it actually makes more
sense to compute an initial “model” of the system, and then &lt;em&gt;incrementally&lt;/em&gt;
update the model when the system changes.&lt;/p&gt;

&lt;p&gt;My line of reasoning was inspired by &lt;a href=&quot;https://news.ycombinator.com/item?id=10271755&quot;&gt;this comment on Hacker News&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Over and over I see reports of iteration speed being critical to
real-world projects, and that’s certainly my experience.&lt;/p&gt;

  &lt;p&gt;But it’s something I rarely see featured in tool design. So many of
our tools are still batch oriented: they start from scratch, read
everything, process everything, and then exit. That made sense in an
era where RAM and CPU were expensive. But now that they’re cheap, I
want tools that I start when I arrive in the morning and kill when I
go home. In between, they should work hard to make my life easy.&lt;/p&gt;

  &lt;p&gt;If I’m going to use a type checker, I want it to load the AST once,
continuously monitor for changes, and be optimized for incremental
changes. Ditto compilers, syntax checkers, linters, test runners,
debugging tools. Everything that matters to me in my core feedback
loop of writing a bit of code and seeing that it works.&lt;/p&gt;

  &lt;p&gt;For 4% of my annual salary, I can get a machine with 128GB of RAM and
8 3.1 GHz cores. Please god somebody build tools that take advantage
of that.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Arguably, the batch mode made sense in the past, when resources weren’t as
plentiful as they are now. Now, we can afford a type checker that sits in the
background, eating up half a gigabyte memory, and most of us won’t even &lt;em&gt;blink&lt;/em&gt;
at that, as long as it helps us write better code—and runs quickly.&lt;/p&gt;

&lt;p&gt;To this end, one could call such software &lt;em&gt;start-once software&lt;/em&gt;&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, which&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Is launched &lt;strong&gt;once&lt;/strong&gt;, via some mechanism and given a target, e.g. a codebase, to
monitor for changes&lt;/li&gt;
  &lt;li&gt;Computes an initial &lt;strong&gt;model&lt;/strong&gt;, the analysis, of the target&lt;/li&gt;
  &lt;li&gt;Whenever changes occur it instantly &lt;strong&gt;recomputes&lt;/strong&gt; a new model and informs
the user of the effects of the changes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this case, the target could be a collection of source files (a “project”), 
the model the compilation errors present in the source files, and the relevance
is a way of communicating those errors to the user.&lt;/p&gt;

&lt;p&gt;The basic idea can be taken from Facebook’s &lt;a href=&quot;http://www.flowtype.org&quot;&gt;Flow&lt;/a&gt;
which does exactly this when you launch it initially, it boots up a server that
keeps the state of the AST in memory. The server runs the analysis and the client
reports the results. There’s an initial up-front cost to all of this from
starting the server but subsequent calls are fast.&lt;/p&gt;

&lt;p&gt;There are some pseudo-implementations of this paradigm: you can have a batch
process that is run every time the target changes, and then do effectively what
is done in step three above. This is &lt;em&gt;kind of&lt;/em&gt; what I described above, but the
difference is that any model is lost inbetween batch runs.&lt;/p&gt;

&lt;p&gt;In fact, file system notification based batch processes remind&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; me of the
&lt;a href=&quot;https://en.wikipedia.org/wiki/The_Chinese_Room&quot;&gt;the Chinese room experiment&lt;/a&gt;:
such tools don’t really have an &lt;em&gt;understanding&lt;/em&gt; of the model that is
&lt;strong&gt;persistent&lt;/strong&gt;, but due to a simultaneously crude and brilliant approach, we get the
subtle impression that such a persistent, evolving understanding actually exists.&lt;/p&gt;

&lt;p&gt;In start-once software, the goal is to always keep the model in working memory
and update it incrementally. Such a program can react quickly to massive
codebase changes. Naturally, speed comes at the cost of memory, but as mentioned
in the quote, if it makes development faster, I think this is a perfectly
justifiable cost.&lt;/p&gt;

&lt;p&gt;This line of thinking doesn’t apply only to static analysis tools. It can work
with any streaming data. Memory is cheap, but speed always isn’t. A good example
is a log processor that computes the state of some system based on the content
of some logs. A start-once processor would continuously monitor the log inputs
and update its model of the system. If it has to churn through a lot of logs at
the start, it may have an initial delay but because the model is persistent, any
changes to the model can be computed quickly.&lt;/p&gt;

&lt;p&gt;Storing the model can be done in two ways. If RAM becomes a limitation (will
it?), a fast database should be used. AFter all, databases &lt;em&gt;solely&lt;/em&gt; exist
because of the prohibitively high cost of ephemeral memory compared to the cost
of non-volatile memory. Traditionally!&lt;/p&gt;

&lt;p&gt;Previously, because of the cost of ephemeral memory, we had to invent a cheaper
form of storage. Now that memory is cheap, this isn’t so much of a threat
anymore.&lt;/p&gt;

&lt;p&gt;When it comes to fault-tolerance, precautions can be taken. The model could be
stored as a persistent image—yes, raw memory or an accurate representation
thereof, or a database. Once the program recovers, it restores the model
immediately, reducing the boot time.&lt;/p&gt;

&lt;p&gt;This model also be extended to web servers: instead of recompiling everything at
every request (hello PHP), one could compile &lt;em&gt;once&lt;/em&gt; and then compile changes
incrementally. This idea isn’t new: &lt;em&gt;hot swapping&lt;/em&gt; has been around for decades,
and its advantages are obvious. Heavy-duty services that take a while to reload
and restore benefit massively of hot swapping. This is routine in the JVM,
Erlang and Lisp worlds.&lt;/p&gt;

&lt;p&gt;Instead of shutting down your engine to upgrade it, you simply replace the parts
to be upgraded with new ones.&lt;/p&gt;

&lt;p&gt;Extending this to static analysis tools isn’t a massive step. If the philosophy
works with server programs I see no reason why it couldn’t work with data
analysis tools. At the cost of ephemeral resources like memory, I want static
analysis tools that can handle large codebases and compute any change big or
small in a fraction of a section.&lt;/p&gt;

&lt;p&gt;I hope more tools will adopt this model. We certainly do have the resources now.&lt;/p&gt;

&lt;h2 id=&quot;addendum-examples-of-start-once-static-analysis-tools&quot;&gt;Addendum: examples of start-once static analysis tools&lt;/h2&gt;

&lt;h3 id=&quot;flow&quot;&gt;&lt;a href=&quot;http://flowtype.org&quot;&gt;Flow&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;A static analysis tool for JavaScript by Facebook, written in OCaml. Upon
launch, it starts a server that runs initial analysis and monitors for
changes.&lt;/p&gt;

&lt;h3 id=&quot;hack&quot;&gt;&lt;a href=&quot;http://hacklang.org/&quot;&gt;Hack&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;A PHP-inspired gradually typed programming language for the HHVM virtual
machine. It runs a type checker in the background in the same way as Flow
does. Also in OCaml!&lt;/p&gt;

&lt;h3 id=&quot;gocode&quot;&gt;&lt;a href=&quot;http://github.com/nsf/gocode&quot;&gt;gocode&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Auto-completion service for Go. It uses a client-server model where completion
requests are sent to the completion server via a JSON-based RPC. Conversely,
every other Go-related static analysis tool
(&lt;a href=&quot;http://dominik.honnef.co/posts/2014/12/an_incomplete_list_of_go_tools/&quot;&gt;there are lots&lt;/a&gt;)
is using the batch approach. That’s fine, since Go seems to be vehemently
opposed to anything modern and advanced, and &lt;em&gt;sometimes&lt;/em&gt; justifiably so. In this
regard Gocode is a rare gem among the Go tooling ecosystem.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Yes, I know REPLs have been around since the eighties, but this isn’t exactly the same thing. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Facebook uses the term “online” when describing Flow &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;They aren’t &lt;em&gt;exactly&lt;/em&gt; the same thing. Since I’m talking about computer programs performing some kind of data analysis, and mentioning the Chinese room experiment, I realize that I’m opening a massive can of worms; the comparison is a mere &lt;em&gt;simile&lt;/em&gt; here. The users of continuous (i.e. inotify-based) batch analysis tools are on the observing end of the Chinese room experiment. &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;

        </description>
        <pubDate>Mon, 07 Dec 2015 12:00:00 +0000</pubDate>
        <link>http://ane.iki.fi/2015/12/07/start-once-software.html</link>
        <guid isPermaLink="true">http://ane.iki.fi/2015/12/07/start-once-software.html</guid>
      </item>
    
  </channel>
</rss>
