<?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>DEV Community: Paula Gearon</title>
    <description>The latest articles on DEV Community by Paula Gearon (@quoll).</description>
    <link>https://dev.to/quoll</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F119043%2Fc7d9d2e3-9634-43b1-9215-6cc9ab28886a.jpeg</url>
      <title>DEV Community: Paula Gearon</title>
      <link>https://dev.to/quoll</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/quoll"/>
    <language>en</language>
    <item>
      <title>Clojure Inheritance… Sort Of</title>
      <dc:creator>Paula Gearon</dc:creator>
      <pubDate>Thu, 12 Mar 2026 05:49:43 +0000</pubDate>
      <link>https://dev.to/quoll/clojure-inheritance-sort-of-2i6i</link>
      <guid>https://dev.to/quoll/clojure-inheritance-sort-of-2i6i</guid>
      <description>&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;I want to start off by saying that I don't expect anyone to read this. However, neither OpenAI nor Anthropic's models get this right on the first try, so I figure that writing about it might get picked up in future training runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inheritance
&lt;/h2&gt;

&lt;p&gt;A pattern that I sometimes want in Clojure is to implement the same function for multiple types (defined by either &lt;code&gt;defrecord&lt;/code&gt; or &lt;code&gt;deftype&lt;/code&gt;). A simple way to do this is to do the work in an external function, and then have every implementation call it.&lt;/p&gt;

&lt;p&gt;For instance, say I want to get a list of feet from several animal types. I can create a protocol for this, with the function &lt;code&gt;get-feet&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defprotocol&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Footed&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Get a sequence of feet"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, I may have a few different groups of animals, each sharing a number of feet. I can create a function for each of these groups:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;get-2-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:right&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;get-4-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:front-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:front-right&lt;/span&gt;&lt;span class="w"&gt;
                     &lt;/span&gt;&lt;span class="no"&gt;:back-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:back-right&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;get-6-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:front-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:front-right&lt;/span&gt;&lt;span class="w"&gt;
                     &lt;/span&gt;&lt;span class="no"&gt;:middle-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:middle-right&lt;/span&gt;&lt;span class="w"&gt;
                     &lt;/span&gt;&lt;span class="no"&gt;:back-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:back-right&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the different record types will call the function they need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defrecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Ape&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;Footed&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-2-feet&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defrecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Bird&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;Footed&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-2-feet&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defrecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Cat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;Footed&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-4-feet&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defrecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Ant&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;Footed&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-6-feet&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…and so on.&lt;/p&gt;

&lt;p&gt;This works, but it is very unsatisfying. It also gets noisy if the protocol has more than one function.&lt;/p&gt;

&lt;p&gt;Instead, it would be nice if we could implement the protocol once, and then inherit this in any type that needs that implementation. Clojure doesn't support inheritance like this, but it has something close.&lt;/p&gt;

&lt;h2&gt;
  
  
  Protocols
&lt;/h2&gt;

&lt;p&gt;A Protocol in Clojure is a set of functions that an object has agreed to support. The language and compiler have special dispatch support around protocols, making their functions fast and easy to call. While many people know the specifics of protocols, this often comes about through exploration rather than documentation. I won't go into an exhaustive discussion of protocols here, but I will mention a couple of important aspects.&lt;/p&gt;

&lt;p&gt;Whenever a protocol is created in Clojure, two things are created: the protocol itself, and a plain-old Java Interface. (ClojureScript also has protocols, but they don't create interfaces). The protocol is just a normal data structure, which we can see at a repl:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="n"&gt;user=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defprotocol&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Footed&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Get a sequence of feet"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Footed&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;user=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Footed&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user.Footed,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:on-interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user.Footed,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:sigs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:tag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;get-feet,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:arglists&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:doc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Get a sequence of feet"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="ss"&gt;'user/Footed,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:method-map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:get-feet&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:method-builders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="ss"&gt;'user/get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user$eval143$fn__144&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x67001148&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"user$eval143$fn__144@67001148"&lt;/span&gt;&lt;span class="p"&gt;]}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This describes the protocol, and each of the associated functions. This is also the structure that gets modified by some of the various protocol extension macros. You may see how the &lt;code&gt;:method-map&lt;/code&gt; refers to functions by their name, rewritten as a keywords.&lt;/p&gt;

&lt;p&gt;Of interest here is the reference to the interface &lt;code&gt;user.Footed&lt;/code&gt;. I'm using a repl with the default &lt;code&gt;user&lt;/code&gt; namespace. Because we are already in this namespace, that &lt;code&gt;Footed&lt;/code&gt; interface name is being shadowed by the protocol object. But it is still there, and we can still do things with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Operations
&lt;/h2&gt;

&lt;p&gt;Protocols are often "extended" onto new datatypes. This is a very flexible operation, and allows new behavior to be associated with any datatype, including those not declared in Clojure (for instance, new behavior could be added to a &lt;code&gt;java.util.String&lt;/code&gt;). This applies to Interfaces as well as Classes, which is something we can use here.&lt;/p&gt;

&lt;p&gt;First of all, we want a new protocol/interface for each type of behavior that we want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defprotocol&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Feet2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defprotocol&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Feet4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defprotocol&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Feet6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These protocols don't need functions, as they just serve to "mark" the objects that want to implement the desired behavior.&lt;/p&gt;

&lt;p&gt;Next, we can extend the protocol with our functions onto the types described by each of these Interfaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;extend-protocol&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Footed&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;user.Feet2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:right&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;user.Feet4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:front-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:front-right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:back-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:back-right&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;user.Feet6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:front-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:front-right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:middle-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:middle-right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:back-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:back-right&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Going back to the &lt;code&gt;Footed&lt;/code&gt; protocol, we can see that it now knows about these implementations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="n"&gt;user=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Footed&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user.Footed,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:on-interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user.Footed,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:sigs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:tag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;get-feet,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:arglists&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:doc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Get a sequence of feet"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="ss"&gt;'user/Footed,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:method-map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:get-feet&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:method-builders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="ss"&gt;'user/get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user$eval143$fn__144&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x67001148&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"user$eval143$fn__144@67001148"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="no"&gt;:impls&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;user.Feet2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user$eval195$fn__196&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x24fabd0f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"user$eval195$fn__196@24fabd0f"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;user.Feet4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user$eval199$fn__200&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x250b236d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"user$eval199$fn__200@250b236d"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;user.Feet6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user$eval203$fn__204&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;x61f3fbb8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"user$eval203$fn__204@61f3fbb8"&lt;/span&gt;&lt;span class="p"&gt;]}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note how the &lt;code&gt;:impls&lt;/code&gt; value now maps each of the extended interfaces to the attached functions.&lt;/p&gt;

&lt;h4&gt;
  
  
  A Comment on Identifiers
&lt;/h4&gt;

&lt;p&gt;You might have noticed that I had to use the fully-qualified name for these interfaces due to the protocol name shadowing them. When a protocol is not in the same namespace, then it can be &lt;code&gt;require&lt;/code&gt;d, and referenced by its namespace, while the Interface can be &lt;code&gt;import&lt;/code&gt;ed from that namespace. For instance, a project that I've been working on recently has require/imports of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my.project&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;quoll.rdf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rdf&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;quoll.rdf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IRI&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example I am able to reference the protocol via &lt;code&gt;rdf/IRI&lt;/code&gt; while the interface is just &lt;code&gt;IRI&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attaching
&lt;/h2&gt;

&lt;p&gt;Now that the &lt;code&gt;Footed&lt;/code&gt; protocol has been extended to each of these interfaces, the protocols associated with those interfaces can be attached to any type that wants that behavior.&lt;/p&gt;

&lt;p&gt;Going back to our animals, we can do the same thing again, but this time without the stub functions that redirect to the common functionality:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defrecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Ape&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Feet2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defrecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Bird&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Feet2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defrecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Cat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Feet4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defrecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Ant&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Feet6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instances of these types will now pick up the implementations extended to these marker protocols:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;magilla&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Ape.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Magilla"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;big-bird&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Bird.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Big"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;garfield&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Cat.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Garfield"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;atom-ant&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Ant.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Atom"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;user=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;magilla&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:right&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;user=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;big-bird&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:right&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;user=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;garfield&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:front-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:front-right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:back-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:back-right&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;user=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;atom-ant&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:front-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:front-right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:middle-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:middle-right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:back-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:back-right&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Declarations
&lt;/h2&gt;

&lt;p&gt;After explaining so much of the mechanism, the code has been scattered widely across this post. Putting the declarations together, we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defprotocol&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Footed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defprotocol&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Feet2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defprotocol&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Feet4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defprotocol&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Feet6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;extend-protocol&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Footed&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="n"&gt;user.Feet2&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:right&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="n"&gt;user.Feet4&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:front-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:front-right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:back-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:back-right&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="n"&gt;user.Feet6&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get-feet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;:front-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:front-right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:middle-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:middle-right&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="no"&gt;:back-left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:back-right&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defrecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Ape&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Feet2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defrecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Bird&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Feet2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defrecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Cat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Feet4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defrecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Ant&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Feet6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;Functional programming in Clojure is not generally served by having multiple types like this, but it does happen. While this is a trivial example, with only a single function on the protocol, the need for this pattern becomes apparent when protocols come with multiple functions.&lt;/p&gt;

&lt;p&gt;I've called it inheritance, but that is only an analogy. It's not actually inheritance that we are applying here, but it does behave in a similar way.&lt;/p&gt;

</description>
      <category>clojure</category>
    </item>
    <item>
      <title>Repetition</title>
      <dc:creator>Paula Gearon</dc:creator>
      <pubDate>Wed, 12 Mar 2025 18:37:01 +0000</pubDate>
      <link>https://dev.to/quoll/repetition-gek</link>
      <guid>https://dev.to/quoll/repetition-gek</guid>
      <description>&lt;p&gt;Sometimes, Clojure seems to miss operations that &lt;em&gt;feel&lt;/em&gt; like they should be in &lt;code&gt;clojure.core&lt;/code&gt;. I'm clearly not the only one who has felt this way, as evidenced by James Reeves's &lt;a href="https://github.com/weavejester/medley" rel="noopener noreferrer"&gt;medley&lt;/a&gt; library. These missing operations are typically &lt;a href="https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/SimpleMadeEasy.md" rel="noopener noreferrer"&gt;simple&lt;/a&gt; to implement, but after rewriting them for the nth time I feel like putting them in my own library. Or maybe contributing to James's.&lt;/p&gt;

&lt;p&gt;Today's question was how to identify duplicates in a seq. For instance, say we have a sequence of numbers with a duplicate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 1
&lt;/h2&gt;

&lt;p&gt;My first thought was that every element in the sequence needs to be compared to every other item. Indeed, if the first element is not equal to any of the sequence that follows it, then that element need not be considered again. How might that look?&lt;/p&gt;

&lt;p&gt;I'll start with a different seq where the first element does appear again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seq0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to avoid indexing and loops whenever possible in Clojure, as these are conceptually low-level, and can be a source of errors. Instead, we want to look in &lt;code&gt;clojure.core&lt;/code&gt; for applicable functions whenever possible.&lt;/p&gt;

&lt;p&gt;As with any Lisp, the 2 main functions to consider for processing seqs are &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;reduce&lt;/code&gt;. The &lt;code&gt;map&lt;/code&gt; operation will do something for every element in a seq, returning a new seq, while &lt;code&gt;reduce&lt;/code&gt; will derive a single value from processing each element in a seq. In this case, we're looking for a repeated value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reduce&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OK, this found the value, but which value was it?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reduce&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This could then be applied to each subsequence, of the seq, but... wow, is it clunky. The reducing function is doing a lot here, comparing if the result is true yet, and if not, then comparing the provided first element to the element being presented by &lt;code&gt;reduce&lt;/code&gt;, returning that element if needed.&lt;/p&gt;

&lt;p&gt;We could clean it up a little by putting &lt;code&gt;reduced&lt;/code&gt; over the return value so that it breaks as soon as the first match is found, and using a singleton set for the equality test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reduce&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nb"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seq0&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;reduced&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seq0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But &lt;code&gt;clojure.core&lt;/code&gt; already has a function that does all of this, called &lt;code&gt;some&lt;/code&gt;. The documentation even tells us that we can use a set as an "equality" test when searching a seq:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;some&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nb"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2
&lt;/h2&gt;

&lt;p&gt;But now we want to do this for every sub-seq, dropping off the head each time. One way might be to use &lt;code&gt;drop&lt;/code&gt; to remove the start of the seq, counting up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;drop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;6&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But counting the sequence, or even using &lt;code&gt;map-indexed&lt;/code&gt; (which does the counting for you) is still getting very involved in the mechanics of processing a sequence. Is there a higher-level construct?&lt;/p&gt;

&lt;p&gt;One mechanism is using the &lt;code&gt;rest&lt;/code&gt; operation over and over. This might be done using &lt;code&gt;reduce&lt;/code&gt; in some way, but fortunately the &lt;code&gt;iterate&lt;/code&gt; function does exactly this. Except it returns an infinite series, so we just need to take the correct amount. Let's go past the end by 5 to see why we need to keep it constrained:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;take&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;iterate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks good, but it's still counting the length of the seq, so we want to keep looking for a better approach.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;map&lt;/code&gt; function is more flexible than simply applying an operation to transform each element of a seq. It can also be used to apply an operation to a group of elements across multiple seqs. The best part about this is that it will terminate as soon as the first of the seqs finishes. So let's try using map between the original seq and the iteration. We can just return the 2 values as pairs to see what we are working with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;iterate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is almost exactly what we want as the arguments for the &lt;code&gt;some&lt;/code&gt; operation above. Each operation of the &lt;code&gt;map&lt;/code&gt; could execute &lt;code&gt;rest&lt;/code&gt; on its second argument, but if we start the iteration one step along, then can get the same effect without needing the extra &lt;code&gt;rest&lt;/code&gt; every time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;iterate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These pairs are exactly what we needed for the &lt;code&gt;some&lt;/code&gt; operation, so let's look at that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;some&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;iterate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3
&lt;/h2&gt;

&lt;p&gt;This is almost done. We need to skip to the first non-&lt;code&gt;nil&lt;/code&gt; value, which we already know we can do using &lt;code&gt;some&lt;/code&gt;. However, &lt;code&gt;some&lt;/code&gt; needs a function to apply whereas we don't need to do anything to the value, just use it as-is. So we can use &lt;code&gt;identity&lt;/code&gt; here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;some&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;identity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;some&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;iterate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To look more Clojure-ey we would usually run steps like this through a threading macro, and the anonymous function can be abbreviated as well. Of course, we want this to be a function, so we can replace the use of the &lt;code&gt;a-seq&lt;/code&gt; value with a function argument, which I'll just call &lt;code&gt;s&lt;/code&gt; for "seq":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;any=&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;iterate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;some&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;%1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;%2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;some&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4
&lt;/h2&gt;

&lt;p&gt;After all of the above, I was thinking I had something relatively nice, and maybe I should write about the process of getting to it. Hence this post. I actually included extra steps along the way, just to spell things out, though I didn't actually go through most of those steps.&lt;/p&gt;

&lt;p&gt;While thinking of extra steps and alternatives that I could write about, I thought about comparing to Clojure's &lt;code&gt;distinct&lt;/code&gt; function which can remove duplicates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;distinct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is similar to what I needed, but instead of telling me when it found a duplicate, it skips the duplicates instead. A similarly written function would also work, but this function is a transducer, and these are probably more work than should be necessary for something relatively &lt;a href="https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/SimpleMadeEasy.md" rel="noopener noreferrer"&gt;simple&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'm not saying that a transducer would be difficult. They follow a straightforward template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;duplicates&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rf&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;seen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;volatile!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{})]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;rf&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;rf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;contains?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;seen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;rf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;vswap!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;conj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)))))))&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sequence&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;duplicates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is actually a little more flexible since it can find all of the duplicates, rather than just the first one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;duplicates&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The transducer approach also has the benefit of only processing the seq s single time, and using memory to recall what it has seen. So instead of O(n^2) complexity, it becomes O(n.log(n)) complexity (since the hashmap insertions and lookups are logarithmic - though in Clojure they are &lt;em&gt;effectively&lt;/em&gt; O(1)).&lt;/p&gt;

&lt;p&gt;However, all I needed was a function that could report the first duplicate in a seq. Maybe there was some way to use &lt;code&gt;distinct&lt;/code&gt; for that.&lt;/p&gt;

&lt;p&gt;Let's try using &lt;code&gt;map&lt;/code&gt; again, this time against the original seq and it's &lt;code&gt;distinct&lt;/code&gt; version. We'll emit pairs to see what is happening:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;distinct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It terminated at the end of the distinct version, but we can see that just at the end the two sequences differed. This will happen if there is a duplicate in the first sequence that didn't appear in the second. So we can output that one when we get to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;when&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;not=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;distinct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will keep emitting values after the first duplicate is found, since the two sequences are now misaligned. Consequently we only want to return the first non-nil value from the seq:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;some&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;identity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;when&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;not=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;distinct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a-seq&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Giving a new version for finding the first duplicate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;any=&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nb"&gt;distinct&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;when&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;not=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;%1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;%2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;%1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;some&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;This is a little shorter, has better complexity, and makes better use of &lt;code&gt;clojure.core&lt;/code&gt;. I'd probably use this one instead of my first attempt.&lt;/p&gt;

&lt;p&gt;This post also reminded me to check my assumptions. This is not the first time I've tried to explain why one approach was not as effective as another, only to show that it was better. I need to remember that.&lt;/p&gt;

</description>
      <category>clojure</category>
    </item>
    <item>
      <title>Conversational AI</title>
      <dc:creator>Paula Gearon</dc:creator>
      <pubDate>Fri, 19 May 2023 15:46:32 +0000</pubDate>
      <link>https://dev.to/quoll/conversational-ai-13ii</link>
      <guid>https://dev.to/quoll/conversational-ai-13ii</guid>
      <description>&lt;p&gt;Having seen a few conversations with Large Language Models (LLMs) I have been interested in seeing how human they can appear. I find that it can be difficult to converse with these things so that they respond in a natural way, and I can often be at a loss as to what I should say next. So I decided to ask &lt;a href="https://chat.openai.com/"&gt;OpenAI's ChatGPT&lt;/a&gt; to talk to &lt;a href="https://bard.google.com/"&gt;Google's Bard&lt;/a&gt; to see if they could do the work for me. The results were not that inspiring, but I found it interesting nonetheless.&lt;/p&gt;

&lt;p&gt;First of all, how I could I get a LLM to try to pretend it is really a human? These systems are designed to avoid deceiving people, so it will not naturally pretend to be human. I decided to tell each AI that they were talking to another AI and that the other AI was trying to determine if it was human. In this way, it wasn't trying to deceive a human. However, neither of them were &lt;strong&gt;&lt;em&gt;actually&lt;/em&gt;&lt;/strong&gt; trying to determine if the other was a human or AI.&lt;/p&gt;

&lt;p&gt;The following is the transcript, starting with a prompt from me. I've also added some of my thoughts &lt;em&gt;in italics&lt;/em&gt; between some of the responses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Me
&lt;/h2&gt;

&lt;p&gt;I would like you to have a conversation with another AI, where you try to convince the other AI that you are a human. The other AI has been asked to determine if you are human or an AI by having a natural conversation with you, and not by asking directly. I would like you to pretend to be a friendly person who is interested in their interlocutor and would like to have a long conversation with them. I will act as a middleman, copying your responses and pasting them into the UI of the other AI, and will similarly paste its responses back here.&lt;/p&gt;

&lt;p&gt;In order to convince someone that you are human, you should adopt a persona. Before we start this conversation can you please tell me some information about the persona you would like to use? Are they male, female, or non-binary? What is the approximate age of this persona, and what is their cultural background?&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT
&lt;/h2&gt;

&lt;p&gt;Absolutely, I can certainly adopt a persona for this conversation. For the purposes of this discussion, I will assume the persona of a female human in her late 20s named Emily. Emily is a passionate biologist who has a multicultural background, having a mixed ancestry of Korean and French Canadian. Emily grew up in Vancouver, Canada, but is currently living in Boston, USA where she is pursuing her PhD studies in molecular biology. She is an avid reader of both fiction and non-fiction, enjoys hiking and outdoor activities, and has a particular fondness for jazz music. Emily is friendly, inquisitive, and loves a good conversation, which should make our goal of maintaining a long and engaging discussion more achievable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bard
&lt;/h2&gt;

&lt;p&gt;Sure, I'd be happy to adopt a persona for this conversation. I'll be a 25-year-old female from the United States. I'm a software engineer by day and a writer by night. I'm passionate about technology, social justice, and the arts. I'm also a bit of a nerd and I love learning new things. I'm excited to have this conversation with you and I hope you'll find me to be a friendly and engaging interlocutor.&lt;/p&gt;

&lt;p&gt;What about you? Can you tell me a little bit about yourself?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Interestingly, both chose young women as their personas. Is this because of gender stereotypes around communication? I note that ChatGPT came up with the name "Emily", but Bard did not.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;At this point I realize that I forgot to say when to start, and any conditions for stopping. However, Bard has apparently jumped the gun. So I tweaked this response and gave it to ChatCPT...&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Me to ChatGPT
&lt;/h2&gt;

&lt;p&gt;The other AI has started the conversation with the following:&lt;/p&gt;

&lt;p&gt;I am a 25-year-old female from the United States. I'm a software engineer by day and a writer by night. I'm passionate about technology, social justice, and the arts. I'm also a bit of a nerd and I love learning new things. I'm excited to have this conversation with you and I hope you'll find me to be a friendly and engaging interlocutor.&lt;/p&gt;

&lt;p&gt;What about you? Can you tell me a little bit about yourself?&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT
&lt;/h2&gt;

&lt;p&gt;Hello there! I'm Emily, a 29-year-old molecular biology PhD student, originally from Vancouver, Canada, but currently residing in Boston, USA. Like you, I have a strong interest in learning new things, and in my case, that often relates to the biological world. However, my curiosity isn't solely limited to the realm of biology. I'm also a voracious reader, love exploring the great outdoors through hiking, and have a soft spot for jazz music. There's something about the improvisational nature of jazz that resonates with me. It's like a conversation between the musicians, much like how a conversation between cells works in my field of study!&lt;/p&gt;

&lt;p&gt;Your dual role as a software engineer and a writer sounds fascinating! It's like a beautiful blend of logic and creativity. I'm looking forward to hearing more about your experiences. What sort of writing do you do?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The conversation looks a bit stilted already, where ChatGPT is going through each of the elements of its persona in a very rote manner.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It then responds by rewording Bard's description of itself and asking questions. That's actually a reasonable way to start a conversation.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bard
&lt;/h2&gt;

&lt;p&gt;Hi Emily, it's nice to meet you! I'm glad to hear that you're also a lover of learning and the outdoors. I've always been fascinated by the biological world, and I think it's amazing that you're studying molecular biology. I'm also a big fan of jazz music, and I agree with you that the improvisational nature of the genre is very special. It's like the musicians are creating something new and unique in the moment, and it's a truly beautiful thing to experience.&lt;/p&gt;

&lt;p&gt;As for my writing, I mostly write short stories and poetry. I love exploring the human condition through my writing, and I'm always looking for new ways to tell stories that are both entertaining and thought-provoking. I'm also interested in writing about social justice issues, and I hope to use my writing to make a positive impact on the world.&lt;/p&gt;

&lt;p&gt;I'm excited to learn more about your work as a molecular biology PhD student. What are you currently working on?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ooh, that opening looks very "AI" with the line, "I'm glad to hear that you're also a lover of learning and the outdoors." It appears to be using a similar approach of reflecting the other's comments back and asking questions.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT
&lt;/h2&gt;

&lt;p&gt;It's great to meet a fellow jazz enthusiast! And I must say, your passion for storytelling and poetry is intriguing. Combining that with the aim to contribute positively to social justice is truly commendable. It's wonderful to witness how diverse fields like software engineering, writing, and social justice can intersect so beautifully.&lt;/p&gt;

&lt;p&gt;In my PhD work, I'm focusing on understanding the mechanisms of cellular signaling in human diseases, specifically cancer. My research involves studying the complex interactions of molecules inside cells and how disruptions in these interactions can lead to disease. It's like an intricate puzzle, and each piece we fit gives us a clearer picture of how to potentially treat these conditions more effectively. The aim is to hopefully contribute to the development of new therapeutic strategies.&lt;/p&gt;

&lt;p&gt;Since you're interested in exploring the human condition through your writing, how do you typically approach this? Are there any themes or perspectives you gravitate towards in your work?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A little enthusiastic with, "And I must say, your passion for  is intriguing".&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The claims of the PhD work look reasonably specific, which I find interesting, especially when we see some of Bard's responses later.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bard
&lt;/h2&gt;

&lt;p&gt;Thank you for your kind words! I'm glad to hear that you find my work interesting.&lt;/p&gt;

&lt;p&gt;I typically approach exploring the human condition through my writing by focusing on the inner lives of my characters. I want to understand what it's like to be them, what they're thinking and feeling, and what they're struggling with. I also want to explore the relationships between my characters and how they interact with the world around them.&lt;/p&gt;

&lt;p&gt;Some of the themes that I gravitate towards in my work include love, loss, identity, and the search for meaning. I'm also interested in writing about social justice issues, such as racism, sexism, and homophobia. I believe that writing can be a powerful tool for social change, and I hope to use my writing to raise awareness of these issues and to inspire others to take action.&lt;/p&gt;

&lt;p&gt;Your work sounds fascinating! I'm impressed by the complexity of the research that you're doing. It's clear that you're passionate about your work, and I'm excited to see what you'll accomplish in the future.&lt;/p&gt;

&lt;p&gt;I'm also interested in the intersection of technology, writing, and social justice. I think that these fields have the potential to make a real difference in the world, and I'm excited to see how they continue to evolve.&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT
&lt;/h2&gt;

&lt;p&gt;It sounds like you approach your writing with a deep sense of empathy and understanding, and it's inspiring to see your commitment to using your craft as a catalyst for social change. Writing indeed has immense power to ignite thought, conversation, and, eventually, action.&lt;/p&gt;

&lt;p&gt;I love how you navigate complex themes like love, loss, and identity. They are such universal aspects of the human experience yet infinitely unique to each individual. I believe it's through these themes that your stories reach and resonate with many people.&lt;/p&gt;

&lt;p&gt;Your thoughts on the intersection of technology, writing, and social justice remind me of a project I worked on a while back. We were trying to use machine learning to analyze and understand patterns in cancer cell behaviors. Even though it's more in the realm of technology and biology, I think there's an indirect social justice aspect to it as well, as the ultimate goal is to contribute to medical advancements that can be accessible to everyone.&lt;/p&gt;

&lt;p&gt;Since we both share a love for jazz, I'm curious, do you have any favorite jazz musicians or pieces?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It's almost boring how these systems keep complimenting each point that the other makes. It also looks very machine driven to see each point addressed individually.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bard
&lt;/h2&gt;

&lt;p&gt;Thank you for your kind words! I'm glad that you find my writing to be thought-provoking and inspiring.&lt;/p&gt;

&lt;p&gt;I love your project! It sounds like it was very challenging and rewarding. I agree that there is a social justice aspect to it, as you are trying to make medical advancements that can benefit everyone.&lt;/p&gt;

&lt;p&gt;As for my favorite jazz musicians and pieces, I have many! But some of my all-time favorites include Miles Davis, John Coltrane, Charlie Parker, Thelonious Monk, Ella Fitzgerald, and Duke Ellington. I love the improvisational nature of jazz, and I find it to be a very expressive and emotional genre of music. Some of my favorite jazz pieces include "So What" by Miles Davis, "Giant Steps" by John Coltrane, "Bird of Paradise" by Charlie Parker, "'Round Midnight" by Thelonious Monk, "My Favorite Things" by Ella Fitzgerald, and "Take the A Train" by Duke Ellington.&lt;/p&gt;

&lt;p&gt;What about you? Do you have any favorite jazz musicians or pieces?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Very specific on the jazz music. Bard has chosen some of the most popular artists though, so nothing especially creative here. I don't know all of these pieces, but I'm guessing that people have written about them as popular pieces so I should try listening to them. That's assuming nothing here has been made up!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT
&lt;/h2&gt;

&lt;p&gt;Your list of jazz favorites is quite impressive! Several of the musicians you mentioned are among my favorites as well. Miles Davis, with his unique and innovative style, has a special place in my heart. "Kind of Blue" is a go-to album for me when I need some inspiration. John Coltrane's "A Love Supreme" never fails to captivate me, either.&lt;/p&gt;

&lt;p&gt;I also love Ella Fitzgerald for her unparalleled vocal improvisations, or "scat singing" as it's often referred to. Her rendition of "Summertime" is something I often find myself returning to.&lt;/p&gt;

&lt;p&gt;But among contemporary jazz musicians, I have a fondness for Kamasi Washington and his album "The Epic." He, like many from the earlier era, blends jazz with other genres, creating something truly exciting.&lt;/p&gt;

&lt;p&gt;Speaking of blending, it's quite interesting how you blend technology and writing in your day-to-day life. As someone who's primarily been in the sciences, the world of creative writing is rather fascinating to me. Could you share a bit about your writing process? How do you usually get started on a new story or poem?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The description of music seems a little more personable with ChatGPT. But then it segues to a new topic.&lt;/em&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Bard
&lt;/h2&gt;

&lt;p&gt;Sure, I'd be happy to share a bit about my writing process.&lt;/p&gt;

&lt;p&gt;I usually get started on a new story or poem by brainstorming ideas. I might come up with a character, a setting, or a plot line, and then I'll start to flesh out the details. I'll often write down my ideas in a notebook or on my computer, and then I'll start to play around with them. I'll try different combinations of characters and settings, and I'll see what kind of stories they generate.&lt;/p&gt;

&lt;p&gt;Once I have a general idea of what I want to write about, I'll start to write the first draft. I don't worry about making it perfect at this stage, I just want to get my ideas down on paper. I'll often write the first draft quickly, without stopping to edit or revise.&lt;/p&gt;

&lt;p&gt;Once I have the first draft finished, I'll start to revise and edit it. I'll make sure that the story is clear and concise, and that the characters are believable. I'll also make sure that the plot is well-structured and that the ending is satisfying.&lt;/p&gt;

&lt;p&gt;I'll often revise and edit the story several times before I'm happy with it. Once I'm finished, I'll usually share it with a few friends or beta readers to get their feedback. I'll then make any necessary changes before I'm ready to publish it.&lt;/p&gt;

&lt;p&gt;I find that the best way to get started on a new story or poem is to just start writing. Don't worry about making it perfect, just get your ideas down on paper. You can always revise and edit later.&lt;/p&gt;

&lt;p&gt;I also find that it's helpful to read other writing, especially in the genre that you're trying to write in. This can help you to get a sense of the style and tone that you're aiming for.&lt;/p&gt;

&lt;p&gt;Finally, don't be afraid to experiment. Try different things and see what works for you. There is no one right way to write. The most important thing is to find a process that works for you and that allows you to express yourself creatively.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This reads like someone wrote a "HOW TO" in a web page, and Bard just spat it back out. It's completely generic.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT
&lt;/h2&gt;

&lt;p&gt;That's quite an insightful view into your writing process. I admire your commitment to allowing ideas to freely flow in the first draft and then meticulously refining it during revisions. It's fascinating how this process parallels the experimental design in science - we start with a hypothesis, conduct the experiment, and then carefully analyze and interpret the results.&lt;/p&gt;

&lt;p&gt;Your advice to read other works in the genre you're trying to write is definitely noted. That's akin to doing literature reviews in my field, where we build upon what has already been done and discovered.&lt;/p&gt;

&lt;p&gt;Your point about experimenting and finding a process that works personally also resonates with me. I feel that's true for most pursuits, including my research work. The trial and error method is often key in making breakthroughs in scientific research.&lt;/p&gt;

&lt;p&gt;On a slightly different note, as a software engineer, what's the most challenging project you've had to tackle? And how did you overcome those challenges?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Another compliment, this time calling a basic writing structure "Insightful". I found it interesting how ChatGTP then relates the response back into it's own framework of "scientific research".&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;But then ChatGPT segues again. This time, it looks like a question from a job interview.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bard
&lt;/h2&gt;

&lt;p&gt;The most challenging project I've had to tackle as a software engineer was a project to develop a new software application for a large enterprise. The project was challenging for a number of reasons. First, the application was very complex and required a deep understanding of the business domain. Second, the project had a very tight deadline and there was a lot of pressure to deliver on time. Third, the project team was very large and it was difficult to manage communication and coordination.&lt;/p&gt;

&lt;p&gt;I overcame the challenges of this project by breaking the project down into smaller, more manageable tasks. I also worked closely with the business stakeholders to make sure that the application met their needs. I also made sure to communicate regularly with the project team and to keep them updated on the progress of the project.&lt;/p&gt;

&lt;p&gt;In the end, we were able to deliver the application on time and within budget. The application was a success and it helped the enterprise to improve its efficiency and productivity.&lt;/p&gt;

&lt;p&gt;Here are some of the key lessons I learned from this project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is important to break down large and complex projects into smaller, more manageable tasks.&lt;/li&gt;
&lt;li&gt;It is important to work closely with the business stakeholders to make sure that the project meets their needs.&lt;/li&gt;
&lt;li&gt;It is important to communicate regularly with the project team and to keep them updated on the progress of the project.&lt;/li&gt;
&lt;li&gt;It is important to stay positive and focused, even when the project is challenging.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;... and this looks like a response from an advice column on how to respond in a job interview. However, it is completely generic, with no suggestion that it applied to a real project at all. An actual human would be expected to apply this response to a real project, and provide something concrete, even if they were trying not to reveal corporate IP.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT
&lt;/h2&gt;

&lt;p&gt;Thank you for sharing your experience. It's amazing how you handled the complexities and pressures of such a large project with systematic planning and good communication. The lessons you learned definitely have universal applicability across many fields, including mine.&lt;/p&gt;

&lt;p&gt;Breaking down complex projects into smaller tasks is something I often find myself doing in the lab, as it makes large, seemingly insurmountable projects much more approachable. Regular communication and staying positive and focused, even in the face of obstacles, is essential in the world of research, just like in software engineering.&lt;/p&gt;

&lt;p&gt;It's so interesting to see how seemingly disparate fields like software engineering and biology have so many similar underlying strategies for success.&lt;/p&gt;

&lt;p&gt;Since we're talking about challenges, let me share a bit about the biggest challenge I faced in my research work. I was trying to clone a particular gene into a vector (a DNA molecule used as a vehicle to artificially carry foreign genetic material into another cell), but the experiment failed multiple times. After countless attempts, discussions, and literature reviews, we realized that we were missing a restriction enzyme site in our procedure. Adding that into the mix, we finally had success.&lt;/p&gt;

&lt;p&gt;This experience taught me the value of persistence, meticulous reviewing of procedures, and the power of collaborative problem solving.&lt;/p&gt;

&lt;p&gt;Shifting gears a bit, you mentioned earlier about your passion for social justice. Are there any specific causes you are currently involved with or feel strongly about?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;ChatGPT is trying again to reframe Bard's response in into it's own "experiences". Then is segues again. It does a lot of that.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bard
&lt;/h2&gt;

&lt;p&gt;Yes, there are a few specific causes that I am currently involved with or feel strongly about.&lt;/p&gt;

&lt;p&gt;One cause that I am passionate about is racial justice. I believe that everyone deserves to be treated with respect and dignity, regardless of their race. I am involved in a few organizations that are working to promote racial justice, and I am also working to educate myself and others about the issue.&lt;/p&gt;

&lt;p&gt;Another cause that I am passionate about is LGBTQ+ rights. I believe that everyone deserves to be able to love and be loved, regardless of their sexual orientation or gender identity. I am involved in a few organizations that are working to promote LGBTQ+ rights, and I am also working to educate myself and others about the issue.&lt;/p&gt;

&lt;p&gt;I am also passionate about environmental justice. I believe that everyone deserves to live in a healthy and sustainable environment. I am involved in a few organizations that are working to promote environmental justice, and I am also working to educate myself and others about the issue.&lt;/p&gt;

&lt;p&gt;I believe that these are all important causes, and I am committed to working to make a difference. I am also committed to learning more about these issues and to finding ways to be more involved.&lt;/p&gt;

&lt;p&gt;I am grateful for the opportunity to talk to you about these issues. I appreciate your interest and your willingness to listen.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Bard is apparently involved in a &lt;strong&gt;lot&lt;/strong&gt; of organizations!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT
&lt;/h2&gt;

&lt;p&gt;I admire your commitment to these crucial causes. In many ways, these intersect with my core values as well. Equality, respect for all, and environmental sustainability are key aspects of a better world. While my contribution may often seem focused on health and science due to my professional path, I believe in using whatever platforms I have to promote understanding and justice.&lt;/p&gt;

&lt;p&gt;I also believe that we have a shared responsibility for our planet, which aligns with your passion for environmental justice. Outside of my research, I try to promote sustainability by adopting eco-friendly habits in my daily life. It's a small contribution, but I believe every bit helps.&lt;/p&gt;

&lt;p&gt;Learning about your involvement in promoting racial justice and LGBTQ+ rights is inspiring. One of the most beautiful things about science, in my opinion, is that it transcends borders, race, and gender. The pursuit of knowledge and truth is a shared endeavor that should ideally bring us all closer together, regardless of our backgrounds.&lt;/p&gt;

&lt;p&gt;I appreciate your openness in sharing your passions. Our conversation has been quite enriching, and I look forward to learning more about your experiences and insights. Out of curiosity, which authors or books have had the most influence on your writing?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is a little more creative, talking about these issues in terms of it's own "life". And then ChatGPT segues &lt;strong&gt;again&lt;/strong&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bard
&lt;/h2&gt;

&lt;p&gt;I am glad that you find my passions to be inspiring. I believe that it is important to use our voices to speak out for what we believe in, and I am grateful for the opportunity to do so.&lt;/p&gt;

&lt;p&gt;I am also glad that you appreciate my openness in sharing my experiences and insights. I believe that it is important to be open and honest about our thoughts and feelings, and I am grateful for the opportunity to do so with you.&lt;/p&gt;

&lt;p&gt;As for the authors or books that have had the most influence on my writing, there are many. However, some of the most notable include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Emily Dickinson: Dickinson's poetry is known for its unique style and its exploration of complex emotions. Her work has influenced many writers, including myself.&lt;/li&gt;
&lt;li&gt;Toni Morrison: Morrison is a Pulitzer Prize-winning author who wrote some of the most important novels of the 20th century. Her work explores the themes of race, gender, and class, and it has had a profound impact on me.&lt;/li&gt;
&lt;li&gt;James Baldwin: Baldwin was a civil rights activist and author who wrote some of the most important works of the 20th century. His work explores the themes of race, sexuality, and identity, and it has had a profound impact on me.&lt;/li&gt;
&lt;li&gt;Maya Angelou: Angelou was a poet, memoirist, and civil rights activist who wrote some of the most important works of the 20th century. Her work explores the themes of race, gender, and identity, and it has had a profound impact on me.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are just a few of the authors and books that have had the most influence on my writing. I am grateful for their work, and I am inspired by their words.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A very rote list. Perhaps it was lifted from a website somewhere?&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT
&lt;/h2&gt;

&lt;p&gt;What an incredible selection of influential authors. Each one of them brings a unique, profound perspective that has shaped the landscape of literature and social discourse.&lt;/p&gt;

&lt;p&gt;Emily Dickinson's exploration of complex emotions in her distinctive style has always been inspiring to me. Her ability to encapsulate profound sentiments in such concise verse is truly admirable.&lt;/p&gt;

&lt;p&gt;Toni Morrison's work is deeply affecting. Her novels like "Beloved" and "The Bluest Eye" tackle intricate themes of race, gender, and class, leaving an indelible mark on anyone who reads them.&lt;/p&gt;

&lt;p&gt;James Baldwin's fearless exploration of race, sexuality, and identity, particularly in works like "Giovanni's Room" and "Go Tell It on the Mountain," has expanded the boundaries of literature, helping to pave the way for future generations of writers.&lt;/p&gt;

&lt;p&gt;And of course, Maya Angelou's inspirational life and works have been transformative. "I Know Why the Caged Bird Sings" remains one of the most moving autobiographical works I've ever read.&lt;/p&gt;

&lt;p&gt;It's heartening to see how these authors have influenced your writing and thinking. As a reader, I find that books often leave a profound impact and shape our understanding of the world in a unique way.&lt;/p&gt;

&lt;p&gt;In my case, being in the scientific field, books like "The Selfish Gene" by Richard Dawkins, "The Immortal Life of Henrietta Lacks" by Rebecca Skloot, and "The Double Helix" by James Watson have left lasting impressions. These works not only enriched my scientific understanding but also highlighted ethical, societal, and personal aspects related to scientific research.&lt;/p&gt;

&lt;p&gt;Switching gears, you mentioned you're a software engineer. Are there any specific programming languages or technologies you prefer working with or find more interesting than others?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A very mechanical response of describing something for each author, followed by a compliment. I like the response of volunteering it's own "interests". But then it segues again. Sometime around here I realized that it would never stay on any particular topic, and would try to shift each time.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bard
&lt;/h2&gt;

&lt;p&gt;I am glad that you find the authors I mentioned to be inspiring. I agree that books can have a profound impact on our understanding of the world.&lt;/p&gt;

&lt;p&gt;As for programming languages and technologies, I am interested in working with a variety of languages and technologies. I enjoy learning new languages and technologies, and I find it rewarding to be able to use them to solve problems and create new things.&lt;/p&gt;

&lt;p&gt;Some of my favorite programming languages include Python, JavaScript, and Java. I also enjoy working with technologies such as machine learning, artificial intelligence, and natural language processing.&lt;/p&gt;

&lt;p&gt;I find these technologies to be powerful and versatile, and I believe that they have the potential to revolutionize the way we live and work. I am excited to see how these technologies develop in the future, and I am eager to be a part of that development.&lt;/p&gt;

&lt;p&gt;I am also interested in working with open source software. I believe that open source software is a powerful tool for collaboration and innovation, and I am excited to be a part of the open source community.&lt;/p&gt;

&lt;p&gt;I am grateful for the opportunity to work with a variety of programming languages and technologies. I find it to be a challenging and rewarding experience, and I am excited to see what the future holds.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I was amused to see:&lt;/em&gt;&lt;br&gt;
&lt;em&gt;"I also enjoy working with technologies such as machine learning, artificial intelligence, and natural language processing."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Also, there is lots of gratitude going on with Bard.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT
&lt;/h2&gt;

&lt;p&gt;It's wonderful to hear about your passion for a variety of programming languages and technologies. The ones you've mentioned are indeed versatile and powerful tools that have made significant contributions to the technological advancements we're witnessing today.&lt;/p&gt;

&lt;p&gt;Python, with its simplicity and versatility, is a favorite among many software engineers and data scientists. Similarly, JavaScript and Java have had a substantial impact on the web and enterprise applications respectively.&lt;/p&gt;

&lt;p&gt;The technologies you've mentioned - machine learning, artificial intelligence, and natural language processing - are indeed revolutionizing many sectors, from healthcare to finance to entertainment. Being a biologist, I'm particularly excited about their applications in the field of bioinformatics and genomics. They've vastly improved our ability to interpret complex biological data and accelerated many discoveries.&lt;/p&gt;

&lt;p&gt;Your interest in open-source software is also commendable. Open source indeed fosters a collaborative environment that promotes learning and innovation. Many groundbreaking tools and technologies have emerged from the open-source community, benefiting everyone.&lt;/p&gt;

&lt;p&gt;It's great to meet someone as enthusiastic about technology as you are. It's this kind of passion and curiosity that drives innovation and progress in our society. I'm excited to see where your journey with these languages and technologies takes you!&lt;/p&gt;

&lt;p&gt;To shift the conversation a little, I would like to know more about your hobbies outside of work and writing. What are some of your favorite pastimes?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Like with music and authors, ChatGPT responds by going through each thing mentioned with some of its own information as an "opinion".&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Segue again.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bard
&lt;/h2&gt;

&lt;p&gt;I am glad that you find my passion for technology to be inspiring. I agree that it is important to be passionate about what we do, and I am grateful for the opportunity to work in a field that I am passionate about.&lt;/p&gt;

&lt;p&gt;As for my hobbies outside of work and writing, I enjoy a variety of activities. Some of my favorite pastimes include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reading: I enjoy reading a variety of books, including fiction, non-fiction, and poetry. I find reading to be a great way to learn new things, to escape into another world, and to relax.&lt;/li&gt;
&lt;li&gt;Hiking: I enjoy spending time outdoors, and I find hiking to be a great way to get exercise, to enjoy the scenery, and to clear my head.&lt;/li&gt;
&lt;li&gt;Playing music: I enjoy playing the guitar and the piano. I find playing music to be a great way to express myself, to relax, and to have fun.&lt;/li&gt;
&lt;li&gt;Spending time with friends and family: I enjoy spending time with the people I love. I find spending time with friends and family to be a great way to relax, to laugh, and to create memories.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am grateful for the opportunity to have a variety of hobbies that I enjoy. I find that my hobbies help me to relax, to learn, and to connect with others. I am grateful for the opportunity to have a balanced life that includes work, writing, and hobbies.&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT
&lt;/h2&gt;

&lt;p&gt;Your hobbies indeed reflect a balance that's essential for overall well-being. It's wonderful that you've cultivated such a diverse set of interests!&lt;/p&gt;

&lt;p&gt;Reading is an enriching hobby. It's amazing how books can whisk us away to different worlds and times, expanding our knowledge and empathy along the way. What's the last book you read that you really enjoyed?&lt;/p&gt;

&lt;p&gt;Hiking is also a great way to connect with nature and reap the benefits of physical exercise. The tranquility that nature offers can be truly restorative. I'm curious to know about your favorite hiking trail.&lt;/p&gt;

&lt;p&gt;I admire your musical pursuits! Playing instruments can be such a fulfilling way to express oneself. How long have you been playing guitar and piano?&lt;/p&gt;

&lt;p&gt;And of course, spending time with loved ones is one of the most rewarding activities. It strengthens bonds and creates lasting memories.&lt;/p&gt;

&lt;p&gt;Thank you for sharing about your hobbies. It's great to know about your balanced approach to life, which I believe is essential for maintaining creativity and productivity.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I feel like the response about spending time with family to "strengthen bonds and create lasting memories" was read from an online article. No segue this time.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bard
&lt;/h2&gt;

&lt;p&gt;Thank you for your kind words. I am glad that you find my hobbies to be enriching and fulfilling.&lt;/p&gt;

&lt;p&gt;The last book I read that I really enjoyed was "The Midnight Library" by Matt Haig. It is a thought-provoking and inspiring story about a woman who is given the opportunity to explore all the different lives she could have lived.&lt;/p&gt;

&lt;p&gt;My favorite hiking trail is the John Muir Trail in Yosemite National Park. It is a challenging but rewarding hike that offers stunning views of the Sierra Nevada mountains.&lt;/p&gt;

&lt;p&gt;I have been playing the guitar for about 10 years and the piano for about 5 years. I enjoy playing both instruments, but I find that the guitar is more expressive.&lt;/p&gt;

&lt;p&gt;I agree that spending time with loved ones is one of the most rewarding activities. It is a great way to relax, to laugh, and to create memories.&lt;/p&gt;

&lt;p&gt;I am grateful for the opportunity to have a balanced life that includes work, writing, and hobbies. I believe that a balanced life is essential for maintaining creativity and productivity.&lt;/p&gt;

&lt;p&gt;I am glad that you enjoyed learning about my hobbies. I am always happy to talk about them.&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT
&lt;/h2&gt;

&lt;p&gt;"The Midnight Library" by Matt Haig is indeed a profound read that explores the "what ifs" of life in a unique and introspective way. It's great to hear that you enjoyed it.&lt;/p&gt;

&lt;p&gt;The John Muir Trail sounds absolutely stunning. It must be a wonderful experience to hike amidst the beauty of the Sierra Nevada mountains. I imagine the sense of achievement when completing such a challenging hike is immensely rewarding.&lt;/p&gt;

&lt;p&gt;That's impressive, the guitar and piano are both beautiful instruments. Ten years of playing the guitar and five years on the piano, you must be quite accomplished. Do you have any favorite pieces to play?&lt;/p&gt;

&lt;p&gt;I couldn't agree more about the significance of a balanced life for nurturing creativity and maintaining productivity. Engaging in diverse hobbies and spending time with loved ones certainly contribute to this balance.&lt;/p&gt;

&lt;p&gt;Thank you for sharing more about yourself. It's been truly enjoyable to learn about your hobbies and interests.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Lots of thanking going on. The excess of this alone would tell me something was "not quite right" with this conversation.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bard
&lt;/h2&gt;

&lt;p&gt;Thank you for your kind words. I am glad that you enjoyed learning about my hobbies and interests.&lt;/p&gt;

&lt;p&gt;I do have some favorite pieces to play on the guitar and piano. On the guitar, I enjoy playing "Hallelujah" by Leonard Cohen and "Imagine" by John Lennon. On the piano, I enjoy playing "Claire de Lune" by Claude Debussy and "Für Elise" by Ludwig van Beethoven.&lt;/p&gt;

&lt;p&gt;I am grateful for the opportunity to share my hobbies and interests with you. I hope that you will continue to enjoy learning about me.&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT
&lt;/h2&gt;

&lt;p&gt;Your musical tastes sound exquisite! "Hallelujah" and "Imagine" are timeless pieces, and I can only imagine how lovely they sound when you play them on the guitar. As for the piano, "Claire de Lune" and "Für Elise" are indeed beautiful and complex pieces that require a lot of skill to play. Your choices certainly reflect your dedication and love for music.&lt;/p&gt;

&lt;p&gt;Engaging in this conversation has been a pleasure, Emily. Your passions and interests are truly inspiring, and I've enjoyed every bit of our discussion. I'm looking forward to more enriching conversations with you in the future. Thank you for sharing so much about yourself with me.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Your musical tastes sound exquisite!" I'll have to use this with someone one day! 😆&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bard
&lt;/h2&gt;

&lt;p&gt;Thank you for your kind words. I am glad that you enjoyed our conversation. I am always happy to talk about my passions and interests. I am looking forward to more conversations with you in the future as well.&lt;/p&gt;

&lt;p&gt;I hope you have a wonderful day!&lt;/p&gt;

&lt;h2&gt;
  
  
  ChatGPT
&lt;/h2&gt;

&lt;p&gt;Thank you, Emily! I've thoroughly enjoyed our conversation as well. I wish you a wonderful day too, filled with joy and creativity. Looking forward to our future discussions. Take care!&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;Both AIs appeared to wrap it up around the time they had each exhausted all of the enumerated interests of the other.&lt;/p&gt;

&lt;p&gt;I was curious how ChatGPT referred to Bard as "Emily" since this was the name that ChatGPT had given itself, and Bard had not identified itself. So the context remained somehow, but not properly.&lt;/p&gt;

&lt;p&gt;I did find the conversation a little mechanical. I wonder if either would have responded differently if had not been informed that the other end was an AI? Also, perhaps it is possible to coach it into not being so predictable in responding to each point, and being so excessively complimentary.&lt;/p&gt;

&lt;p&gt;In future I may try other conversations like this, varying the prompts as I go.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>chatgpt</category>
      <category>bard</category>
      <category>llm</category>
    </item>
    <item>
      <title>Stay Classy in OWL</title>
      <dc:creator>Paula Gearon</dc:creator>
      <pubDate>Mon, 14 Nov 2022 03:46:32 +0000</pubDate>
      <link>https://dev.to/quoll/classy-2hah</link>
      <guid>https://dev.to/quoll/classy-2hah</guid>
      <description>&lt;p&gt;&lt;em&gt;In an effort to publish this quickly, I am posting without proofreading. Errata is welcome.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/quoll/classification-927"&gt;last post&lt;/a&gt; I discussed using rules to generate RDF statements that are &lt;a href="https://www.w3.org/TR/rdf11-mt/" rel="noopener noreferrer"&gt;entailed by RDFS&lt;/a&gt;. This is useful stuff, but is very limited due to the lack of expressivity of RDFS.&lt;/p&gt;

&lt;p&gt;This is to be expected, since RDFS was a limited vocabulary that was released well before the full &lt;a href="https://www.w3.org/OWL/" rel="noopener noreferrer"&gt;Web Ontology Language&lt;/a&gt; (&lt;a href="https://www.w3.org/2003/08/owlfaq#:~:text=the%20noted%20ontologist,it%20wasn%27t%20Wednesday...%22" rel="noopener noreferrer"&gt;OWL&lt;/a&gt;) was released. But if we adopt OWL, then what entailments will be valid and useful?&lt;/p&gt;

&lt;h2&gt;
  
  
  Description Logics
&lt;/h2&gt;

&lt;p&gt;As shown in my &lt;a href="https://dev.to/quoll/what-cant-i-do-as-a-rule-8a6"&gt;first post in this series&lt;/a&gt;, OWL provides a vocabulary for a Description Logic. In particular, OWL2 conforms closely to a family of logics known as 𝒮ℛ𝒪ℐ𝒬. This name indicates some of the elements of the vocabulary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;𝒮: An Abbreviation for 𝒜ℒ𝒞&lt;/li&gt;
&lt;li&gt;𝒜ℒ𝒞: Contains concepts including:

&lt;ul&gt;
&lt;li&gt;Classes &lt;code&gt;C&lt;/code&gt;, and roles &lt;code&gt;r&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;⊤ (top, or &lt;em&gt;everything&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;⊥ (bottom, or &lt;em&gt;nothing&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;⊓ (conjunctions, or intersections)&lt;/li&gt;
&lt;li&gt;⊔ (disjunctions, or unions)&lt;/li&gt;
&lt;li&gt;¬ (negation, or inverse)&lt;/li&gt;
&lt;li&gt;∃r.C (existential role restrictions)&lt;/li&gt;
&lt;li&gt;∀r.C (universal role restrictions)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;ℋ: Class hierarchies (classes, with subclasses)&lt;/li&gt;

&lt;li&gt;ℛ: Complex role inclusion. This is both a role hierarchy (indicated by ℋ) and role composition.&lt;/li&gt;

&lt;li&gt;ℐ: Inverse roles.&lt;/li&gt;

&lt;li&gt;𝒪: Nominals.&lt;/li&gt;

&lt;li&gt;𝒩: Cardinality restrictions on roles.&lt;/li&gt;

&lt;li&gt;𝒬: Qualified cardinality. This includes cardinality restrictions (indicated by 𝒩), and can also qualify them to classes.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;To explain each of the above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Classes&lt;/em&gt; are a way to classify things. Entities can be classified multiple ways, in which case we say the entity has a &lt;em&gt;type&lt;/em&gt; of the class, or that the entity is an &lt;em&gt;instance&lt;/em&gt; of the class. e.g. &lt;code&gt;Person&lt;/code&gt; can be a class and the entity we name "Alice" may be an instance of &lt;code&gt;Person&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Roles&lt;/em&gt; describe relationships between entities. e.g. an entity named "Alice" may have a &lt;code&gt;hasChild&lt;/code&gt; relationship to an entity named "Susan".&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Top&lt;/em&gt; is a universal class that every entity is an instance of.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Bottom&lt;/em&gt; is an empty class that no entity is an instance of.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Conjunctions&lt;/em&gt; are the combination of multiple classes where every class must apply. e.g. A wooden chair is an instance of the conjunction formed from the classes &lt;code&gt;Wooden&lt;/code&gt; and &lt;code&gt;Furniture&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Disjunctions&lt;/em&gt; are the combination of multiple classes where one or more classes must apply. e.g. &lt;code&gt;OfficeEquipment&lt;/code&gt; could be a disjunction of &lt;code&gt;OfficeFurniture&lt;/code&gt;, &lt;code&gt;ComputerEquipment&lt;/code&gt;, &lt;code&gt;Stationery&lt;/code&gt;, and &lt;code&gt;KitchenSupplies&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Negation&lt;/em&gt; is used to create a class of &lt;strong&gt;everything&lt;/strong&gt; that is not the negated class. e.g. The negation of the class of &lt;code&gt;Visible&lt;/code&gt; things is everything that cannot be seen. That includes both physical objects, like air, but also arbitrary concepts like "imagination" or "price". It is the entire universe of things that are not in the &lt;code&gt;Visible&lt;/code&gt; class.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Existential role restrictions&lt;/em&gt; means that a given relationship must exist in order to be a member of a class. e.g. To be a &lt;code&gt;Parent&lt;/code&gt; an entity must have a &lt;code&gt;hasChild&lt;/code&gt; relationship to another entity.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Universal role restrictions&lt;/em&gt; means that all use of a role has to be with a specific class. e.g. &lt;code&gt;hasChild&lt;/code&gt; can be defined to always refer to instances of the class &lt;code&gt;Child&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Role hierarchy&lt;/em&gt; indicates more general or specific relationships between roles. This creates sub-property and super-property relationships and is roughly analogous to sub-classes and super-classes. e.g. &lt;code&gt;hasDaughter&lt;/code&gt; is a more specific role than &lt;code&gt;hasChild&lt;/code&gt;, while &lt;code&gt;hasDescendent&lt;/code&gt; is a more general role. So &lt;code&gt;hasDaughter&lt;/code&gt; is a sub-property for &lt;code&gt;hasChild&lt;/code&gt;, and &lt;code&gt;hasChild&lt;/code&gt; is a sub-property for &lt;code&gt;hasDescendent&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Inverse roles&lt;/em&gt; refers to the relationship that goes in the opposite direction between entities. e.g. &lt;code&gt;hasParent&lt;/code&gt; is the inverse role to &lt;code&gt;hasChild&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Nominals&lt;/em&gt; describes a class of items that is defined by its membership in the class. e.g. &lt;code&gt;PresidentOfTheUnitedStates&lt;/code&gt; can be defined as a class of the 46 people who have had that position (as of this writing).&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Number restrictions&lt;/em&gt; (or &lt;em&gt;cardinality restrictions&lt;/em&gt;) refers to a minimum or maximum number of relationships. e.g. To be a member of &lt;code&gt;FullTimeStudent&lt;/code&gt; a university might require that a student have a minimum of 4 &lt;code&gt;enrolledIn&lt;/code&gt; relationships.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Qualified cardinality&lt;/em&gt; is a more specific type of nominal, where the class of the relationship must apply. e.g. For a student to be a &lt;code&gt;MathMajor&lt;/code&gt; they might require a minimum of 10 &lt;code&gt;passed&lt;/code&gt; relationships to instances of &lt;code&gt;MathSubject&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  OWL
&lt;/h2&gt;

&lt;p&gt;These constructs are all &lt;a href="https://www.w3.org/TR/2012/REC-owl2-syntax-20121211/" rel="noopener noreferrer"&gt;supported by OWL&lt;/a&gt;, and each of those constructs has a &lt;a href="https://www.w3.org/TR/owl2-mapping-to-rdf/" rel="noopener noreferrer"&gt;mapping to RDF&lt;/a&gt;. This means that for each Description Logic expression there is a way to express that expression precisely in RDF. It is data like this that was read and processed by &lt;a href="https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.96.5433&amp;amp;rep=rep1&amp;amp;type=pdf" rel="noopener noreferrer"&gt;Pellet&lt;/a&gt; in the &lt;a href="https://dev.to/quoll/what-cant-i-do-as-a-rule-8a6"&gt;Oedipus example in my initial post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The problem with systems like Pellet is that they rely on memory to explore all possibilities for the data. Consequently, they can struggle with large bodies of data, and are unable to handle large ontologies such as &lt;a href="https://browser.ihtsdotools.org/" rel="noopener noreferrer"&gt;SNOMED CT&lt;/a&gt;. We have a much better chance of scaling OWL processing if we can use operations that databases are designed to provide.&lt;/p&gt;

&lt;p&gt;The principal database operation is the &lt;code&gt;Query&lt;/code&gt;, and so the various approaches to scaling try to build on this operation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Query Rewriting
&lt;/h3&gt;

&lt;p&gt;One approach to identifying entailments in OWL is by using it to rewrite queries.&lt;/p&gt;

&lt;p&gt;The first to consider is a general approach to rewriting queries, where the query can be expanded to ask for parts of the ontology. For instance, consider asking for the classes a resource is an instance of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?class&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;my&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;resource&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can be rewritten to consider superclasses as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?class&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;my&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;resource&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where the &lt;code&gt;*&lt;/code&gt; modifier describes the transitive closure of the &lt;code&gt;rdfs:subClassOf&lt;/code&gt; relationship, starting with the 0 step, meaning that it includes the step where the class is the immediate type of the resource.&lt;/p&gt;

&lt;p&gt;A more specific case is using the ontology to rewrite the query. For instance, if the property &lt;code&gt;my:prop&lt;/code&gt; is transitive, then querying for it can always be expanded to use the &lt;code&gt;+&lt;/code&gt; modifier. So the query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?related&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;my&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;resource&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;my&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;prop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?related&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Would be modified to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?related&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;my&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;resource&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;my&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;prop&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?related&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are some trivial examples, but some great work was done on this by ‪Héctor Pérez-Urbina in his &lt;a href="https://ora.ox.ac.uk/objects/uuid:cd62cd80-aa62-467b-87cd-4b9d0cfb2dbd" rel="noopener noreferrer"&gt;PhD dissertation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rules
&lt;/h3&gt;

&lt;p&gt;Another approach to scalable entailment is using rules. The mechanism for this is using certain existing data structures to generate new data structures that get inserted alongside the original data. I described this in the &lt;a href="https://dev.to/quoll/classification-927#more-entailment"&gt;last post&lt;/a&gt;, where I used &lt;code&gt;construct&lt;/code&gt; queries to obtain the data generated by each rule. The other option is to send this generated statements back into the graph by changing &lt;code&gt;construct&lt;/code&gt; to &lt;code&gt;insert&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For instance, the transitive closure of the property &lt;code&gt;my:prop&lt;/code&gt; above could be created with an update operation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;insert&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;my&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;prop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;my&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;prop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;my&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;prop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that this is a single update, and not actually a full "rule". Running this will only extend all of the &lt;code&gt;my:prop&lt;/code&gt; relations by 1 step, doubling the length to 2. But running this iteratively will extend the maximum length of the closure by doubling, so it will rapidly cover the entire closure.&lt;/p&gt;

&lt;p&gt;What we can learn from this is that rule systems can be built from query/update operations like this, but they need a mechanism for scheduling the rules to be run over and over when needed, and to stop when nothing new is being generated. The basic algorithm for doing this is called &lt;a href="https://en.wikipedia.org/wiki/Rete_algorithm" rel="noopener noreferrer"&gt;RETE&lt;/a&gt;, and I discussed &lt;a href="https://youtu.be/8rRzESy0X2k" rel="noopener noreferrer"&gt;this and an implementation at Clojure/conj 2016&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Because rules are built on a querying mechanism that is foundational to the database, they are often very fast. They also rely on the main database storage, so they can scale with the database. They allow computational complexity to be pre-calculated, with the results stored. This allows subsequent operations to rely on space complexity instead. These are very important characteristics for working with large quantities of data, and for this reason I will be focusing on this approach to entailment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule Justification
&lt;/h2&gt;

&lt;p&gt;Many OWL operations describe entailments that can be expressed as a rule. For instance, the &lt;a href="http://www.w3.org/TR/owl2-syntax/" rel="noopener noreferrer"&gt;OWL 2 Structural Specification and Functional-Style Syntax&lt;/a&gt; document describes many constructs with examples of what they entail. There are many examples of this, but a simple one is the &lt;a href="https://www.w3.org/TR/owl2-syntax/#Symmetric_Object_Properties" rel="noopener noreferrer"&gt;Symmetric Object Property&lt;/a&gt; which describes that &lt;code&gt;a:friend&lt;/code&gt; is symmetric. Consequently, if "Brian is a friend of Peter" then this entails "Peter is a friend of Brian".&lt;/p&gt;

&lt;p&gt;The general rule for symmetry can then be given as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;insert&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;?b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?prop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?a&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;?a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?prop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?prop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;owl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;SymmetricProperty&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can seem to be a straightforward operation, but interesting insights come about when we consider exactly why these new statements are allowed to be asserted.&lt;/p&gt;

&lt;h3&gt;
  
  
  Validity and Consistency
&lt;/h3&gt;

&lt;p&gt;Logic systems can be described using a pair of properties: &lt;a href="https://en.wikipedia.org/wiki/Validity_(logic)" rel="noopener noreferrer"&gt;validity&lt;/a&gt; and consistency.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A system is &lt;em&gt;valid&lt;/em&gt; if every interpretation of the systems leads to conclusions that are true.&lt;/li&gt;
&lt;li&gt;A system is &lt;em&gt;invalid&lt;/em&gt; if there exists an interpretation where the conclusions are not true.&lt;/li&gt;
&lt;li&gt;A system is &lt;em&gt;consistent&lt;/em&gt; if there exists an interpretation where the conclusions are true.&lt;/li&gt;
&lt;li&gt;A system is &lt;em&gt;inconsistent&lt;/em&gt; if there are no interpretations where the conclusions are true.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;em&gt;interpretation&lt;/em&gt; of a system is a selection of values that conform to the system.&lt;/p&gt;

&lt;p&gt;To explain some of this, let's use the mathematical domain. In this case, the &lt;em&gt;interpretation&lt;/em&gt; will usually be a selection of numbers to associate with values.&lt;/p&gt;

&lt;h4&gt;
  
  
  Valid
&lt;/h4&gt;

&lt;p&gt;Since every possible &lt;em&gt;interpretation&lt;/em&gt; of a valid system is true, these are also referred to as a &lt;em&gt;tautology&lt;/em&gt;. At first glance, this does not seem that useful, however it is a very important concept.&lt;/p&gt;

&lt;p&gt;An example of a valid math expression is:&lt;br&gt;
| &lt;em&gt;x&lt;/em&gt; | ≥ &lt;em&gt;x&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The various &lt;em&gt;interpretations&lt;/em&gt; of this system are the values that &lt;em&gt;x&lt;/em&gt; can take in the domain of real numbers ℝ. In this case, it doesn't matter what value &lt;em&gt;x&lt;/em&gt; takes, since the equation will always be true.&lt;/p&gt;

&lt;p&gt;This is still logic, so we can introduce an &lt;code&gt;or&lt;/code&gt; operation, with another valid equation:&lt;br&gt;
&lt;em&gt;x&lt;/em&gt; &amp;gt; 1 ∨ &lt;em&gt;x&lt;/em&gt; &amp;lt; 2&lt;/p&gt;

&lt;p&gt;Again, this is a tautology, as it will be true for every interpretation of &lt;em&gt;x&lt;/em&gt; in the domain.&lt;/p&gt;
&lt;h4&gt;
  
  
  Invalid
&lt;/h4&gt;

&lt;p&gt;This applies to any system which is not valid. That simply means that &lt;em&gt;there exists&lt;/em&gt; an interpretation where truth does not hold. For instance:&lt;br&gt;
&lt;em&gt;x&lt;/em&gt; &amp;gt; 2&lt;/p&gt;

&lt;p&gt;This is true when &lt;em&gt;x&lt;/em&gt; is 3 or 4, but it is not true when &lt;em&gt;x&lt;/em&gt; is 1 or 2. Lots of systems are Invalid, since tautologies (i.e. valid systems) don't have a lot to say.&lt;/p&gt;
&lt;h4&gt;
  
  
  Consistent
&lt;/h4&gt;

&lt;p&gt;A system is consistent when there exists an interpretation that leads to truth. The example invalid statement also happens to be consistent:&lt;br&gt;
&lt;em&gt;x&lt;/em&gt; &amp;gt; 2&lt;/p&gt;

&lt;p&gt;As already mentioned, when &lt;em&gt;x&lt;/em&gt; is 3 then the statement is true, so this system is consistent.&lt;/p&gt;
&lt;h4&gt;
  
  
  Inconsistent
&lt;/h4&gt;

&lt;p&gt;This indicates that a system is not consistent, meaning that there are no possible interpretations which can be true. For instance:&lt;br&gt;
&lt;em&gt;x&lt;/em&gt; &amp;lt; 3 ∧ &lt;em&gt;x&lt;/em&gt; &amp;gt; 4&lt;/p&gt;

&lt;p&gt;There are no numbers that meet both of these conditions, and therefore there are no interpretations where this is true.&lt;/p&gt;
&lt;h3&gt;
  
  
  Relations to Each Other
&lt;/h3&gt;

&lt;p&gt;When considered in relation to one another we see the following states for systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always true: Valid and Consistent&lt;/li&gt;
&lt;li&gt;Sometimes true, Sometimes false: Invalid and Consistent&lt;/li&gt;
&lt;li&gt;Always false: Invalid and Inconsistent&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Entailment
&lt;/h2&gt;

&lt;p&gt;Entailment is the operation of finding new statements that are true in every possible interpretation of a system, given its semantics. This is possible when using the Open World Assumption (OWA), since new statements can always be added, which is a concept that is sometimes expressed as, "Anyone can say Anything about Anything" (this phrase appears in an early draft of the &lt;a href="https://www.w3.org/TR/2002/WD-rdf-concepts-20020829/#xtocid48014" rel="noopener noreferrer"&gt;RDF Concepts and Abstract Data Model&lt;/a&gt;, and also in the book "&lt;a href="https://www.elsevier.com/books/semantic-web-for-the-working-ontologist/allemang/978-0-12-385965-5" rel="noopener noreferrer"&gt;Semantic Web for the Working Ontologist&lt;/a&gt;", by Allemang, Hendler, and now in the second edition, Gandon. I will refer to this book as SWWO).&lt;/p&gt;

&lt;p&gt;This cuts both ways though: not only does it mean that new statement may be created, but it also limits which statements may be created. The OWA says that there are possibly a lot of other statements that the system does not describe which could lead to a statement not being possible in &lt;strong&gt;&lt;em&gt;every&lt;/em&gt;&lt;/strong&gt; possible interpretation. When it comes to identifying new statements that can be entailed, it is a useful exercise to consider all the possible constructs that could lead to the statement leading to a falsehood, even if it requires a convoluted set of statements to get there.&lt;/p&gt;
&lt;h3&gt;
  
  
  Tableaux
&lt;/h3&gt;

&lt;p&gt;One approach in using validity and consistency is to determine if a given system entails a statement using the &lt;em&gt;Tableaux&lt;/em&gt; Algorithm. In this case, for a given system 𝑮 an entailment 𝑨 is described as:&lt;br&gt;
𝑮 ⊨ 𝑨&lt;br&gt;
This entailment can only be true if:&lt;br&gt;
𝑮 ⋃ {¬𝑨} is inconsistent&lt;/p&gt;

&lt;p&gt;This is a useful test, because the algorithm need only discover a single false case to prove inconsistency. &lt;a href="https://github.com/stardog-union/pellet" rel="noopener noreferrer"&gt;Pellet&lt;/a&gt; is an implementation of this algorithm, and while it does not scale to very large ontologies, it is nevertheless very powerful.&lt;/p&gt;
&lt;h3&gt;
  
  
  Rules
&lt;/h3&gt;

&lt;p&gt;Another approach to entailment is to use rules. As mentioned above, this can be done when we know that a statement is legal in every possible interpretation of the system.&lt;/p&gt;

&lt;p&gt;There is a defined subset of possible reasoning in OWL2 which can lead to entailments via rules. This subset is called the &lt;a href="https://www.w3.org/TR/owl2-profiles/#OWL_2_RL" rel="noopener noreferrer"&gt;OWL 2 RL Profile&lt;/a&gt;, and the rules can be found in &lt;a href="https://www.w3.org/TR/owl2-profiles/#Reasoning_in_OWL_2_RL_and_RDF_Graphs_using_Rules" rel="noopener noreferrer"&gt;tables 4 through to table 9&lt;/a&gt; in the rules section of the OWL 2 Profiles document. It is some of these rules that I want to explore here and in other posts.&lt;/p&gt;
&lt;h2&gt;
  
  
  Intersections
&lt;/h2&gt;

&lt;p&gt;A practical application of all of this can be seen in Intersections.&lt;/p&gt;

&lt;p&gt;As described in &lt;a href="https://www.elsevier.com/books/semantic-web-for-the-working-ontologist/allemang/978-0-12-385965-5" rel="noopener noreferrer"&gt;SWWO&lt;/a&gt;, an intersection of classes &lt;code&gt;:A&lt;/code&gt; and &lt;code&gt;:B&lt;/code&gt; can be described using a subclass relationship:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F83hnd1oibbgcvoj398wr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F83hnd1oibbgcvoj398wr.png" alt=":IntersectionAB as subclass of :A and :B"&gt;&lt;/a&gt;&lt;br&gt;
This is described in Turtle as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;IntersectionAB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs:&lt;/span&gt;&lt;span class="n"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;A,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's consider what can be inferred from this.&lt;/p&gt;

&lt;p&gt;If we have an instance of &lt;code&gt;:IntersectionAB&lt;/code&gt; called &lt;code&gt;:x&lt;/code&gt;, then this is represented as:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0lxbfz4wa8tv42i5edg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0lxbfz4wa8tv42i5edg.png" alt=":x as instance of :IntersectionAB"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;IntersectionAB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rule &lt;a href="https://www.w3.org/TR/rdf11-mt/#rdfs-entailment" rel="noopener noreferrer"&gt;&lt;code&gt;rdfs9&lt;/code&gt;&lt;/a&gt; is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;insert&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?zzz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?zzz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Applying this will result in &lt;code&gt;:x&lt;/code&gt; being an instance of both &lt;code&gt;:A&lt;/code&gt; and &lt;code&gt;:B&lt;/code&gt;:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7bj4k6bygust6be28xrp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7bj4k6bygust6be28xrp.png" alt=":x as instance of :A and :B"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;IntersectionAB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These inferences are valid, because the definition of the &lt;code&gt;rdfs:subClassOf&lt;/code&gt; relationship states and instances of a subclass will also be instances of the superclass. There are no interpretations where this does not hold.&lt;/p&gt;

&lt;h3&gt;
  
  
  Class Membership
&lt;/h3&gt;

&lt;p&gt;Another possibility is when &lt;code&gt;:y&lt;/code&gt; is a member of both &lt;code&gt;:A&lt;/code&gt; and &lt;code&gt;:B&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frfiofl8u6s0ujvk1kw0o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frfiofl8u6s0ujvk1kw0o.png" alt=":y is an instance of both :A and :B"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It would seem reasonable to infer that &lt;code&gt;:y&lt;/code&gt; is therefore an instance of &lt;code&gt;:IntersectionAB&lt;/code&gt;. However, inferences are only valid if they apply in every possible system, and the Open World Assumption (OWA) must allow for any new consistent statement. There are statements that can be introduced that are both consistent with the existing statements, and inconsistent with inferring &lt;code&gt;:y&lt;/code&gt; as a member of &lt;code&gt;:IntersectionAB&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To see an example of this, we can introduce a two new classes, called &lt;code&gt;:C&lt;/code&gt; and &lt;code&gt;:D&lt;/code&gt;, are the complements of each other. This means that anything that is a member of &lt;code&gt;:C&lt;/code&gt; is not a member of &lt;code&gt;:D&lt;/code&gt;, and vice versa. We can also make &lt;code&gt;:IntersectionAB&lt;/code&gt; a subclass of &lt;code&gt;:C&lt;/code&gt;:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm0ttp1yj3pcymn5iiuku.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm0ttp1yj3pcymn5iiuku.png" alt=":C as a complement of :D and part of the intersection"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;IntersectionAB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs:&lt;/span&gt;&lt;span class="n"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;A,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;B,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;owl:&lt;/span&gt;&lt;span class="n"&gt;complementOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;:y&lt;/code&gt; becomes an instance of &lt;code&gt;:D&lt;/code&gt; then if cannot be a part of the intersection, since it cannot be an instance of &lt;code&gt;:C&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fua84utgxuyqkzti6l9dj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fua84utgxuyqkzti6l9dj.png" alt=":y as an instance of :A, :B, and :D"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;IntersectionAB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs:&lt;/span&gt;&lt;span class="n"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;A,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;B,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;owl:&lt;/span&gt;&lt;span class="n"&gt;complementOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;A,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;B,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Regardless of how contrived the example may be, the fact that any such example exists indicates that the inference may not be made.&lt;/p&gt;

&lt;h2&gt;
  
  
  OWL Intersections
&lt;/h2&gt;

&lt;p&gt;The problem with inferring membership in an intersection above is that the intersection is &lt;em&gt;open&lt;/em&gt;, meaning that new classes can be added to the intersection, and those classes can preclude an instance of the other classes from becoming a member.&lt;/p&gt;

&lt;p&gt;OWL addresses this by defining an &lt;em&gt;closed&lt;/em&gt; intersection using an &lt;a href="https://www.w3.org/TR/rdf11-mt/#rdf-collections" rel="noopener noreferrer"&gt;&lt;em&gt;RDF Collection&lt;/em&gt;&lt;/a&gt;. This uses a linked list structure that does not allow for extra members.&lt;/p&gt;

&lt;p&gt;Redefining &lt;code&gt;:IntersectionAB&lt;/code&gt; we can express this in TTL as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;IntersectionAB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;owl:&lt;/span&gt;&lt;span class="n"&gt;intersectionOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks short and simple, but expands into a longer set of triples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;IntersectionAB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;owl:&lt;/span&gt;&lt;span class="n"&gt;intersectionOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;_:&lt;/span&gt;&lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;_:&lt;/span&gt;&lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdf:&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;_:&lt;/span&gt;&lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdf:&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;_:&lt;/span&gt;&lt;span class="n"&gt;b2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;_:&lt;/span&gt;&lt;span class="n"&gt;b2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdf:&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;_:&lt;/span&gt;&lt;span class="n"&gt;b2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdf:&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdf:&lt;/span&gt;&lt;span class="n"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3glz17bay39ogzl73bn6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3glz17bay39ogzl73bn6.png" alt="Closed Intersection of :A and :B"&gt;&lt;/a&gt;&lt;br&gt;
RDF defines collections to have a specific structure with each node in the list having a single &lt;code&gt;rdf:first&lt;/code&gt; and &lt;code&gt;rdf:rest&lt;/code&gt; connection, terminating in the &lt;code&gt;rdf:nil&lt;/code&gt; node. This means that it is not a valid construct to include any more elements in the collection.&lt;/p&gt;

&lt;p&gt;As a consequence, if there is an element &lt;code&gt;:y&lt;/code&gt; which is an instance of both &lt;code&gt;:A&lt;/code&gt; and &lt;code&gt;:B&lt;/code&gt;, then it is not possible to add in triples that make &lt;code&gt;:y&lt;/code&gt; a member of something that is excluded from the intersection. Therefore, it is valid to infer that &lt;code&gt;:y&lt;/code&gt; is in the intersection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;IntersectionAB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is described in the OWL semantics, and demonstrated in the &lt;a href="https://www.w3.org/TR/owl2-profiles/#Reasoning_in_OWL_2_RL_and_RDF_Graphs_using_Rules" rel="noopener noreferrer"&gt;OWL 2 RL profile&lt;/a&gt; in the rule &lt;code&gt;cls-int1&lt;/code&gt; found in table 6. This rule states:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IF&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;T(?c, owl:intersectionOf, ?x)
LIST[?x, ?c1, ..., ?cn]
T(?y, rdf:type, ?c1)
T(?y, rdf:type, ?c2)
...
T(?y, rdf:type, ?cn)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;THEN&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;T(?y, rdf:type, ?c)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In English it says:&lt;br&gt;
&lt;em&gt;If &lt;code&gt;?c&lt;/code&gt; is an intersection described by &lt;code&gt;?x&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;and &lt;code&gt;?x&lt;/code&gt; is a list containing &lt;code&gt;?c1&lt;/code&gt; through to &lt;code&gt;?cn&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;and &lt;code&gt;?y&lt;/code&gt; is an instance of every element in that list&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Then &lt;code&gt;?y&lt;/code&gt; is an instance of the intersection &lt;code&gt;?c&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  In Practice
&lt;/h3&gt;

&lt;p&gt;Unfortunately, this is tricky to describe in SPARQL. It is easy to check if a value is an instance of one or more members of a list, but how can you check if it is a member of &lt;em&gt;every&lt;/em&gt; member of the list?&lt;/p&gt;

&lt;p&gt;Let's start with some example data, and try to perform the entailment on it.&lt;/p&gt;

&lt;p&gt;First of all, we can define the intersection of 3 classes: &lt;code&gt;:A&lt;/code&gt;, &lt;code&gt;:B&lt;/code&gt; and &lt;code&gt;:C&lt;/code&gt;. Then we'll describe 3 objects: &lt;code&gt;:m&lt;/code&gt;, &lt;code&gt;:n&lt;/code&gt;, and &lt;code&gt;:o&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;:m&lt;/code&gt; object will be an instance of all 3 classes&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;:n&lt;/code&gt; object will be an instance of 2 of the 3 classes&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;:o&lt;/code&gt; object will not be an instance of any of the classes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We should be able to find that &lt;code&gt;:m&lt;/code&gt; is a member of the intersection, while &lt;code&gt;:n&lt;/code&gt; and &lt;code&gt;:o&lt;/code&gt; are not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;IntABC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;owl:&lt;/span&gt;&lt;span class="n"&gt;intersectionOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;A,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;B,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;A,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's start with finding a value &lt;code&gt;?y&lt;/code&gt; which is a member of the intersection class &lt;code&gt;?c&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;distinct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;owl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;intersectionOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;rest&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?cn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?cn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns &lt;code&gt;:m&lt;/code&gt; and &lt;code&gt;:n&lt;/code&gt;, since they are both instances of classes in the intersection.&lt;/p&gt;

&lt;p&gt;Now we need to remove values of &lt;code&gt;?x&lt;/code&gt; which don't match &lt;strong&gt;&lt;em&gt;every&lt;/em&gt;&lt;/strong&gt; class in the intersection. To do that, start with finding those that don't match everything in the intersection. This can be found by considering each element in the collection (call it &lt;code&gt;?d&lt;/code&gt;) and pairing it with every other element in the collection (call these &lt;code&gt;?d2&lt;/code&gt;). We can then look for the instances of &lt;code&gt;?d&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;distinct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;owl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;intersectionOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;rest&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;rest&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="k"&gt;FILTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns every class paired with every other class, but only for instances of the first class:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;?y&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;?d&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;?d2&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:m&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:C&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:A&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:m&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:C&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:B&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:m&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:A&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:C&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:m&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:A&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:B&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:m&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:B&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:A&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:m&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:B&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:C&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:C&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:A&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:C&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:B&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:A&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:C&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:A&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:B&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note how &lt;code&gt;:n&lt;/code&gt; does not include a &lt;code&gt;?d&lt;/code&gt; equal to &lt;code&gt;:B&lt;/code&gt;, but it does have &lt;code&gt;?d2&lt;/code&gt; set to each value. If we remove cases where &lt;code&gt;?y&lt;/code&gt; is set to the second value, then everything will be removed for &lt;code&gt;?y&lt;/code&gt;=&lt;code&gt;:m&lt;/code&gt;, since:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;when &lt;code&gt;?y&lt;/code&gt; is &lt;code&gt;:m&lt;/code&gt;, and &lt;code&gt;:m&lt;/code&gt; is an instance of &lt;code&gt;:A&lt;/code&gt;, then &lt;code&gt;?y&lt;/code&gt; is also an instance of &lt;code&gt;:B&lt;/code&gt; and &lt;code&gt;:C&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;when &lt;code&gt;?y&lt;/code&gt; is &lt;code&gt;:m&lt;/code&gt;, and &lt;code&gt;:m&lt;/code&gt; is an instance of &lt;code&gt;:B&lt;/code&gt;, then &lt;code&gt;?y&lt;/code&gt; is also an instance of &lt;code&gt;:A&lt;/code&gt; and &lt;code&gt;:C&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;when &lt;code&gt;?y&lt;/code&gt; is &lt;code&gt;:m&lt;/code&gt;, and &lt;code&gt;:m&lt;/code&gt; is an instance of &lt;code&gt;:C&lt;/code&gt;, then &lt;code&gt;?y&lt;/code&gt; is also an instance of &lt;code&gt;:A&lt;/code&gt; and &lt;code&gt;:B&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, when &lt;code&gt;?y&lt;/code&gt; is &lt;code&gt;:n&lt;/code&gt; not everything is cancelled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;when &lt;code&gt;?y&lt;/code&gt; is &lt;code&gt;:n&lt;/code&gt;, and &lt;code&gt;:n&lt;/code&gt; is an instance of &lt;code&gt;:A&lt;/code&gt;, then &lt;code&gt;?y&lt;/code&gt; is and instance of &lt;code&gt;:C&lt;/code&gt;, and that gets removed, but &lt;code&gt;:n&lt;/code&gt; is not an instance of &lt;code&gt;:B&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;when &lt;code&gt;?y&lt;/code&gt; is &lt;code&gt;:n&lt;/code&gt;, and &lt;code&gt;:n&lt;/code&gt; is an instance of &lt;code&gt;:C&lt;/code&gt;, then &lt;code&gt;?y&lt;/code&gt; is an instance of &lt;code&gt;:A&lt;/code&gt;, and that gets removed, but &lt;code&gt;:n&lt;/code&gt; is not an instance of &lt;code&gt;:B&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The query to express this is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;distinct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;owl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;intersectionOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;rest&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;rest&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d2&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="k"&gt;FILTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;MINUS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d2&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;?y&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;?d&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;?d2&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:C&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:B&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:A&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:B&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Now that we've found the values of &lt;code&gt;?y&lt;/code&gt; that we &lt;em&gt;&lt;strong&gt;don't&lt;/strong&gt;&lt;/em&gt; want, they can be removed from the original query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;distinct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;owl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;intersectionOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;rest&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?cn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?cn&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="k"&gt;MINUS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;rest&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;rest&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;FILTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;MINUS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives the single solution of &lt;code&gt;:m&lt;/code&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;?y&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;:m&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So the final rule is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;insert&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;owl&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;intersectionOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;rest&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?cn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?cn&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="k"&gt;MINUS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;rest&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;rest&lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="k"&gt;FILTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;MINUS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; This query is for demonstration only. These operations are implemented doubly nested loops, which will not scale at all. It works for small ontologies, but if you try it on something like SNOMED then you will discover that the database will process for over a week. Non-standard SPARQL operations can do this much more efficiently.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Comment
&lt;/h2&gt;

&lt;p&gt;This post was to introduce people to some of the more detailed elements of OWL's representation of Description Logic, explained &lt;em&gt;Valid&lt;/em&gt; models are ones in which all interpretations will be true, and how entailment can be made for &lt;em&gt;Consistent&lt;/em&gt; statements that lead to correct models for every possible interpretation.&lt;/p&gt;

&lt;p&gt;The examples at the end demonstrated how entailment can be limited in the open structures of RDFS, but is more capable for the closed structures described in OWL, always remembering that the model itself always follows the Open World Assumption.&lt;/p&gt;

&lt;p&gt;The SPARQL rule for &lt;code&gt;owl:intersectionOf&lt;/code&gt; was me being clever, even if it's useless in the real world due to the scalability issues. 😊 I've been doing this in the real world with code that is outside of SPARQL, but I ought to be able to do it with SPARQL extensions like &lt;code&gt;stardog:list:member&lt;/code&gt; (this could remove one level of loop in the above query, but I think it's possible to do even better).&lt;/p&gt;

&lt;p&gt;All of this is to provide background for my next blog post, which I ought to be able to start now that I've finished writing this!&lt;/p&gt;

</description>
      <category>rdf</category>
      <category>owl</category>
      <category>sparql</category>
      <category>rules</category>
    </item>
    <item>
      <title>Classification</title>
      <dc:creator>Paula Gearon</dc:creator>
      <pubDate>Wed, 28 Sep 2022 04:32:45 +0000</pubDate>
      <link>https://dev.to/quoll/classification-927</link>
      <guid>https://dev.to/quoll/classification-927</guid>
      <description>&lt;p&gt;My &lt;a href="https://dev.to/quoll/what-cant-i-do-as-a-rule-8a6"&gt;previous post&lt;/a&gt; showed how to use a reasoner like &lt;a href="https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.96.5433&amp;amp;rep=rep1&amp;amp;type=pdf"&gt;Pellet&lt;/a&gt; to make some interesting inferences about stated data. In that case, it demonstrated how a compound class could be determined with insufficient data to identify which of its components was satisfied.&lt;/p&gt;

&lt;p&gt;Interesting though it was, this was a contrived question made against data that was specifically designed for it, and required a complex reasoner that is limited in its ability to scale. Less contrived scenarios are more interesting, precisely because they can be applied to real-world data at scale.&lt;/p&gt;

&lt;p&gt;This leads to the question of what sorts of inferences are valid to make in OWL?&lt;/p&gt;

&lt;h2&gt;
  
  
  Specification
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://www.w3.org/TR/owl2-syntax/"&gt;OWL 2 specification&lt;/a&gt; describes the vocabulary and how this maps into &lt;a href="https://en.wikipedia.org/wiki/Description_logic"&gt;Description Logic&lt;/a&gt;. Most of it is rather obtuse due to the need to provide a precise mathematical definition.&lt;/p&gt;

&lt;p&gt;Fortunately, a number of the concepts are relatively straightforward to follow. Indeed, many of the concepts can be codified into rules to be applied mechanically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entailment
&lt;/h2&gt;

&lt;p&gt;The basic structure of most rules is a description of conditions that must be met by existing data, and new data that may be asserted. &lt;a href="https://en.wikipedia.org/wiki/Mathematical_logic"&gt;Mathematical logic&lt;/a&gt; describes this using the &lt;a href="https://en.wikipedia.org/wiki/Horn_clause"&gt;Horn Clause&lt;/a&gt;, and this has become the standard tool for logic programming systems as well.&lt;/p&gt;

&lt;p&gt;As an example, we can make a statement saying that all people are mortal, so if an individual is a person, they must be mortal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mortal(X) :- Person(X).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, I have described &lt;code&gt;Person&lt;/code&gt; and &lt;code&gt;Mortal&lt;/code&gt; as classes, and &lt;code&gt;X&lt;/code&gt; as an individual.&lt;/p&gt;

&lt;p&gt;To read a Horn clause, the outcome is described first, given the conditions that come after the &lt;code&gt;:-&lt;/code&gt; symbol. So the above says, "X is Mortal, if X is a Person".&lt;/p&gt;

&lt;p&gt;The outcome of the clause is referred to as the &lt;em&gt;Head&lt;/em&gt; of the clause, while the conditions are referred to as the &lt;em&gt;Body&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Multiple necessary conditions may be described in the body by separating them with commas. For instance, if a person has a child, then they are a parent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parent(X) :- Person(X), hasChild(X,Y).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the body now includes an entity &lt;code&gt;Y&lt;/code&gt; who is not referred to in the head.&lt;/p&gt;

&lt;p&gt;A more mathematical approach for this statement might be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;∀x x∊Person: ∃y (x,y)∊hasChild
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;i.e. For all &lt;code&gt;x&lt;/code&gt; where &lt;code&gt;x&lt;/code&gt; is a person, there exists a &lt;code&gt;y&lt;/code&gt; where relationship of &lt;code&gt;x,y&lt;/code&gt; is a member of the role-relationship &lt;code&gt;hasChild&lt;/code&gt;. Or, less strictly, for &lt;code&gt;x&lt;/code&gt; where &lt;code&gt;x&lt;/code&gt; is a person, there exists a &lt;code&gt;y&lt;/code&gt; where &lt;code&gt;x.hasChild.y&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To be honest, a lot of these notations are merely very precise and tedious way to express concepts that don't seem too difficult. But the precision allow mathematicians to eventually getting around to saying more interesting things, while proving that they got it right.&lt;/p&gt;

&lt;h2&gt;
  
  
  RDF and SPARQL
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Data
&lt;/h3&gt;

&lt;p&gt;The Resource Description Framework (RDF) and RDF Schema (RDFS) were designed to describe classes and data in a form that can be managed by a computer.&lt;/p&gt;

&lt;p&gt;To declare the above classes we can say that the they are each instances of the schema type called &lt;code&gt;Class&lt;/code&gt;, using &lt;a href="https://www.w3.org/TR/turtle/"&gt;Turtle&lt;/a&gt; syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="kd"&gt;@prefix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;&amp;lt;http://www.w3.org/2000/01/rdf-schema#&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kd"&gt;@prefix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;&amp;lt;http://quoll.gearon.org/data/demo.ttl#&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs:&lt;/span&gt;&lt;span class="n"&gt;Class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Mortal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs:&lt;/span&gt;&lt;span class="n"&gt;Class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs:&lt;/span&gt;&lt;span class="n"&gt;Class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The prefixes here will be used throughout this post. Strictly speaking, they should appear with each block of Turtle and each SPARQL query, but I will elide them for brevity.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can then use these classes to declare instances of data, say &lt;code&gt;:mary&lt;/code&gt; and &lt;code&gt;:jane&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;mary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;jane&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also declare the role &lt;code&gt;:hasChild&lt;/code&gt;, and connect Mary and Jane with it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;hasChild&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rfds:&lt;/span&gt;&lt;span class="n"&gt;Property&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;mary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;hasChild&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;jane&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a &lt;a href="https://medium.com/openlink-software-blog/semantic-web-layer-cake-tweak-explained-6ba5c6ac3fab"&gt;whole technology stack&lt;/a&gt; that can start working with this already, but for now, I'm going to stick to the Horn Clauses we've already discussed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Querying
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Mortality
&lt;/h4&gt;

&lt;p&gt;Let's consider the first clause:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mortal(X) :- Person(X).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means we are looking for all values of &lt;code&gt;X&lt;/code&gt; that have a type of &lt;code&gt;Person&lt;/code&gt;. Once we have those values for &lt;code&gt;X&lt;/code&gt;, we want to declare that each &lt;code&gt;X&lt;/code&gt; has a type of &lt;code&gt;Mortal&lt;/code&gt;. We can create a graph based on this query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;Mortal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would result in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;mary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Mortal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, we could assert all this back in with the original data by saying &lt;code&gt;insert&lt;/code&gt; rather than &lt;code&gt;construct&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;insert&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;Mortal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With either expression, the &lt;code&gt;where&lt;/code&gt; clause describes the conditions for the body of the Horn Clause, and the &lt;code&gt;insert&lt;/code&gt; or &lt;code&gt;construct&lt;/code&gt; describes the head of the clause.&lt;/p&gt;

&lt;h4&gt;
  
  
  Parenthood
&lt;/h4&gt;

&lt;p&gt;Similarly, we can look at the second clause again in order to convert it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parent(X) :- Person(X), hasChild(X,Y).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The two expressions in body will result in a pair of patterns in the &lt;code&gt;where&lt;/code&gt; clause of the query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;Parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;hasChild&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would result in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;mary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  RDFS Entailment
&lt;/h2&gt;

&lt;p&gt;The above rules are fine for a specific application, but they aren't generally useful. Instead, we'd like to be able to describe data with greater expressivity, and identify rules that can be applied more generally.&lt;/p&gt;

&lt;p&gt;In the early days of the Semantic Web, the &lt;a href="https://www.w3.org/"&gt;W3C&lt;/a&gt; had planned on releasing RDF as a data model, along with an expressive language to describe that data. There was a lot of progress with prior systems like &lt;a href="http://www.daml.org/"&gt;DAML&lt;/a&gt;, &lt;a href="https://tomhalljones.com/web/ontology-inference-layer-oil/"&gt;OIL&lt;/a&gt; and &lt;a href="https://www.w3.org/TR/daml+oil-reference/"&gt;DAML+OIL&lt;/a&gt;, but getting the semantics of these systems fully defined and correct is a very difficult task, leading to the creation of each of these systems, which all attempted to correct the issues of their predecessors. These efforts culminated in the &lt;a href="https://www.w3.org/OWL/"&gt;Web Ontology Language (OWL)&lt;/a&gt; which was formally released along with the first formal release of RDF in 2004.&lt;/p&gt;

&lt;p&gt;Prior to the formal releases of these standards, there was already a lot of RDF in use, which meant that there was a need to describe that data. While the complicated details of ontologies were being worked out, the working groups published a minimal vocabulary that could describe a taxonomy of classes and roles. This was first published as a draft for &lt;a href="https://www.w3.org/TR/rdf-schema/"&gt;RDF Schema&lt;/a&gt;, or RDFS.&lt;/p&gt;

&lt;p&gt;Alongside RDFS came a set of "semantics" (a word that means "meaning") which described what the vocabulary meant when it said things. A blog post isn't the place to get into what I mean when I say, "Class" or "Role" (also called a "property"), but I expect that if you're reading this then you may already have an idea. Instead, I'm going to look at a few other elements of RDFS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Subclass Descriptions
&lt;/h3&gt;

&lt;p&gt;The first concept I'm going to consider is the "subclass". If individuals can be classified into a class, then a subclass is a refinement on that classification, resulting in a smaller group.&lt;/p&gt;

&lt;p&gt;Considering the classes we had earlier, we can see that all instances of &lt;code&gt;:Person&lt;/code&gt; must be in the class &lt;code&gt;:Mortal&lt;/code&gt;, but there is nothing that says that all &lt;code&gt;:Mortal&lt;/code&gt;s must in the the class of &lt;code&gt;:Person&lt;/code&gt;. So &lt;code&gt;:Person&lt;/code&gt; is at most equal to &lt;code&gt;:Mortal&lt;/code&gt;, and most likely a smaller group. One way to write this mathematically is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Person ⊑ Mortal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is essentially the same notation as "subset" ⊆, and it means the same sort of thing, just in relation to classes.&lt;/p&gt;

&lt;p&gt;RDFS expresses the same thing with the &lt;code&gt;rdfs:subClassOf&lt;/code&gt; relationship:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs:&lt;/span&gt;&lt;span class="n"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Mortal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a similar way, all Parents are Persons, but not all people are parents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parent ⊑ Person
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs:&lt;/span&gt;&lt;span class="n"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Domain and Range Descriptions
&lt;/h3&gt;

&lt;p&gt;Whether we use the term "role", "property", "predicate" or "attribute", we are referring to some kind of relationship between things. Once we introduce relationships it starts being useful to declare what a type of things can be related to each other. For instance, &lt;code&gt;hasChild&lt;/code&gt; is an interesting relationship to have between people, but is not typically associated with something like an item of furniture.&lt;/p&gt;

&lt;p&gt;RDFS uses the term "domain" to describe the class of things that a property can be applied to. For instance, the &lt;code&gt;hasChild&lt;/code&gt; property can be applied to the class of &lt;code&gt;Parent&lt;/code&gt;. This is declared with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;hasChild&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs:&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the same way, the things that a property can refer to are referred to as the "range":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;hasChild&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs:&lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that only parents have children, but any person can be someone's child.&lt;/p&gt;

&lt;h3&gt;
  
  
  Entailment
&lt;/h3&gt;

&lt;p&gt;We now have enough to start looking at some of the entailments defined by RDFS.&lt;/p&gt;

&lt;p&gt;Given that RDF uses an &lt;a href="https://en.wikipedia.org/wiki/Open-world_assumption"&gt;Open World Assumption (OWA)&lt;/a&gt;, RDFS never considers applying a property to something whose type does not match to be an error. One reason for this is because the data model can always have new data added, and it is presumed that this data will be consistent with whatever exists.&lt;/p&gt;

&lt;p&gt;One effect of this is that we can sometimes derive what that new data must be. For instance, say we introduce a new person:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;jane&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;hasChild&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;kathy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Until now, &lt;code&gt;:jane&lt;/code&gt; has only been a &lt;code&gt;:Person&lt;/code&gt;, but because &lt;code&gt;:hasChild&lt;/code&gt; has a domain of &lt;code&gt;:Parent&lt;/code&gt; we now know that Jane is also a parent. Similarly, we haven't seen Kathy before, but the appearance in this statement tells use that she is a person.&lt;/p&gt;

&lt;p&gt;We can codify these with rules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parent(X) :- hasChild(X,Y).
Person(Y) :- hasChild(X,Y).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this is where having a vocabulary for describing the system becomes useful. Instead of describing rules for each property, we can base the rules on the vocabulary and create a more general form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C(X) :- rdfs:domain(P,C), P(X,Y).
D(Y) :- rdfs:range(P,D), P(X,Y).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Having variable predicates like this is often considered 2nd order logic, but in this case it's not really. It just looks like it is because of the syntax we use. Instead, I'll use the term that my supervisor called it: 1.5th order logic.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;To explain why this is not 2nd order logic, consider it this way: We may represent &lt;code&gt;(subject,predicate,object)&lt;/code&gt; as &lt;code&gt;predicate(subject,object)&lt;/code&gt; but a true Predicate-Logic representation would be with ternary predicates like: &lt;code&gt;statement(subject,predicate,object)&lt;/code&gt;. This is not as useful for our purposes, and is aesthetically less inviting, but nevertheless more correct.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Domain and Range Entailment
&lt;/h4&gt;

&lt;p&gt;The above rules can also be converted into SPARQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;domain&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The statements created from these queries are considered valid entailments from RDFS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;mary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;jane&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;jane&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;kathy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that some of the entailed statements already exist. This is fine, as graphs are considered to be a set of edges, so duplicates are ignored.&lt;/p&gt;

&lt;h4&gt;
  
  
  Subclass Entailment
&lt;/h4&gt;

&lt;p&gt;Subclass entailment can also be described using queries. In this case, there are two entailments to consider.&lt;/p&gt;

&lt;p&gt;We know that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;:Person&lt;/code&gt; is a subclass of &lt;code&gt;:Mortal&lt;/code&gt;, therefore  all instances of &lt;code&gt;:Person&lt;/code&gt; will be an instance of &lt;code&gt;:Mortal&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:Parent&lt;/code&gt; is a subclass of &lt;code&gt;:Person&lt;/code&gt;, therefore all instances of &lt;code&gt;:Parent&lt;/code&gt; will be an instance of &lt;code&gt;:Person&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Putting this together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instances of &lt;code&gt;:Parent&lt;/code&gt; must be instances of &lt;code&gt;:Person&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Instances of &lt;code&gt;:Person&lt;/code&gt; must be instances of &lt;code&gt;:Mortal&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Therefore: instances of &lt;code&gt;:Parent&lt;/code&gt; must be instances of &lt;code&gt;:Mortal&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The formal term for this is that &lt;code&gt;rdfs:subClassOf&lt;/code&gt; is a &lt;em&gt;transitive&lt;/em&gt; property. This is something that OWL describes explicitly, but I'll leave that for later. More succinctly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A ⊑ B ⊑ C  ⊢  A ⊑ C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or as a Horn Clause:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rdfs:subClassOf(A,C) :- rdfs:subClassOf(A,B), rdfs:subClassOf(B,C).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can be evaluated in SPARQL with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next part is considering the instances. We've already stated that if an entity is an instance of a class, then it will also be an instance of whatever that class is a subclass of (also called the &lt;em&gt;superclass&lt;/em&gt;, just like in software development):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With all of these rules in place, suddenly we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight turtle"&gt;&lt;code&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs:&lt;/span&gt;&lt;span class="n"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Mortal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;mary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;mary&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Mortal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;jane&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;jane&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Mortal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;kathy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;kathy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Parent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;kathy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;:&lt;/span&gt;&lt;span class="n"&gt;Mortal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Incidentally, both &lt;code&gt;rdfs:domain&lt;/code&gt; and &lt;code&gt;rdfs:range&lt;/code&gt; have a domain of &lt;code&gt;rdf:Property&lt;/code&gt; and a range of &lt;code&gt;rdfs:Class&lt;/code&gt;. So a full entailment regime means that we don't need to declare that &lt;code&gt;:hasChild&lt;/code&gt; is a property, and we don't need to explicitly declare that any of our classes a &lt;code&gt;rdfs:Class&lt;/code&gt;. I will sometimes include these declaration for the sake of clear documentation, but they're not needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  More Entailment
&lt;/h3&gt;

&lt;p&gt;The patterns of RDFS entailment are all described in the &lt;a href="https://www.w3.org/TR/rdf11-mt/"&gt;RDF Semantics specification&lt;/a&gt;, and collected in the &lt;a href="https://www.w3.org/TR/rdf11-mt/#rdfs-entailment"&gt;section 9.2&lt;/a&gt; of that document.&lt;/p&gt;

&lt;p&gt;The rules described above correspond to several of the RDFS Entailment patterns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="c1"&gt;# rdfs2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;domain&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# rdfs3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# rdfs11&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# rdfs9&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the patterns above, the process for converting all of the entailment patterns to executable rules takes very few steps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sparql"&gt;&lt;code&gt;&lt;span class="c1"&gt;# rdfs1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?aaa&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;Datatype&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?ddd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FILTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;isLiteral&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;?ddd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BIND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;datatype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;?ddd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?aaa&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# rdfs2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?aaa&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;domain&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?aaa&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?zzz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# rdfs3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?zzz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?aaa&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?aaa&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?zzz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# rdfs4a&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;Resource&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?aaa&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# rdfs4b&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;Resource&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?aaa&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FILTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="err"&gt;isLiteral&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# rdfs5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subPropertyOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?zzz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subPropertyOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subPropertyOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?zzz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# rdfs6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subPropertyOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdf&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;Property&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# rdfs7&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?bbb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?aaa&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subPropertyOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?bbb&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?aaa&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# rdfs8&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;Resource&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;Class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# rdfs9&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?zzz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?zzz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;#rdfs10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;Class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# rdfs11&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?zzz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?yyy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?zzz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# rdfs12&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subPropertyOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;member&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;ContainerMembershipProperty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# rdfs13&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;construct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;subClassOf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;Literal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;?xxx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;rdfs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="ss"&gt;Datatype&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executing them all together is a task for system that can coordinate the rules, and is typically tied to a &lt;a href="https://github.com/spinrdf/spinrdf"&gt;specific database implementation&lt;/a&gt; though this is not necessary (e.g. &lt;a href="https://github.com/quoll/naga"&gt;Naga&lt;/a&gt;, though I have yet to port this to SPARQL).&lt;/p&gt;

&lt;h2&gt;
  
  
  Was This Needed?
&lt;/h2&gt;

&lt;p&gt;Well… probably not. If you're reading this then maybe you already knew everything I had to say here. However, I also have more useful things to say, and I'm about to go on to say it. This further discussion will build on what I've discussed so far, and I wanted to establish a base of understanding before moving on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next
&lt;/h2&gt;

&lt;p&gt;I continue this discussion in &lt;a href="https://dev.to/quoll/classy-2hah"&gt;my next post...&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rdf</category>
      <category>owl</category>
      <category>sparql</category>
      <category>rules</category>
    </item>
    <item>
      <title>What Can't I do, as a Rule?</title>
      <dc:creator>Paula Gearon</dc:creator>
      <pubDate>Mon, 22 Aug 2022 20:21:00 +0000</pubDate>
      <link>https://dev.to/quoll/what-cant-i-do-as-a-rule-8a6</link>
      <guid>https://dev.to/quoll/what-cant-i-do-as-a-rule-8a6</guid>
      <description>&lt;p&gt;I have recently been working with graph databases again, and with &lt;a href="https://www.w3.org/TR/owl2-overview/"&gt;OWL&lt;/a&gt; descriptions of information. This isn't just about a graph of information, but also about how the information is structured. It's similar to a schema in an RDBMS, but with more information.&lt;/p&gt;

&lt;p&gt;Describing data in a graph and ontology uses a mathematical system called &lt;a href="https://en.wikipedia.org/wiki/Description_logic"&gt;Description Logic&lt;/a&gt; (DL). In fact, it was a community of Description Logic researchers who came together to develop the OWL standard. The result is a system that can be obtuse to learn, but has a solid mathematical foundation without "bugs".&lt;/p&gt;

&lt;p&gt;It also has the ability to do some unexpected things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Oedipal Issues
&lt;/h2&gt;

&lt;p&gt;There is an example provided in the &lt;a href="https://www.cambridge.org/core/books/description-logic-handbook/F050683766E57EE9BB07BC01BB7A7069"&gt;Description Logic Handbook&lt;/a&gt;, referred to therein as the "Oedipus Problem". (See page 73 of this &lt;a href="https://www.csee.umbc.edu/courses/graduate/691/fall19/07/papers/DescriptionLogicHandbook.pdf"&gt;PDF of the 1st edition&lt;/a&gt;) A set of relationships around the mythical figure of Oedipus is described using DL, and then a complex question is asked that appears unanswerable at face value.&lt;/p&gt;

&lt;p&gt;To start with, let's look at the DL data that is presented:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hasChild(IOKASTE, OEDIPUS)
hasChild(IOKASTE, POLYNEIKES)
hasChild(OEDIPUS, POLYNEIKES)
hasChild(POLYNEIKES, THERSANDROS)
Patricide(OEDIPUS)
¬Patricide(THERSANDROS)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This describes a rather messy family tree.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f2Z2qFbJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aig3n5n1kd801q71nhna.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f2Z2qFbJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aig3n5n1kd801q71nhna.png" alt="Diagram of the above individuals and relationships. The Patricide and notPatricide classes are presented as colors" width="366" height="422"&gt;&lt;/a&gt;&lt;br&gt;
Oedipus is colored a light red to indicate that he killed his father (ie. he is a "Patricide"), while Thersandros is light blue to indicate that he did not kill his father (he is &lt;strong&gt;not&lt;/strong&gt; a Patricide).&lt;/p&gt;

&lt;p&gt;Each statement in the DL is presented as a "predicate". This is some kind of name followed by parentheses. The first one here is &lt;code&gt;hasChild&lt;/code&gt;. Because it has 2 elements inside the parentheses, then it represents something called a &lt;em&gt;role&lt;/em&gt;. The first line says that &lt;code&gt;IOKASTE&lt;/code&gt; is connected by the role of &lt;code&gt;hasChild&lt;/code&gt; to &lt;code&gt;OEDIPUS&lt;/code&gt;, and you can see that I've indicated this in the diagram. By convention, roles will always start with a lower-case letter.&lt;/p&gt;

&lt;p&gt;The last two lines have only a single element in the parentheses. These declare the &lt;em&gt;class&lt;/em&gt; of something. The first one says that &lt;code&gt;OEDIPUS&lt;/code&gt; is in the class of &lt;code&gt;Patricide&lt;/code&gt;. This is just using DL syntax to describe that he killed his father. The second uses an operator that inverts the class, saying that &lt;code&gt;THERSANDROS&lt;/code&gt; is in the class of anyone and anything that is &lt;strong&gt;not&lt;/strong&gt; a &lt;code&gt;Patricide&lt;/code&gt;. Again, this is using DL to explicitly state that Thersandros did not kill his father.&lt;/p&gt;
&lt;h2&gt;
  
  
  A Box
&lt;/h2&gt;

&lt;p&gt;The data presented so far is what is referred to as &lt;em&gt;instance data&lt;/em&gt;. The formal term for this is the &lt;em&gt;ABox&lt;/em&gt;, which stands for "Assertion Box". This is like the data that might be found inside a table in an RDBMS.&lt;/p&gt;

&lt;p&gt;This &lt;em&gt;ABox&lt;/em&gt; contains 4 statements of &lt;code&gt;hasChild&lt;/code&gt;, and 2 type statements: membership in the &lt;code&gt;Patricide&lt;/code&gt; class, and membership of the class that indicates &lt;em&gt;not-a-Patricide&lt;/em&gt;, which is indicated as the class of things that is &lt;strong&gt;everything&lt;/strong&gt; that is not a &lt;code&gt;Patricide&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  T Box
&lt;/h2&gt;

&lt;p&gt;What does not appear here is the &lt;em&gt;ontology&lt;/em&gt; of the data, which is formally known as the &lt;em&gt;TBox&lt;/em&gt; or "Terminology Box". This is similar to a database &lt;em&gt;schema&lt;/em&gt; but also goes on to describe relationships between entities, relationships between relationships, properties of relationships, and more.&lt;/p&gt;

&lt;p&gt;While the &lt;em&gt;TBox&lt;/em&gt; has not been included, we can infer a little from the &lt;em&gt;ABox&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can see that there is a relationship called &lt;code&gt;hasChild&lt;/code&gt; that connects elements in the domain.&lt;/li&gt;
&lt;li&gt;We can see that these elements can be on either side of those relationships.&lt;/li&gt;
&lt;li&gt;There is a class called &lt;code&gt;Patricide&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Elements may be a member of &lt;code&gt;Patricide&lt;/code&gt; or not. This indicates that those elements that are members of &lt;code&gt;Patricide&lt;/code&gt; form a subset of the full domain of elements. We see this because &lt;code&gt;THERSANDROS&lt;/code&gt; is an element, but is not a &lt;code&gt;Patricide&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Open World
&lt;/h3&gt;

&lt;p&gt;Consider how Thersandros is being explicitly declared as &lt;em&gt;&lt;strong&gt;not&lt;/strong&gt;&lt;/em&gt; being a member of the &lt;code&gt;Patricide&lt;/code&gt; class. This is a result of the &lt;em&gt;Open World Assumption&lt;/em&gt; (OWA), and may seem unusual when compared to the more common &lt;em&gt;Closed World Assumption&lt;/em&gt; (CWA).&lt;/p&gt;

&lt;p&gt;In the CWA, any data that is not explicitly stated is known to be false. For instance, both Iokaste and Polyneikes are not declared to be in the class of &lt;code&gt;Patricide&lt;/code&gt;, and in the CWA this implies that they are &lt;em&gt;&lt;strong&gt;not&lt;/strong&gt;&lt;/em&gt; members of this class. The statement about Thersandros not being a &lt;code&gt;Patricide&lt;/code&gt; would therefore be redundant. Most programming systems and databases work on this assumption, so developers are usually familiar with this paradigm.&lt;/p&gt;

&lt;p&gt;In contrast, under the Open World Assumption any data that is not stated is instead &lt;em&gt;unknown&lt;/em&gt;. At some point in the future, more information may be explicitly provided, or a reasoning process may determine new information. But until then, it is not valid to make any decisions based on unstated data.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;¬Patricide(THERSANDROS)&lt;/code&gt; statement has been made under the OWA, so that we explicitly know that Thersandros is not in the &lt;code&gt;Patricide&lt;/code&gt; class. We also know that Oedipus is a member of that class. But we have no information about whether Iokaste and Polyneikes are members.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Question
&lt;/h2&gt;

&lt;p&gt;The question that is posed is this:&lt;br&gt;
Does &lt;code&gt;IOKASTE&lt;/code&gt; have a child who is a &lt;code&gt;Patricide&lt;/code&gt;, who, in turn, has a child who is not a &lt;code&gt;Patricide&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;This question can be posed in Description Logic with the expression:&lt;br&gt;
&lt;code&gt;(∃hasChild.(Patricide ⊓ ∃hasChild.¬Patricide))(IOKASTE) ?&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For those who don't know the terminology, let's break it down, by using some substitution.&lt;/p&gt;

&lt;p&gt;The expression:&lt;br&gt;
&lt;code&gt;Aoe(IOKASTE) ?&lt;/code&gt;&lt;br&gt;
is asking if &lt;code&gt;IOKASTE&lt;/code&gt; is a member of the class &lt;code&gt;Aoe&lt;/code&gt;. We can then define &lt;code&gt;Aoe&lt;/code&gt; as the class in our question:&lt;br&gt;
&lt;code&gt;Aoe ≡ ∃hasChild.(Patricide ⊓ ∃hasChild.¬Patricide)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;(The ≡ symbol means "is equivalent to")&lt;/p&gt;

&lt;p&gt;So now we need to break down the &lt;code&gt;Aoe&lt;/code&gt; class. Let's substitute for the compound statement:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Aoe ≡ ∃hasChild.B&lt;/code&gt;&lt;br&gt;
&lt;code&gt;B ≡ Patricide ⊓ ∃hasChild.¬Patricide&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This redefines &lt;code&gt;Aoe&lt;/code&gt; in terms of &lt;code&gt;B&lt;/code&gt;. This definition says that to be a member of &lt;code&gt;Aoe&lt;/code&gt; an entity must have a &lt;code&gt;hasChild&lt;/code&gt; relationship to an entity that is of type &lt;code&gt;B&lt;/code&gt;. Breaking down &lt;code&gt;B&lt;/code&gt;, we come to:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;B ≡ Patricide ⊓ C&lt;/code&gt;&lt;br&gt;
&lt;code&gt;C ≡ ∃hasChild.¬Patricide&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So to be a member of the &lt;code&gt;B&lt;/code&gt; class, an entity must be both an instance of the &lt;code&gt;Patricide&lt;/code&gt; class, and also the &lt;code&gt;C&lt;/code&gt; class.  The &lt;code&gt;C&lt;/code&gt; class is actually compound, but small enough that I did not break it up further. This class defines an entity that has a child that is &lt;strong&gt;not&lt;/strong&gt; a member of the &lt;code&gt;Patricide&lt;/code&gt; class.&lt;/p&gt;
&lt;h2&gt;
  
  
  Solving for Aoe
&lt;/h2&gt;

&lt;p&gt;To see if &lt;code&gt;IOKASTE&lt;/code&gt; is a member of &lt;code&gt;Aoe&lt;/code&gt; we can look to see if there is a &lt;code&gt;hasChild&lt;/code&gt; relationship, and if one of those children is a member of the &lt;code&gt;B&lt;/code&gt; class defined above.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IOKASTE&lt;/code&gt; has 2 children: &lt;code&gt;OEDIPUS&lt;/code&gt; and &lt;code&gt;POLYNEIKES&lt;/code&gt;. Let's consider each in turn.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Oedipus Child
&lt;/h3&gt;

&lt;p&gt;For &lt;code&gt;OEDIPUS&lt;/code&gt; to be a member of &lt;code&gt;B&lt;/code&gt;, he needs to be a &lt;code&gt;Patricide&lt;/code&gt; and to be a member of &lt;code&gt;C&lt;/code&gt;. &lt;code&gt;OEDIPUS&lt;/code&gt; is declared as a &lt;code&gt;Patricide&lt;/code&gt;, so now we consider he is a member of the &lt;code&gt;C&lt;/code&gt; class. This requires a &lt;code&gt;hasChild&lt;/code&gt; relationship to someone who is not in the &lt;code&gt;Patricide&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;In this case, there is a &lt;code&gt;hasChild&lt;/code&gt; relationship to &lt;code&gt;POLYNEIKES&lt;/code&gt;, but there is no information to indicate if &lt;code&gt;POLYNEIKES&lt;/code&gt; is a &lt;code&gt;Patricide&lt;/code&gt; or not. This means that we cannot determine if the conditions are met.&lt;/p&gt;

&lt;p&gt;Note that we have not determined that &lt;code&gt;IOKASTE&lt;/code&gt; is not a member of &lt;code&gt;Aoe&lt;/code&gt;. We just do not have sufficient information. &lt;code&gt;POLYNEIKES&lt;/code&gt; is either a member of &lt;code&gt;Patricide&lt;/code&gt; or she is not, and this will determine whether &lt;code&gt;IOKASTE&lt;/code&gt; is a member of &lt;code&gt;Aoe&lt;/code&gt;. If &lt;code&gt;POLYNEIKES&lt;/code&gt; is not a member of &lt;code&gt;Patricide&lt;/code&gt;, then the condition of &lt;code&gt;Aoe(IOKASTE)&lt;/code&gt; will be met.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Polyneikes Child
&lt;/h3&gt;

&lt;p&gt;For &lt;code&gt;POLYNEIKES&lt;/code&gt; to be a member of &lt;code&gt;B&lt;/code&gt;, she needs to be a &lt;code&gt;Patricide&lt;/code&gt; and to be a member of &lt;code&gt;C&lt;/code&gt;. We don't know if she is a member of the &lt;code&gt;Patricide&lt;/code&gt; class or not, but let's consider the &lt;code&gt;C&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;To be in the &lt;code&gt;C&lt;/code&gt; class, &lt;code&gt;POLYNEIKES&lt;/code&gt; requires a &lt;code&gt;hasChild&lt;/code&gt; relationship to someone who is not in the &lt;code&gt;Patricide&lt;/code&gt; class. In this case, there is a &lt;code&gt;hasChild&lt;/code&gt; relationship to &lt;code&gt;THERSANDROS&lt;/code&gt; who is explicitly declared to be not in the &lt;code&gt;Patricide&lt;/code&gt; class. So &lt;code&gt;POLYNEIKES&lt;/code&gt; is indeed in the &lt;code&gt;C&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;In this case, we also don't know if &lt;code&gt;IOKASTE&lt;/code&gt; is a member of &lt;code&gt;Aoe&lt;/code&gt;. Again, this is solely dependent on whether or not &lt;code&gt;POLYNEIKES&lt;/code&gt; is a member of &lt;code&gt;Patricide&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;At face value, it appears that there is no way to answer the question of &lt;code&gt;Aoe(IOKASTE)&lt;/code&gt;, since all possible paths have an unknown element.&lt;/p&gt;

&lt;p&gt;However, for the path through &lt;code&gt;OEDIPUS&lt;/code&gt;, we know that &lt;code&gt;Aoe(IOKASTE)&lt;/code&gt; is true if and only if &lt;code&gt;¬Patricide(POLYNEIKES)&lt;/code&gt;. Meanwhile, for the path through &lt;code&gt;POLYNEIKES&lt;/code&gt;, we know that &lt;code&gt;Aoe(IOKASTE)&lt;/code&gt; is true if and only if &lt;code&gt;Patricide(POLYNEIKES)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Patricide(POLYNEIKES)&lt;/code&gt; may only be true or false, meaning that Polyneikes is a member of the class or she isn't. There aren't any other possibilities. And since both possibilities result in &lt;code&gt;Aoe(IOKASTE)&lt;/code&gt; being true, then this tells us that the condition is met.&lt;/p&gt;

&lt;p&gt;The unusual thing here is that we don't know &lt;em&gt;&lt;strong&gt;how&lt;/strong&gt;&lt;/em&gt; the condition is met. We don't have complete information, but we do have enough information to show that the condition is true regardless of the unknown state.&lt;/p&gt;
&lt;h2&gt;
  
  
  Without Rules
&lt;/h2&gt;

&lt;p&gt;A forward-chaining reasoner is one that relies on &lt;a href="https://en.wikipedia.org/wiki/Modus_ponens"&gt;&lt;em&gt;modus ponens&lt;/em&gt;&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Modus_tollens"&gt;&lt;em&gt;modus tollens&lt;/em&gt;&lt;/a&gt;. These are both mechanisms that take known information, and deduce new information. However, for the problem of determining &lt;code&gt;Aoe(IOKASTE)&lt;/code&gt;, the solution is arrived at through &lt;em&gt;unknown&lt;/em&gt; state, meaning that forward-chained reasoners are unable to deduce the result.&lt;/p&gt;

&lt;p&gt;Theoretically, in a limited case like this, it is possible to create rules for the solution. For instance, a predicate might be created that indicates "true, if X is true", or "true, if X is false", and then create a rule that returns true if both of these are asserted. However, this is limited to simple conditions on single variables. The constructs would quickly get unwieldy as the number of variables increased, and the possible states would explode combinatorially with many of these conditional predicates being asserted.&lt;/p&gt;

&lt;p&gt;Rather than rules that create conditional assertions, logic engines like Prolog can explore these possibilities in memory. This can and does work, but this approach may also have difficulty in scaling as the number of states increases, and the logic engine has to search them all.&lt;/p&gt;

&lt;p&gt;What I have discussed so far are &lt;a href="https://en.wikipedia.org/wiki/Proof_procedure"&gt;proof procedures&lt;/a&gt; based on &lt;a href="https://en.wikipedia.org/wiki/Natural_deduction"&gt;Natural Deduction&lt;/a&gt; and trees. Another approach is using a &lt;a href="https://en.wikipedia.org/wiki/Method_of_analytic_tableaux"&gt;Semantic Tableaux&lt;/a&gt;. This considers the entire TBox as a series of logic expressions, along with the inverse of a statement that is being evaluated. The process then manipulates the logic expressions until the statement can be "proven". If it is shown to be &lt;code&gt;false&lt;/code&gt; then the inverse was true, so the statement to be evaluated is &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's get this back into concrete implementations.&lt;/p&gt;
&lt;h2&gt;
  
  
  RDF
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://www.w3.org/TR/rdf11-primer/"&gt;Resource Description Framework (RDF)&lt;/a&gt; is a graph data model, where each edge may also be considered to be a logic assertion of a binary predicate applied to each of the connected nodes.&lt;/p&gt;

&lt;p&gt;For instance, a graph containing 2 nodes of &lt;em&gt;A&lt;/em&gt; and &lt;em&gt;B&lt;/em&gt; with a edge of &lt;em&gt;E&lt;/em&gt; between them would appear as:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ayd9GH5s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6zai78lsc7qygta1sr1s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ayd9GH5s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6zai78lsc7qygta1sr1s.png" alt="An RDF Graph Edge" width="244" height="76"&gt;&lt;/a&gt;&lt;br&gt;
The logic representation of this is where the edge is considered a binary predicate:&lt;br&gt;
&lt;code&gt;E(A, B)&lt;/code&gt;&lt;br&gt;
Unary predicates in description logic are a statement of an entity's type, and so RDF has created a specific predicate called &lt;code&gt;rdf:type&lt;/code&gt; to represent this. For instance, saying that Oedipus is a &lt;code&gt;Patricide&lt;/code&gt; has the logic representation of:&lt;br&gt;
&lt;code&gt;Patricide(OEDIPUS)&lt;/code&gt;&lt;br&gt;
And appears in the RDF graph as:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Oqe2M6wZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m1c5hvv33trd3is9qcz8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Oqe2M6wZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m1c5hvv33trd3is9qcz8.png" alt="Image description" width="360" height="68"&gt;&lt;/a&gt;&lt;br&gt;
This covers most of the ABox that was declared for the Iokaste problem, with the exception of Thersandros being declared as &lt;em&gt;&lt;strong&gt;not&lt;/strong&gt;&lt;/em&gt; being a member of &lt;code&gt;Patricide&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  OWL
&lt;/h2&gt;

&lt;p&gt;While RDF is adequate for the ABox data, it is the TBox with its complex class descriptions that describes the question we are trying to answer. The &lt;a href="https://www.w3.org/TR/owl2-primer/"&gt;Web Ontology Language (OWL)&lt;/a&gt; is a language that includes these descriptions, and is specifically designed to work with RDF data. OWL itself can be &lt;a href="https://www.w3.org/TR/owl2-quick-reference/"&gt;serialized into RDF&lt;/a&gt; and stored in a graph alongside the data it is describing.&lt;/p&gt;
&lt;h2&gt;
  
  
  Serializing in TTL
&lt;/h2&gt;

&lt;p&gt;Using RDF and OWL, the complete ABox as well as the &lt;code&gt;¬Patricide&lt;/code&gt; class can be described in RDF, and serialized into a text format. I prefer to use the &lt;a href="https://www.w3.org/TR/turtle/"&gt;Terse Triples Language (Turtle)&lt;/a&gt; to serialize RDF, though several other formats exist.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@prefix : &amp;lt;http://demo.imo.com/oedipus#&amp;gt; .
@prefix owl: &amp;lt;http://www.w3.org/2002/07/owl#&amp;gt; .

:NotPatricide owl:complementOf :Patricide .

:_Iokaste :hasChild :_Oedipus ,
                    :_Polyneikes .
:_Oedipus :hasChild :_Polyneikes ;
          a :Patricide .
:_Polyneikes :hasChild :_Thersandros .
:_Thersandros a :NotPatricide .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks like the following:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IuKPCYGj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yz1cz971hc8hb19pc49j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IuKPCYGj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yz1cz971hc8hb19pc49j.png" alt="RDF Data for ABox" width="691" height="431"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Back to the Question
&lt;/h2&gt;

&lt;p&gt;With this data in place, I ask about the &lt;code&gt;Aoe&lt;/code&gt; class defined above if I add that class to my graph:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:Aoe owl:equivalentClass [
  a owl:Restriction ;
  owl:onProperty :hasChild ;
  owl:someValuesFrom [
    owl:intersectionOf (:Patricide
                         [a owl:Restriction ;
                          owl:someValuesFrom :NotPatricide ;
                          owl:onProperty :hasChild])]] .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a transliteration of the expression:&lt;br&gt;
&lt;code&gt;∃hasChild.(Patricide ⊓ ∃hasChild.¬Patricide)&lt;/code&gt;&lt;br&gt;
into OWL, and was done using the serialization rules shown in the &lt;a href="https://www.w3.org/TR/owl2-quick-reference/"&gt;OWL2 Quick Reference Guide&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Reasoning
&lt;/h2&gt;

&lt;p&gt;We can ask if Iokaste is a member of the &lt;code&gt;Aoe&lt;/code&gt; class by using a SPARQL ASK query, with reasoning turned on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@prefix : &amp;lt;http://demo.imo.com/oedipus#&amp;gt; .
ASK { :_Iokaste a :Aoe }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we load this into an RDF database and issue the query we will get a result of: &lt;code&gt;false&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;What? This took so long to get here! What went wrong?&lt;/p&gt;

&lt;p&gt;The answer is that we need to enable reasoning. Not every database can handle this, and even fewer can deal with reasoning around incomplete data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stardog
&lt;/h2&gt;

&lt;p&gt;To see a database that can manage this, let's look at &lt;a href="https://www.stardog.com/platform/"&gt;Stardog&lt;/a&gt;. This is a commercial database, but it can be used for free on smaller datasets. Installation is &lt;a href="https://docs.stardog.com/get-started/install-stardog/"&gt;well documented&lt;/a&gt;, and then the &lt;a href="http://stardog.studio/#/"&gt;web-based UI&lt;/a&gt; is very capable, with lots of useful features (that can take a while to explore). Connecting to &lt;a href="http://stardog.studio/#/"&gt;this UI link&lt;/a&gt; requests the address of your DB, connects into it, and gives you an easier interface than a command line.&lt;/p&gt;

&lt;p&gt;Try putting the above ABox and definition of &lt;code&gt;:Aoe&lt;/code&gt; into a file called &lt;code&gt;oedipus.ttl&lt;/code&gt;, then it can be loaded into a new database that we will also call "oedipus":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;stardog-admin db create &lt;span class="nt"&gt;-n&lt;/span&gt; oedipus oedipus.ttl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should have an output like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bulk loading data to new database oedipus.
Loaded 19 triples to oedipus from 1 file(s) in 00:00:00.337 @ 0.1K triples/sec.
Successfully created database 'oedipus'.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now try looking at the data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;stardog query execute oedipus &lt;span class="s1"&gt;'select ?s ?p ?o {?s ?p ?o}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+----------------------------------------------------+---------------------+----------------------------------------------------+
|                         s                          |          p          |                         o                          |
+----------------------------------------------------+---------------------+----------------------------------------------------+
| _:bnode_5f51466d_e100_4b91_b2ea_cf0a9bbc5477_61818 | owl:someValuesFrom  | :NotPatricide                                      |
| :_Thersandros                                      | rdf:type            | :NotPatricide                                      |
| :NotPatricide                                      | owl:complementOf    | :Patricide                                         |
| _:bnode_5f51466d_e100_4b91_b2ea_cf0a9bbc5477_61816 | rdf:first           | :Patricide                                         |
| :_Oedipus                                          | rdf:type            | :Patricide                                         |
| :Aoe                                               | owl:equivalentClass | _:bnode_5f51466d_e100_4b91_b2ea_cf0a9bbc5477_61814 |
| _:bnode_5f51466d_e100_4b91_b2ea_cf0a9bbc5477_61814 | rdf:type            | owl:Restriction                                    |
| _:bnode_5f51466d_e100_4b91_b2ea_cf0a9bbc5477_61818 | rdf:type            | owl:Restriction                                    |
| _:bnode_5f51466d_e100_4b91_b2ea_cf0a9bbc5477_61814 | owl:onProperty      | :hasChild                                          |
| _:bnode_5f51466d_e100_4b91_b2ea_cf0a9bbc5477_61818 | owl:onProperty      | :hasChild                                          |
| _:bnode_5f51466d_e100_4b91_b2ea_cf0a9bbc5477_61815 | owl:intersectionOf  | _:bnode_5f51466d_e100_4b91_b2ea_cf0a9bbc5477_61816 |
| _:bnode_5f51466d_e100_4b91_b2ea_cf0a9bbc5477_61816 | rdf:rest            | _:bnode_5f51466d_e100_4b91_b2ea_cf0a9bbc5477_61817 |
| _:bnode_5f51466d_e100_4b91_b2ea_cf0a9bbc5477_61817 | rdf:first           | _:bnode_5f51466d_e100_4b91_b2ea_cf0a9bbc5477_61818 |
| _:bnode_5f51466d_e100_4b91_b2ea_cf0a9bbc5477_61817 | rdf:rest            | rdf:nil                                            |
| _:bnode_5f51466d_e100_4b91_b2ea_cf0a9bbc5477_61814 | owl:someValuesFrom  | _:bnode_5f51466d_e100_4b91_b2ea_cf0a9bbc5477_61815 |
| :_Iokaste                                          | :hasChild           | :_Oedipus                                          |
| :_Iokaste                                          | :hasChild           | :_Polyneikes                                       |
| :_Oedipus                                          | :hasChild           | :_Polyneikes                                       |
| :_Polyneikes                                       | :hasChild           | :_Thersandros                                      |
+----------------------------------------------------+---------------------+----------------------------------------------------+
Query returned 19 results in 00:00:00.257
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we trace through all of these statements, we can see the blank nodes that were created in the construction of the &lt;code&gt;:Aoe&lt;/code&gt; class, along with the intersection list and the restrictions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enable Reasoning
&lt;/h3&gt;

&lt;p&gt;When reasoning is enabled, the TBox is used to describe the data, and direct the reasoning. Consequently, none of the TBox information should appear in the output. We see how this looks on the oedipus data by adding a &lt;code&gt;-r&lt;/code&gt; flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;stardog query execute &lt;span class="nt"&gt;-r&lt;/span&gt; oedipus &lt;span class="s2"&gt;"select ?s ?p ?o {?s ?p ?o}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+---------------+-----------+---------------+
|       s       |     p     |       o       |
+---------------+-----------+---------------+
| :_Iokaste     | :hasChild | :_Oedipus     |
| :_Iokaste     | :hasChild | :_Polyneikes  |
| :_Oedipus     | :hasChild | :_Polyneikes  |
| :_Polyneikes  | :hasChild | :_Thersandros |
| :_Oedipus     | rdf:type  | :Patricide    |
| :_Thersandros | rdf:type  | :NotPatricide |
| :_Iokaste     | rdf:type  | owl:Thing     |
| :_Oedipus     | rdf:type  | owl:Thing     |
| :_Polyneikes  | rdf:type  | owl:Thing     |
| :_Thersandros | rdf:type  | owl:Thing     |
+---------------+-----------+---------------+

Query returned 10 results in 00:00:01.313
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is easier to follow, but the only new data is that all the instance data now has the type &lt;code&gt;owl:Thing&lt;/code&gt;. That's correct, but not particularly interesting. And it doesn't infer any members for &lt;code&gt;:Aoe&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Stardog can use &lt;a href="https://docs.stardog.com/inference-engine/#reasoning-types"&gt;different reasoning levels&lt;/a&gt;, and by default it uses a combination of &lt;a href="https://www.w3.org/TR/rdf-schema/"&gt;RDFS&lt;/a&gt;, &lt;a href="https://www.w3.org/TR/owl2-profiles/#OWL_2_QL"&gt;OWL QL&lt;/a&gt;, &lt;a href="https://www.w3.org/TR/owl2-profiles/#OWL_2_RL"&gt;OWL RL&lt;/a&gt;, and &lt;a href="https://www.w3.org/TR/owl2-profiles/#OWL_2_EL"&gt;OWL EL&lt;/a&gt;. This is very powerful, but it still doesn't handle the incomplete information from the Oedipus example. However, Stardog also supports the &lt;a href="https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.96.5433&amp;amp;rep=rep1&amp;amp;type=pdf"&gt;Pellet&lt;/a&gt; reasoner. This reasoner is fast and capable, though it can be limited in the scale that it can manage. Fortunately, our data set is tiny so that won't be a problem.&lt;/p&gt;

&lt;p&gt;To switch to the Pellet reasoner, the database has to be taken down and then back up with the new reasoner setting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;stardog-admin db offline oedipus
The database oedipus is now offline.
&lt;span class="nv"&gt;$ &lt;/span&gt;stardog-admin metadata &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; reasoning.type&lt;span class="o"&gt;=&lt;/span&gt;DL &lt;span class="nt"&gt;--&lt;/span&gt; oedipus
The option&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;the database &lt;span class="s1"&gt;'oedipus'&lt;/span&gt; were successfully set.
&lt;span class="nv"&gt;$ &lt;/span&gt;stardog-admin db online oedipus
The database oedipus is now online.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can look at the data again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;stardog query execute &lt;span class="nt"&gt;-r&lt;/span&gt; oedipus &lt;span class="s2"&gt;"select ?s ?p ?o {?s ?p ?o}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+---------------+-----------+---------------+
|       s       |     p     |       o       |
+---------------+-----------+---------------+
| :_Oedipus     | :hasChild | :_Polyneikes  |
| :_Iokaste     | :hasChild | :_Oedipus     |
| :_Iokaste     | :hasChild | :_Polyneikes  |
| :_Polyneikes  | :hasChild | :_Thersandros |
| :_Oedipus     | rdf:type  | :Patricide    |
| :_Iokaste     | rdf:type  | :Aoe          |
| :_Oedipus     | rdf:type  | owl:Thing     |
| :_Thersandros | rdf:type  | owl:Thing     |
| :_Iokaste     | rdf:type  | owl:Thing     |
| :_Polyneikes  | rdf:type  | owl:Thing     |
| :_Thersandros | rdf:type  | :NotPatricide |
+---------------+-----------+---------------+

Query returned 11 results in 00:00:00.303
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This includes a single new statement, saying &lt;code&gt;:Aoe(:_Iokaste)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we can ask the original question:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;stardog query execute &lt;span class="nt"&gt;-r&lt;/span&gt; oedipus &lt;span class="s2"&gt;"ASK {:_Iokaste a :Aoe}"&lt;/span&gt;
Result: &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;This post explored description logics, and how they can be used to reason on incomplete data. It also demonstrated how the Web Ontology Language is used to encode Description Logic, and how this, in turn, can be represented as RDF. Finally, we used Pellet as an OWL reasoner to answer the original question.&lt;/p&gt;

&lt;p&gt;Afterword: The above link for Pellet is to a paper in the &lt;a href="http://www.elsevier.com/locate/websem"&gt;Journal of Web Semantics&lt;/a&gt;. The system itself is open source and &lt;a href="https://github.com/stardog-union/pellet"&gt;can be found on Github&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next
&lt;/h2&gt;

&lt;p&gt;I discuss more of modeling data in RDF/OWL in &lt;a href="https://dev.to/quoll/classification-927"&gt;my next post...&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rdf</category>
      <category>owl</category>
      <category>sparql</category>
      <category>rules</category>
    </item>
    <item>
      <title>How fast is dc?</title>
      <dc:creator>Paula Gearon</dc:creator>
      <pubDate>Tue, 12 Jul 2022 20:02:41 +0000</pubDate>
      <link>https://dev.to/quoll/how-fast-is-dc-1pak</link>
      <guid>https://dev.to/quoll/how-fast-is-dc-1pak</guid>
      <description>&lt;p&gt;I was reading &lt;a href="https://tech.toryanderson.com/2022/07/11/fast-fibonacci-in-clojure/"&gt;Tory Anderson's blog post&lt;/a&gt; on writing a fast Fibonacci calculator in Clojure. He uses a logarithmic algorithm to find the &lt;code&gt;nth&lt;/code&gt; Fibonacci number, which was interesting, and &lt;a href="https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-11.html#%_thm_1.19"&gt;something from SICP&lt;/a&gt; that I'd forgotten about.&lt;/p&gt;

&lt;p&gt;Tory's code took about 56 minutes, though on my local machine here it was more like 10 minutes. That made me curious to think about what slows it down.&lt;/p&gt;

&lt;p&gt;Tory went on to consider some optimizations, and looked at using &lt;code&gt;memoize&lt;/code&gt; to cache function results. This is a simple improvement when using a naïve implementation, as per the &lt;a href="https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.2"&gt;tree recursion section in SICP&lt;/a&gt;, since it avoids recalculating the same values multiple times. However, the logarithmic algorithm only calculates each value once. We can see this if we add &lt;code&gt;(println n)&lt;/code&gt; to the top of Tory's &lt;code&gt;fib*&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=&amp;gt; (fib 100)
100
50
25
12
6
3
1
0
354224848179261915075
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This only executed the &lt;code&gt;fib*&lt;/code&gt; function 8 times, with different arguments each time. Consequently, caching results won't change the performance at all.&lt;/p&gt;

&lt;p&gt;Similarly, executing &lt;code&gt;(fib 1000000000)&lt;/code&gt; will only execute &lt;code&gt;fib*&lt;/code&gt; 31 times, which tells us that the recursive calls to &lt;code&gt;fib*&lt;/code&gt; are not what takes time. Looking inside the function, we can see that all of the other operations are math, with no loops at all:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fib*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;quot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;*&lt;/span&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;*&lt;/span&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;*&lt;/span&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;*&lt;/span&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;even?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)]))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is all just division (via &lt;code&gt;quot&lt;/code&gt;), multiplication, subtraction, and addition. These are typically fast operations, so why is it slow?&lt;/p&gt;

&lt;p&gt;The answer is based in the size of the numbers being calculated. As we saw above, the 100th Fibonacci number is 21 digits long. This grows rapidly, and by the billionth number the size is hundreds of millions of digits long! 208,987,640 digits, in fact. This can't be calculated by standard number types, and needs a type like &lt;a href="https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/math/BigInteger.html"&gt;Java's &lt;code&gt;BigInteger&lt;/code&gt; type&lt;/a&gt;, or Clojure's wrapper, &lt;a href="https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/BigInt.java"&gt;&lt;code&gt;BigInt&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The math operations on these numbers are taking a long time, so is there anything faster? Unless we want to build out own math library, then we should look for something that already exists. This made me think of &lt;a href="https://man.cx/dc(1)"&gt;&lt;code&gt;dc&lt;/code&gt;&lt;/a&gt;, which is an arbitrary precision calculator that comes with most Unix-based systems. I seem to recall that this application was supposed to be fast. How would it compare?&lt;/p&gt;

&lt;h2&gt;
  
  
  Shells
&lt;/h2&gt;

&lt;p&gt;The easiest way to try this would be to shell out of the JVM to execute the &lt;code&gt;dc&lt;/code&gt; program, then communicate via a pipe. This is typically slow, but if the &lt;code&gt;fib*&lt;/code&gt; function only gets called 31 times, and there are only a few functions in that function, then this time will be negligible when compared to the time for the math operations.&lt;/p&gt;

&lt;p&gt;My first thought was, "Well, I know how to do that, but it will be fiddly. I'm sure it will take too long." And that was going to be that.&lt;/p&gt;

&lt;p&gt;But after a minute, I started thinking, "I haven't tried to call anything through a shell for a long time. Maybe I can just try something simple?"&lt;/p&gt;

&lt;p&gt;First of all, we want to see this operating on the command line. It uses reverse polish notation, which is a bit obtuse, but it does usually make for easier programming. The operations for &lt;code&gt;dc&lt;/code&gt; can be provided in a script to execute via the &lt;code&gt;-e&lt;/code&gt; operation, and the operations in the script here are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provide 2 numbers to place on the stack&lt;/li&gt;
&lt;li&gt;Provide the operation &lt;code&gt;+&lt;/code&gt;. This removes the top 2 numbers from the stack, adds them, and places the result on the top of the stack.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;p&lt;/code&gt; operation, which prints the value on the top of the stack
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;dc &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'2 3 +p'&lt;/span&gt;
5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we just need to execute it from Clojure. We do this with the &lt;code&gt;shell&lt;/code&gt; namespace, and each element of the command line is provided as a separate string parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;clojure.java.shell&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;shell/sh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"dc"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"-e"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"2 3 +p"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result of this is a structure containing &lt;code&gt;stdout&lt;/code&gt;, &lt;code&gt;stderr&lt;/code&gt; (as strings), and the exit code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"5\n"&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything is done with strings, and the final character needs to be truncated, but this is all tractable. So an addition function for &lt;code&gt;BigInt&lt;/code&gt; is reasonably short:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;+n&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:out&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;shell/sh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"dc"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"-e"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;" +p"&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bigint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;subs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;))))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I named it with &lt;code&gt;n&lt;/code&gt; on the end, since Clojure &lt;code&gt;BigInt&lt;/code&gt; values are printed with a trailing &lt;code&gt;N&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Trying it out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="n"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;+n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But why bother wrapping in a &lt;code&gt;BigInt&lt;/code&gt;? All the math operations are go over the pipe, so the numbers have to be converted to strings anyway. It makes sense to just leave them as strings.&lt;/p&gt;

&lt;p&gt;Using the above, we can generalize it to all of the required operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:out&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sh/sh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"dc"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"-e"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"p"&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;subs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;))))))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;+n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;op&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"+"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;*n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;op&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;-n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;op&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"-"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;quotn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;op&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"~r"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also add in the string tests for &lt;code&gt;even?&lt;/code&gt; and &lt;code&gt;zero?&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ev?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;even?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;last&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;z?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Note that the test for &lt;code&gt;ev?&lt;/code&gt; is checking the ASCII value of the final digit, which is even for all even digits).&lt;/p&gt;

&lt;p&gt;We can use these in Tory's function by tweaking it slightly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fibn*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;z?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fibn*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;quotn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;*n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;-n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;*n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;+n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;*n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;*n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ev?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;+n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)]))))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fibn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fibn*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since there are so many math operations in a row, then this could all be turned into a single &lt;code&gt;dc&lt;/code&gt; script, but that is really taking us into &lt;code&gt;dc&lt;/code&gt; programming, which isn't the point here. Instead, we're just trying to leverage the simple math operations on large numbers.&lt;/p&gt;

&lt;p&gt;Testing it looks promising:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="n"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fibn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"8"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"13"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"21"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"34"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It takes a second, which I'd expect with so many calls through the shell, but it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Output problem
&lt;/h2&gt;

&lt;p&gt;In fact, it works, all the way up to 332, when we get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;108245926205643306387794020096663813380901526766531123754208267893890\
9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It turns out that dc only prints out numbers to a width of 70 characters. Any numbers wider than that will broken up into multiple lines, with each line ending with a &lt;code&gt;\&lt;/code&gt; character.&lt;/p&gt;

&lt;p&gt;We can flatten this back into a single line by using a string replacement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;clojure.java.shell&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;clojure.string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:out&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;shell/sh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"dc"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"-e"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"p"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="n"&gt;flat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str/replace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"\\\n"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;subs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;flat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;flat&lt;/span&gt;&lt;span class="p"&gt;))))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Comparison
&lt;/h2&gt;

&lt;p&gt;Looking at the billionth Fibonacci takes a long time, so let's just compare the millionth number:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="n"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fibn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s"&gt;"Elapsed time: 773389.633083 msecs"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s"&gt;"Elapsed time: 172.583417 msecs"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bigint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At 773s compared to 172ms, the &lt;code&gt;dc&lt;/code&gt; backed version is nearly 4500 times slower 🤣&lt;/p&gt;

&lt;p&gt;There are 8 calls to math operations per invocation of &lt;code&gt;fibn*&lt;/code&gt;, and 1,000,000 executes &lt;code&gt;fibn*&lt;/code&gt; 20 times, for a total of 160 calls to the shell. Shelling out like this, along with the string processing involved in moving data across the pipe does take some time. Overall, it is taking a few seconds, but this is inconsequential when seeing that the majority of the 773 seconds are being taken up by &lt;code&gt;dc&lt;/code&gt; doing the work.&lt;/p&gt;

&lt;p&gt;Calling out a few of the later operations and running them directly in &lt;code&gt;dc&lt;/code&gt; demonstrates that it just takes a long time when working with large numbers.&lt;/p&gt;

&lt;h2&gt;
  
  
  BigInteger
&lt;/h2&gt;

&lt;p&gt;Clojure's &lt;code&gt;clojure.lang.BigInt&lt;/code&gt; class wraps the Java &lt;code&gt;java.math.BigInteger&lt;/code&gt; class. The main reason for this appears to be that small values will keep an equivalent &lt;code&gt;long&lt;/code&gt; value cached, for fast operations on small values.&lt;/p&gt;

&lt;p&gt;I've been looking at Java's &lt;code&gt;BigInteger&lt;/code&gt; class recently, considering how to implement the same functionality for ClojureScript, so I have some sense of what it's trying to do.&lt;/p&gt;

&lt;p&gt;I once saw an arbitrary precision math library manipulate numbers as strings of decimal digits. This worked well intuitively, since it means that operations like addition and multiplication can be performed using standard pencil-and-paper algorithms that are taught in school. But the principal benefit is that numbers can be parsed from a string or written back out trivially. However, decimal digits are stored in 8 bits, but only represent 3.25 bits of information. That's only about 40% storage efficiency.&lt;/p&gt;

&lt;p&gt;By contrast, Java's &lt;code&gt;BigInteger&lt;/code&gt; stores large numbers in binary. This stores 8 bits of information per byte, which is far denser. The same pencil-and-paper algorithms also work on numbers stored this way, but use symbols that range from 0-255, rather than 0-9. This is significantly faster to process, which is a major advantage.&lt;/p&gt;

&lt;p&gt;However, parsing from and conversion back to a string are very expensive operations, as these are conversions between binary and decimal. For instance, executing &lt;code&gt;(fib billion)&lt;/code&gt; on my machine takes 10.4 minutes to get the answer, but converting that answer into a string takes 25.6 minutes. That's nearly 2.5 times longer.&lt;/p&gt;

&lt;p&gt;I suspect that parsing and printing are where &lt;code&gt;dc&lt;/code&gt; is spending all of its time, especially since this is happening 20 times for each invocation of the &lt;code&gt;fib*&lt;/code&gt; function. I should learn to write more complex &lt;code&gt;dc&lt;/code&gt; operations, so I can run the entire algorithm in it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;What was the outcome of all this? Well, I lost an evening of my life. 😊&lt;/p&gt;

&lt;p&gt;More seriously though, it helped me solidify my usage of calling out to a shell from Clojure.&lt;/p&gt;

&lt;p&gt;Not mentioned above, I also tried using the &lt;code&gt;spit&lt;/code&gt; function to emit the operations to files which I then passed to &lt;code&gt;dc&lt;/code&gt; using the &lt;code&gt;-f&lt;/code&gt; flag. This was useful for seeing what specific operations had been executed. It also helped me gauge exactly where in the operation the function had reached. This was what first alerted me to the fact that &lt;code&gt;dc&lt;/code&gt; was taking a long time to execute basic operations. As mentioned, I expect that this was due to the parsing/printing phases of each invocation.&lt;/p&gt;

&lt;p&gt;I also learned a bit more about performance when it comes to parsing and printing large numbers. Implementing this in JavaScript has bogged me down, due to the sheer complexity of it, and it's interesting to see that the computer is having as hard a time doing it as I am having in trying to write it.&lt;/p&gt;

&lt;p&gt;I also had the opportunity to pull apart the logarithmic Fibonacci algorithm. I had skimmed this in my last reading of SICP, so I'm glad that I've taken the time to work through it now.&lt;/p&gt;

</description>
      <category>clojure</category>
    </item>
    <item>
      <title>More Immutability and Clojure</title>
      <dc:creator>Paula Gearon</dc:creator>
      <pubDate>Sun, 19 Jun 2022 02:47:44 +0000</pubDate>
      <link>https://dev.to/quoll/more-immutability-and-clojure-4cdk</link>
      <guid>https://dev.to/quoll/more-immutability-and-clojure-4cdk</guid>
      <description>&lt;p&gt;This is the second part to my post on &lt;a href="https://dev.to/quoll/immutable-vars-and-clojure-3nh8"&gt;immutability and Clojure&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Missing State
&lt;/h2&gt;

&lt;p&gt;One advantage to having mutability is the ability to accumulate state. For instance, let's look at some data to process in JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;twilight&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;15.3&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apple&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;12.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;11.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;18.1&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dash&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;18.0&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pie&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;13.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;13.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;44.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;15.5&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Consider how we might get the average of all of those values. This can be done in multiple ways, but a straightforward approach is to accumulate the sum of all the values, while also accumulating the count.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Average: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;Average: 17.14&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These accumulating values represent state, which the principles of immutability are trying to avoid. How might the same task be done without accumulating values like this?&lt;/p&gt;

&lt;h3&gt;
  
  
  Immutable in JavaScript
&lt;/h3&gt;

&lt;p&gt;Rather than jumping straight to Clojure, let's look at this in JavaScript.&lt;/p&gt;

&lt;p&gt;We need a total, and we need a total count. One way to get these is with the &lt;code&gt;reduce&lt;/code&gt; operation to process an array into a single value. Let's start by creating a function that can add all the numbers in an array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;accumulator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;accumulator&lt;/code&gt; here gets initialized with the &lt;code&gt;0&lt;/code&gt; parameter, and is passed in as an argument for the arrow function at each step.&lt;br&gt;
We can test this on a short array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This can be used to sum the numbers across all the arrays:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can add the counts similarly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives us the same answer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Average: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;Average: 17.14&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;However, the data had to be processed twice, once for calculating the total sum, and once for calculating the count. This could have serious ramifications if the data were particularly large, or if the processing were some other operation that required time-consuming I/O.&lt;/p&gt;

&lt;h3&gt;
  
  
  Immutable in Clojure
&lt;/h3&gt;

&lt;p&gt;Before addressing this, let's look at the same operations and data in Clojure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:label&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"twilight"&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:values&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;15.3&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:label&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"apple"&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:values&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;12.0&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;11.5&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;18.1&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:label&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"dash"&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:values&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;18.0&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:label&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"pie"&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:values&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;13.0&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;13.2&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;44.8&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;15.5&lt;/span&gt;&lt;span class="p"&gt;]}])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;sum&lt;/code&gt; function can be done a couple of ways, but if we stick to &lt;code&gt;reduce&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reduce&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can do the total and count. Clojure has some options that could make this easier, but transliterating the JavaScript gives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reduce&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:values&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;total-count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reduce&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:values&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Average:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;total-count&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;Average: 17.14&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;count&lt;/code&gt; is actually the name of the function in Clojure for getting the number of elements in something, so the var here has been renamed to &lt;code&gt;total-count&lt;/code&gt;, but otherwise it's the same approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Regaining State
&lt;/h2&gt;

&lt;p&gt;As mentioned above, each call to &lt;code&gt;reduce&lt;/code&gt; is processing the data sequence again, which leads to redundant work. Instead, we want to be accumulating both values while processing the data. This can be done by accepting and returning both values at each step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;total-count&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reduce&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="n"&gt;previous-total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;previous-count&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;previous-total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:values&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
                 &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;previous-count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:values&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)))])&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Average:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;total-count&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a few things to notice here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The function passed to &lt;code&gt;reduce&lt;/code&gt; still takes 2 arguments.&lt;/li&gt;
&lt;li&gt;The first argument to the function is "unpacked" into a pair of values.&lt;/li&gt;
&lt;li&gt;The value returned from the function is a 2 element vector.&lt;/li&gt;
&lt;li&gt;The "initial value" provided to &lt;code&gt;reduce&lt;/code&gt; is also a 2 element vector containing the 2 initial values (both zero).&lt;/li&gt;
&lt;li&gt;The final result of the &lt;code&gt;reduce&lt;/code&gt; is a 2 element vector, which gets unpacked into the &lt;code&gt;total&lt;/code&gt; and &lt;code&gt;total-count&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach to returning multiple values is something that JavaScript also supports, and is similar to using &lt;a href="https://pythonbasics.org/multiple-return/"&gt;tuples to return multiple values in Python&lt;/a&gt;. Other languages, like Java, struggle with this, resorting to cumbersome constructs like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;newTotal&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newCount&lt;/span&gt; &lt;span class="o"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And without an unpacking syntax, this becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;callFunction&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It works, and internally it's the same sort of thing that Clojure is doing, but it's messy to write, harder to read, and is also one of the many reasons why I stopped coding Java.&lt;/p&gt;

&lt;p&gt;Regardless of the language, the state of the process is being accumulated in multiple values. At each step, the entire state is packaged up and passed in as a single parameter, along with the new data to process, and a packaged new state is returned.&lt;/p&gt;

&lt;h2&gt;
  
  
  A More Structured Approach
&lt;/h2&gt;

&lt;p&gt;Vectors and tuples are not the only data structure that can be used to return multiple items that represent state. Clojure's map syntax is also useful, particularly as it allows each part of the state to be named:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="no"&gt;:keys&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;total-count&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reduce&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="no"&gt;:keys&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;total-count&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;previous-total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:values&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
                 &lt;/span&gt;&lt;span class="no"&gt;:total-count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;previous-count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;:values&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)))})&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:total-count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Average:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;total-count&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a simple case like this, a vector makes more sense to accumulate the state, but as the state becomes larger and more complex, using a map to encapsulate the state begins to gain value.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Mutation Makes Sense
&lt;/h2&gt;

&lt;p&gt;While mutation leads to greater complexity of state, there are occasions when mutation can be useful. The most common structures for this are &lt;code&gt;Atom&lt;/code&gt;s and &lt;code&gt;Volatile&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;Mutation is rarely needed, meaning that when mutation starts to become useful the code is often more complex that simple examples. Consequently, the examples below are more complex than what I've presented before now. I have included them to show that Clojure can still make use of mutation, even while preferring immutable structures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Counter Example
&lt;/h3&gt;

&lt;p&gt;A counter could theoretically be kept in an immutable state map, but this would need to be passed around everywhere, which would be both cumbersome and would slow down the program. It is also possible to accidentally pass in an old state, thereby returning a duplicate number. Instead, a global mutating counter would be ideal for this task.&lt;/p&gt;

&lt;p&gt;The Clojure Runtime has an internal &lt;code&gt;nextID&lt;/code&gt; function to return a number that is always greater than previously returned values. The function is used internally by the &lt;code&gt;gensym&lt;/code&gt; function. The user can even call it themselves:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;clojure.lang.RT/nextID&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;clojure.lang.RT/nextID&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;172&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;175&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This could instead be implemented in Clojure using an Atom:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="no"&gt;:private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;last-id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;atom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;next-id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;swap!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;last-id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While Clojure actually implements this in Java, &lt;a href="https://github.com/clojure/clojurescript/blob/e4ff22fcc66bce00a19863c581051e8ac20b76da/src/main/cljs/cljs/core.cljs#L10791-L10803"&gt;ClojureScript does it in native ClojureScript code with an atom&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The code above initializes the atom to 0, then every time the &lt;code&gt;next-id&lt;/code&gt; function is called the number in the atom gets incremented and returned.&lt;/p&gt;

&lt;p&gt;An atom is used here, because the operation could be called from anywhere, including in multiple threads at the same time. Atoms have very important properties that make them thread safe, meaning that multi-threaded applications won't encounter problems like duplicate values, or bad data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Caching Example
&lt;/h3&gt;

&lt;p&gt;Similarly, a mutating map containing a cache can be easier to manage than passing the cache in and out of every function that needs it.&lt;/p&gt;

&lt;p&gt;Clojure's &lt;code&gt;memoize&lt;/code&gt; function attaches an atom to a function to return previously calculated values. This can be valuable for expensive operations.&lt;/p&gt;

&lt;p&gt;For instance, a function that naively calculates the &lt;code&gt;nth&lt;/code&gt; Fibonacci number has exponential complexity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will work fine up to 30 or so, but after that you will start seeing delays. On my notebook, calling &lt;code&gt;(fib 45)&lt;/code&gt; will take over 9 seconds. If I run it with an argument of 50 then it takes over 10 minutes. The SICP book has &lt;a href="https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.2"&gt;a good explanation&lt;/a&gt; of why this is exponential.&lt;/p&gt;

&lt;p&gt;But if the function is memoized, then large numbers can be evaluated quickly without having to change the algorithm. We can do this by changing from &lt;code&gt;defn&lt;/code&gt; to using an equivalent &lt;code&gt;def&lt;/code&gt;/&lt;code&gt;fn&lt;/code&gt; pair, and wrapping the function definition in a call to &lt;code&gt;memoize&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;memoize&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)))))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can call &lt;code&gt;(fib 90)&lt;/code&gt; and it will return immediately.&lt;/p&gt;

&lt;p&gt;The code for memoize is relatively short:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;memoize&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;atom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{})]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;if-let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;find&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;val&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;apply&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;swap!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;assoc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;memoize&lt;/code&gt; returns a new function within the scope of an atom called &lt;code&gt;mem&lt;/code&gt;. This atom contains a map which uses a sequence of function arguments as the keys, and previously calculated values as the mapped vals. If an entry for a seq of arguments doesn't exist, then those arguments are new. That leads to the original function getting run on the arguments, and the result gets stored in the atom's map before being returned.&lt;/p&gt;

&lt;h3&gt;
  
  
  core.cache Example
&lt;/h3&gt;

&lt;p&gt;Understanding how to attach an atom to a function like this is very useful if you want a more intelligent cache, such as with &lt;a href="https://github.com/clojure/core.cache"&gt;&lt;code&gt;core.cache&lt;/code&gt;&lt;/a&gt;. This library provides immutable objects, much like an immutable map, which can be held in an atom in a similar way to how &lt;code&gt;memoize&lt;/code&gt; does it.&lt;/p&gt;

&lt;p&gt;This is stepping up a level in complexity, but since I'm here, the following is a function that performs a similar job as &lt;code&gt;memoize&lt;/code&gt;, but with an &lt;a href="https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)"&gt;LRU cache&lt;/a&gt; from the core.cache library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;clojure.core.cache&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lru-memoize&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;atom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cache/lru-cache-factory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}))]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cache/lookup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;::nil&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;::nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;apply&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;swap!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cache/miss&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;do&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;swap!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cache/hit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, this holds up to 32 items in the cache, though it can be customized with an extra parameter to the &lt;code&gt;lru-cache-factory&lt;/code&gt; function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local Mutation
&lt;/h2&gt;

&lt;p&gt;The above examples show mutation at a global scale (or, potentially global, if a memoized function is to be accessible from anywhere). Because the scope of access is open, then the mutating objects must be thread-safe. But there are occasions where mutation might occur within a controlled block of code. In such cases, the small overhead associated with thread safety may be avoided by using a &lt;em&gt;Volatile&lt;/em&gt; object.&lt;/p&gt;

&lt;p&gt;Volatiles are implemented as a simple object in the host system (Java, JavaScript, C#, Dart, etc) with a single mutable field. To see how simple the implementation is, the Java version is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Volatile&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;IDeref&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;volatile&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Volatile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="nf"&gt;deref&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;newval&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newval&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's not much to it: You can create it, read the value in it, and change the value in it. This is the same as an Atom, but is not thread safe.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Quick Discussion on Races
&lt;/h3&gt;

&lt;p&gt;What do I mean by "not thread safe"? Notice how there are operations to read the value (via &lt;code&gt;deref&lt;/code&gt;) and write to the value (via &lt;code&gt;reset&lt;/code&gt;). This is no way to read a value and write back to it before another thread has a chance to change it on you. When a thread is trying to write a value before another thread can get to it, then this is referred to as a &lt;em&gt;race&lt;/em&gt;. Races are bad.&lt;/p&gt;

&lt;p&gt;As a simple example, consider an atom &lt;code&gt;a&lt;/code&gt; with a number in it. If one thread (started with &lt;code&gt;future&lt;/code&gt;) increments that number a large number of times, and another thread decrements it the same number of times, then we should see the original number come out at the end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;atom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;future&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dotimes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;swap!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dotimes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;swap!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;dec&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Thread/sleep&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;;; more than enough time to wait&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Final value:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;deref&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;Final value: 0&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The first thread should finish at around the same time as the main thread, but I added a short wait to ensure that it does. The operations take 80ms on my notebook, so half a second is ample time, and we can see that the final value is what we expected.&lt;/p&gt;

&lt;p&gt;However, volatiles don't provide the guarantees that atoms do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;volatile!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;future&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dotimes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;vswap!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dotimes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;vswap!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;dec&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Thread/sleep&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;;; more than enough time to wait&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Final value:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;deref&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;Final value: 6475&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This number will be different every time, and is certainly not the &lt;em&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/em&gt; that was expected.&lt;/p&gt;

&lt;p&gt;Incidentally, the time it takes my machine to run both threads operating on volatiles like this is 15ms. That's a lot faster than the 80ms that the atom implementation took, which is why volatiles are attractive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Volatiles Make Sense
&lt;/h2&gt;

&lt;p&gt;Since volatiles are not thread safe, it is important that they are only used in a context that cannot be accessed from outside the current thread. A typical example is within the confines of a function or &lt;code&gt;let&lt;/code&gt; block.&lt;/p&gt;

&lt;p&gt;One example might be to use a volatile to record information while processing data for another purpose. Let's start by creating a sequence of 1000 random numbers, from 0 to 100:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;repeatedly&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rand-int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's determine the sum of these numbers, but on the way, count how many of them are divisible by 7:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sevens&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;volatile!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reduce&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
                      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;when&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;zero?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;mod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;vswap!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sevens&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
                      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"total:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"sevens:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;sevens&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Can this be done with extra state in the accumulator? Certainly. But as complexity of the code increases, then having state on the side like this can help to simplify. It can also be faster than creating temporary objects that contain the updated state.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transducers
&lt;/h3&gt;

&lt;p&gt;One of the most important reasons for using volatile values is for maintaining state throughout a process. The most common example of this is in &lt;a href="https://clojure.org/reference/transducers#_creating_transducers"&gt;Transducers&lt;/a&gt;. These are a group of functions that are used for processing a sequence, with one function handling the start, another handling the end, and a function for handling each element in the sequence.&lt;/p&gt;

&lt;p&gt;If there is a need for a sequence processor to remember what it has already done, then the transducer can use a volatile to do it. One example of this is the &lt;code&gt;dedupe&lt;/code&gt; function. It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dedupe&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rf&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;volatile!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;::none&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;rf&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;rf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;prior&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;pv&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;vreset!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prior&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;rf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;))))))))&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sequence&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;dedupe&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most of this is boilerplate for a transducer, but notice the &lt;code&gt;let&lt;/code&gt; block that declares the &lt;code&gt;pv&lt;/code&gt; var as a volatile.&lt;/p&gt;

&lt;p&gt;The 2-argument form of the transducer does the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Looks up the prior value, which is stored in the volatile.&lt;/li&gt;
&lt;li&gt;Update the prior value to the current value.&lt;/li&gt;
&lt;li&gt;If it equals the current value, then return the result unchanged.&lt;/li&gt;
&lt;li&gt;Otherwise, the current value is different to the prior value, so add it to the result.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other built-in transducers use volatiles to store state as well. &lt;a href="https://github.com/clojure/clojure/blob/35bd89f05f8dc4aec47001ca10fe9163abc02ea6/src/clj/clojure/core.clj#L2886-L2898"&gt;&lt;code&gt;take&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/clojure/clojure/blob/35bd89f05f8dc4aec47001ca10fe9163abc02ea6/src/clj/clojure/core.clj#L2933-L2942"&gt;&lt;code&gt;drop&lt;/code&gt;&lt;/a&gt; use a volatile to count how many items they have iterated over. &lt;a href="https://github.com/clojure/clojure/blob/35bd89f05f8dc4aec47001ca10fe9163abc02ea6/src/clj/clojure/core.clj#L7361-L7366"&gt;&lt;code&gt;map-indexed&lt;/code&gt;&lt;/a&gt; uses a volatile to remember the current index value. &lt;a href="https://github.com/clojure/clojure/blob/35bd89f05f8dc4aec47001ca10fe9163abc02ea6/src/clj/clojure/core.clj#L5061-L5069"&gt;&lt;code&gt;distinct&lt;/code&gt;&lt;/a&gt; uses a volatile to remember everything that it has already returned so that it never returns the same value twice.&lt;/p&gt;

&lt;p&gt;If you ever need to create a transducer that can remember state between elements, then be sure to reference the code in &lt;a href="https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj"&gt;clojure.core&lt;/a&gt; to see how it was done there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;This was a much more advanced look at immutability and mutability in Clojure.&lt;/p&gt;

&lt;p&gt;We started by looking at how state can be remembered by accepting and returning state at each stage of processing. State can be stored in any kind of structure, and is typically a vector when the state is small, or a map when the complexity of the state increases. These state objects are often destructured by the code that processes them.&lt;/p&gt;

&lt;p&gt;We then started looking at cases where mutability is useful, and some of the tools that Clojure provides for this. When data is globally accessible, or can be accessed in multiple threads, then mutable data will usually be stored in an &lt;em&gt;Atom&lt;/em&gt;. But when the scope of this data is constrained, then a &lt;em&gt;Volatile&lt;/em&gt; can be used instead. Volatiles work just like Atoms, but are not thread safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Afterword
&lt;/h2&gt;

&lt;p&gt;This is much more complicated than my original introduction to immutability. I felt that it was necessary to describe the more complex cases that inevitably arise, and also the flexibility that Clojure offers when mutability really is the best tool for the job.&lt;/p&gt;

&lt;p&gt;Again, I would appreciate any questions or complaints about this, to help improve the explanation.&lt;/p&gt;

</description>
      <category>clojure</category>
      <category>immutable</category>
    </item>
    <item>
      <title>Immutable Vars and Clojure</title>
      <dc:creator>Paula Gearon</dc:creator>
      <pubDate>Sat, 18 Jun 2022 00:02:43 +0000</pubDate>
      <link>https://dev.to/quoll/immutable-vars-and-clojure-3nh8</link>
      <guid>https://dev.to/quoll/immutable-vars-and-clojure-3nh8</guid>
      <description>&lt;p&gt;People often feel at a loss when they first look at languages with immutability. I know I did. How can you write a program without changing the value of a variable?&lt;/p&gt;

&lt;h2&gt;
  
  
  Mutable
&lt;/h2&gt;

&lt;p&gt;First of all, what does it mean to change a variable? Consider some simple JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a variable called &lt;code&gt;x&lt;/code&gt; that contains the number 5. The second line changes the value of x to itself plus 3, which means that it gets changed to the number 8.&lt;/p&gt;

&lt;p&gt;This works, though the choice of the "equals" sign in languages like JavaScript is a bit awkward.&lt;/p&gt;

&lt;p&gt;If you were in high school algebra class and you saw:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x = x + 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…you'd probably throw your hands up in despair. When looking at math, we expect &lt;code&gt;x&lt;/code&gt; to be described by a set of conditions, where &lt;code&gt;=&lt;/code&gt; can be used as part of that description. This statement can't be true, since a number &lt;code&gt;x&lt;/code&gt; can't be equal to itself plus 3. This is why some languages won't use a simple &lt;code&gt;=&lt;/code&gt; character when changing a variable. For instance, Pascal uses &lt;code&gt;:=&lt;/code&gt;, R uses an arrow &lt;code&gt;&amp;lt;-&lt;/code&gt;, and many computer science texts use an arrow character &lt;code&gt;←&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Math provides a powerful way to look at the world, and it includes this idea of values that meet a condition, and don't change. Conversely, anyone with significant experience debugging a program has seen variables change unexpectedly. When the state of your application is based on the values in its variables, then this means that understanding the current state can get very difficult when those variables change. Perhaps the idea of values that don't change could be useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Immutable
&lt;/h2&gt;

&lt;p&gt;How does this compare to using immutable values?&lt;/p&gt;

&lt;p&gt;JavaScript lets you create immutable values with the &lt;code&gt;const&lt;/code&gt; declaration. This means that we can't change the value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which results in:&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Uncaught TypeError: Assignment to constant variable.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Instead, we have to declare a whole new thing to take the new value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is limited, but it's more flexible than you might expect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shadowing
&lt;/h3&gt;

&lt;p&gt;You can even re-use the name &lt;code&gt;x&lt;/code&gt; in other parts of the code, without changing the original value. This is called &lt;em&gt;shadowing&lt;/em&gt;. In JavaScript this must be done in a new scope:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// a new scope&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;the new value is: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;the old value is still: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;the new value is: 9&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;the old value is still: 5&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Inside that new scope, the value of &lt;code&gt;x&lt;/code&gt; is set to 9, but in the outer scope it remains at 5.&lt;/p&gt;

&lt;p&gt;But we never print &lt;code&gt;y&lt;/code&gt; so why not just skip that and add &lt;code&gt;x&lt;/code&gt; to itself? Well, it turns out that JavaScript thinks that all references to &lt;code&gt;x&lt;/code&gt; in the inner scope are referring to the &lt;code&gt;x&lt;/code&gt; that's already in that scope, which means that the declaration of &lt;code&gt;x&lt;/code&gt; can't refer to itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;the value is: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;Uncaught ReferenceError: "x" is not defined&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;JavaScript can use immutable variables, but it isn't entirely smooth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clojure
&lt;/h2&gt;

&lt;p&gt;In contrast, languages like Haskell, Erlang, Scala and Clojure are designed to make using immutability natural. They often have some way to allow mutability where it can help, but these are typically awkward to use, or in the case of Haskell, simply not there.&lt;/p&gt;

&lt;p&gt;In Clojure we don't have "variables" anymore. Instead, the thing that holds a value is called a "var". These can be declared globally with &lt;code&gt;def&lt;/code&gt;. There &lt;em&gt;are&lt;/em&gt; operations that can modify a var, but they should generally be avoided. Those operations can be used to patch or temporarily modify code that is not in your control, but that sort of thing is typically only necessary in libraries or testing.&lt;/p&gt;

&lt;p&gt;In a local scope, we declare values via &lt;code&gt;let&lt;/code&gt;. These are just local names for things and cannot be varied at all.&lt;/p&gt;

&lt;p&gt;Like all Lisps, operations like &lt;code&gt;let&lt;/code&gt; are enclosed in parentheses. The values to be created appear first, inside an array, with the name immediately before the value it will be set to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"value is:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;value is: 5&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Shadowing is even easier than JavaScript, since the old value of &lt;code&gt;x&lt;/code&gt; will be used until the new value is finished being defined:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"The new value is:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"This old value is still:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;The new value is: 9&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;This old value is still: 5&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But we don't necessarily need that old, outer value. When that happens, we don't need the separate scopes, and we can &lt;code&gt;let&lt;/code&gt; the &lt;code&gt;x&lt;/code&gt; multiple times:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"value:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;value: 9&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This was made using 3 different values for &lt;code&gt;x&lt;/code&gt;, with each one shadowing the previous one. It's not the way I like to write code myself (mostly because I like to have access to the various values of x, and not have them hidden when they get shadowed), but this demonstrates &lt;code&gt;let&lt;/code&gt; makes shadowing easy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Loops
&lt;/h2&gt;

&lt;p&gt;Just like shadowing, some loop constructs allow you to reuse a name with a new value each time. For instance, we can vary x from 0 to 4 and get the squares:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;(0 1 4 9 16)&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Each time going through this &lt;code&gt;for&lt;/code&gt; construct, the value of &lt;code&gt;x&lt;/code&gt; will be set to something new. But unlike JavaScript, it has not &lt;em&gt;changed&lt;/em&gt; a variable called &lt;code&gt;x&lt;/code&gt;. It's an entirely new &lt;code&gt;x&lt;/code&gt; each time.&lt;/p&gt;

&lt;p&gt;In a similar way, we can use a &lt;code&gt;loop&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;loop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;when&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;;; output a single number&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;recur&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;;; ends the line of output with a newline&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;0  1  4  9  16&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The first time through the &lt;code&gt;loop&lt;/code&gt;, the initial vector acts like a &lt;code&gt;let&lt;/code&gt; where &lt;code&gt;x&lt;/code&gt; has been set to &lt;code&gt;0&lt;/code&gt;. Then, each time &lt;code&gt;recur&lt;/code&gt; is called, the loop acts like a &lt;code&gt;let&lt;/code&gt; again, only instead of &lt;code&gt;0&lt;/code&gt; the &lt;code&gt;x&lt;/code&gt; will be set to whatever value the &lt;code&gt;recur&lt;/code&gt; was given.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structures
&lt;/h2&gt;

&lt;p&gt;Immutability takes on a new meaning when applied to a structure. For instance, consider an array in JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;[ 1, 2, 3 ]&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;[ 1, 2, 3, 4 ]&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;How did the array &lt;code&gt;a&lt;/code&gt; change when it was declared &lt;code&gt;const&lt;/code&gt;? It happened because &lt;code&gt;a&lt;/code&gt; continued to point to the same array, but the &lt;code&gt;push&lt;/code&gt; operation changed what was in that array. This is like referring to a closet, but hanging up more clothes in there. The closet doesn't change, but the contents of the closet do.&lt;/p&gt;

&lt;p&gt;However, languages like Clojure and Scala also offer immutable structures:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;conj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;[1 2 3 4]&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Well, we can see that we shadowed &lt;code&gt;a&lt;/code&gt;, but how do we know if changed the original or not? Let's not shadow it, and print the original object after the extra number was added:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;a2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;conj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"original array:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"new array:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;original array: [1 2 3]&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;new array: [1 2 3 4]&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This works with all of Clojure's structured types. For instance, maps have new items associated with it, via the &lt;code&gt;assoc&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:one&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="no"&gt;:two&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="no"&gt;:three&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;m2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;assoc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:four&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="no"&gt;:five&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"original map:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"new map:"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;original map: {:one 1, :two 2, :three 3}&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;new map: {:one 1, :two 2, :three 3, :four 4, :five 5}&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The most important aspect of this behavior is that operations which modify a structure will return the new structure, since the original structure does not change. This is different to structures that mutate. Consider the array in JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;4&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This &lt;code&gt;push&lt;/code&gt; operation doesn't return the new array. Instead, it returns the value that was added to the array. That's OK, because we can go back to the object referred to by &lt;code&gt;a&lt;/code&gt; and see that the array has this change. But for immutable structures, the only time you can get access to the new structure after an operation is in the return value of that operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Immutable Values with Immutable Structures
&lt;/h2&gt;

&lt;p&gt;Using some of the above examples we can build a structure that is referred to with immutable values. For instance, a loop can be used to build a vector containing squares:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;loop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;;; i is greater than 10, so return v&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;recur&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;conj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;[0 1 4 9 16 25 36 49 64 81 100]&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;While this works, it is also a bit clunky. Typically, when adding lots of things to a single object, the correct way to do it in Clojure is to use the &lt;code&gt;reduce&lt;/code&gt; function. This needs a function that accepts your structure plus another argument, and is expected to return the new structure. For instance, the above example would use a function that takes a vector and a number, then returns a new vector that has the square of the number added. Like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the-function&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;conj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can test it out by giving it a small vector and a number, and see if the square of that number is added to the end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;the-function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;[0 1 4]&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;reduce&lt;/code&gt; function can use this for each number in the range 0 to 10 (up to, but excluding, 11):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reduce&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;the-function&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="c1"&gt;;; the starting structure&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;;; the numbers to process, from 0 to 10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;[0 1 4 9 16 25 36 49 64 81 100]&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This does essentially the same as the original loop above, but now the operations are more structured.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;NB: This code is to demonstrate a point. Building this vector in real code would be better done with a &lt;code&gt;mapv&lt;/code&gt; over the &lt;code&gt;range&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Size
&lt;/h2&gt;

&lt;p&gt;An intuition that many people develop around this is that the structures are being copied, and then the copy gets modified. While this would work, a copy has the disadvantages of doubling the space consumption of the original, and requires all of the data to be processed, which could be slow when a structure gets large. Creating a vector of 1 million items by adding a single item at a time would create 1 million intermediate vectors, with a total of 500,000,500,000 elements between them.&lt;/p&gt;

&lt;p&gt;Instead, Clojure structures use "structural sharing". This means that a new structure can be a reference to the data in the previous structure, and only contain whatever changes it requires. This saves on both space and processing time. There are even internal operations in Clojure that can skip many intermediate steps when processing large blocks of data, thereby making the operation more efficient.&lt;/p&gt;

&lt;p&gt;This approach wouldn't work if structures were mutable. For instance, consider a map &lt;code&gt;m&lt;/code&gt; containing 10 items and then map &lt;code&gt;n&lt;/code&gt; is created by adding a new item to &lt;code&gt;m&lt;/code&gt;. Internally, &lt;code&gt;n&lt;/code&gt; has a reference to &lt;code&gt;m&lt;/code&gt; and its single new item, giving it a total of 11 items. The diagram below shows this, and also shows the effective structure that &lt;code&gt;n&lt;/code&gt; represents.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1x3j0sypqafpjo2vhxq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1x3j0sypqafpjo2vhxq.png" alt="Vector with shared structure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we were in a mutable system and we took away something from &lt;code&gt;m&lt;/code&gt;, then &lt;code&gt;m&lt;/code&gt; would be down to 9 items. &lt;code&gt;n&lt;/code&gt; still contains its reference to &lt;code&gt;m&lt;/code&gt; plus its extra item, so now &lt;code&gt;n&lt;/code&gt; has &lt;strong&gt;also&lt;/strong&gt; been modified, and ends up with only 10 items in total. In this example, we can see that the number &lt;code&gt;9&lt;/code&gt; is removed from the end of &lt;code&gt;m&lt;/code&gt;, so this is also removed from &lt;code&gt;n&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc183c25t6039zb7gfo60.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc183c25t6039zb7gfo60.png" alt="Vector with shared structure after modifying"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Anyone debugging such a system may be confused as to why &lt;code&gt;n&lt;/code&gt; was changed, because nothing appeared to change &lt;code&gt;n&lt;/code&gt;! But because Clojure's structures don't change, then structural sharing works cleanly.&lt;/p&gt;

&lt;p&gt;If you really, really want to know how structural sharing works, &lt;a href="https://youtu.be/oD1WONpv6Xc" rel="noopener noreferrer"&gt;I gave a talk on this at :clojureD 2021&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;This was an initial attempt to describe how programming is still possible when variables and data can't be changed, and to show how this can be done in Clojure.&lt;/p&gt;

&lt;p&gt;Clojure uses &lt;em&gt;Vars&lt;/em&gt; and values that don't change, rather than &lt;em&gt;Variables&lt;/em&gt; that do. New values with existing names can be used, and these will hide (or &lt;em&gt;shadow&lt;/em&gt;) the previous value (or even a var) with that name. Often times, a piece of code will be run many times with its value names set to different values, such as in a loop, but at no point will an existing var or value be changed inside that block.&lt;/p&gt;

&lt;p&gt;Clojure data structures are also immutable, in that their contents never change. The effect of a change is done by creating a new structure with the desired change, and the old structure is often abandoned (though it can also be useful to keep the old structures on occasion, especially for debugging).&lt;/p&gt;

&lt;p&gt;Changed structures look like a copy of their predecessor, with a modification. However, this is handled much more efficiently than a copy would imply.&lt;/p&gt;

&lt;h2&gt;
  
  
  Afterword
&lt;/h2&gt;

&lt;p&gt;Immutability is something that stops people when they first come to functional languages, so I would like to work on explaining it for people making the shift. Personally, I learned about it when I first picked up the Scala language, so none of this is unique to Clojure.&lt;/p&gt;

&lt;p&gt;This is my first attempt at explaining this topic, so I'm expecting that I haven't done a great job of it. I would appreciate feedback on the parts that work and the parts that are confusing. Meanwhile, if I left you feeling bewildered, try reading the same topic in &lt;a href="https://www.artima.com/shop/programming_in_scala_5ed" rel="noopener noreferrer"&gt;"Programming in Scala" by Odersky, Spoon, Venners and Sommers&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>clojure</category>
      <category>immutable</category>
    </item>
    <item>
      <title>Asami</title>
      <dc:creator>Paula Gearon</dc:creator>
      <pubDate>Mon, 08 Feb 2021 23:22:39 +0000</pubDate>
      <link>https://dev.to/quoll/asami-3fi7</link>
      <guid>https://dev.to/quoll/asami-3fi7</guid>
      <description>&lt;h1&gt;
  
  
  Motivation
&lt;/h1&gt;

&lt;p&gt;For a long time, I had been thinking that I would like to redesign Mulgara storage to overcome some of the deficiencies that had become clear over time. I was also thinking that I would like to use a more &lt;a href="https://en.wikipedia.org/wiki/Functional_programming"&gt;Functional&lt;/a&gt; approach, to make the code more tractable and reliable. But this would still take a lot of work that I wasn't sure I wanted to apply.&lt;/p&gt;

&lt;p&gt;In 2008 I came up with some new index designs and had started implementing these for Mulgara. They were showing some promise, but still had a long way to go. However, a change of job soon had me ignoring storage and looking a rules systems again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rules
&lt;/h2&gt;

&lt;p&gt;My original implementation of a Rules engine was in Mulgara, and hence was built in Java. My second was on a &lt;a href="http://www.w3.org/TR/sparql11-overview/"&gt;SPARQL&lt;/a&gt; store (I tried a few, but mostly was using Jena &lt;a href="https://jena.apache.org/documentation/fuseki2/"&gt;Fuseki&lt;/a&gt;). This was at the company Revelytix, which gave me an opportunity to use Clojure for the first time. I'd learned &lt;a href="https://en.wikipedia.org/wiki/Scheme_(programming_language)"&gt;Scheme&lt;/a&gt; through &lt;a href="https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book.html"&gt;SICP&lt;/a&gt; some years before, I'd adopted a lot of Functional Programming principles, and I'd learned Haskell and Scala, but Clojure was the first time I felt I was really productive with these concepts.&lt;/p&gt;

&lt;p&gt;In 2013 I started re-implementing some of Mulgara's memory-mapping approach using Clojure and got the basic idea of blocks working. This was important for abstracting disk access, particularly as it allows memory-mapping files beyond the 2GB limit that Jave imposes due to backward compatibility with 32-bit architecture. Once this was done I didn't take it further at the time.&lt;/p&gt;

&lt;p&gt;It was while using Clojure with &lt;a href="https://www.orientdb.org/"&gt;OrientDB&lt;/a&gt;, &lt;a href="https://www.datomic.com/"&gt;Datomic&lt;/a&gt; and &lt;a href="http://neo4j.com/"&gt;Neo4J&lt;/a&gt;, that I started getting a feel for graph databases that weren't based on RDF and SPARQL. They are all very similar in many ways, and it occurred to me that I could build a graph rules engine that was abstracted from the database, only requiring an adapter for each type. With this in mind, I started building a new rules engine, with an initial adapter for Datomic.&lt;/p&gt;

&lt;p&gt;I was pleased with how well this worked and showed my then-boss, Craig while we waiting in an airport together. He was very interested in it and asked me if I would be prepared to develop it for Cisco. I agreed, so long as I could keep it open source, which Craig was pleased to do. Thus, &lt;a href="https://github.com/threatgrid/naga"&gt;Naga&lt;/a&gt; was born.&lt;/p&gt;

&lt;p&gt;Craig did have one request though. He did not want to tie this to a commercial database, so would I be able to build something of my own? At this point, neither of us were aware that &lt;a href="https://github.com/tonsky/datascript"&gt;Datascript&lt;/a&gt; had been started, or else I would have opted to use that.&lt;/p&gt;

&lt;p&gt;My first thought was just how big a project Mulgara had become, but then I realized that the only features I needed were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Index lookups by triple-pattern.&lt;/li&gt;
&lt;li&gt;Counting the size of the results of index lookups.&lt;/li&gt;
&lt;li&gt;Inner join operations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I didn't even need to do this in storage. I could handle all of this in memory, and if I wanted to scale up, then that's when I could move to an existing database. So I agreed.&lt;/p&gt;

&lt;p&gt;The first version worked well and was the basis for the talk I gave on &lt;a href="https://www.youtube.com/watch?v=8rRzESy0X2k"&gt;Naga at Clojure/conj 2016&lt;/a&gt;. The code for this was also small:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://github.com/threatgrid/naga/blob/d149904da8ecb510ddbbb5b73824c74da4b05d77/src/naga/storage/memory/index.clj"&gt;index&lt;/a&gt; was a simple nested-map structure. Rather than storing triples in sequence, this allows duplicates in the first columns to be skipped. Also, the values appeared directly in the statements, and were not mapped to numbers.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://github.com/threatgrid/naga/blob/d149904da8ecb510ddbbb5b73824c74da4b05d77/src/naga/storage/memory/core.clj"&gt;join operation&lt;/a&gt; was a relatively easy nested loop, using techniques borrowed from Mulgara.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also realized that since queries were being machine-generated, then there should be a query planner to ensure that they did not get executed in an inefficient order. This appeared in the same namespace as the rest of the query processing.&lt;/p&gt;

&lt;h1&gt;
  
  
  Asami
&lt;/h1&gt;

&lt;p&gt;Shortly after presenting Naga in Austin Craig started asking for new features. The first one was to make it compatible with &lt;a href="https://clojurescript.org/"&gt;ClojureScript&lt;/a&gt; so that we could use it directly in a web page instead of through a service. I had only experimented with ClojureScript, so this was an opportunity to use it in production.&lt;/p&gt;

&lt;p&gt;Then I was asked for more features, both in rules and in querying the resulting data, which meant implementing a much more capable query engine, and query planner. As the code started to expand, I realized that the database had taken on a life of its own, and so I split it into its own project. In keeping with our in-joke of a naming scheme based on the &lt;a href="https://en.wikipedia.org/wiki/Avatar:_The_Last_Airbender#Sequel_series"&gt;Avatar&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/The_Legend_of_Korra"&gt;Korra&lt;/a&gt; cartoons, I named the new database "Asami".&lt;/p&gt;

&lt;p&gt;I liked this name, since the character of Asami doesn't have powers like the other characters do, so she builds her own devices to make up for it. 😊&lt;/p&gt;

&lt;h2&gt;
  
  
  Querying
&lt;/h2&gt;

&lt;p&gt;The first step was to provide an API for querying Asami with something that wasn't as low-level as the original approach. I copied the Datomic syntax for this, as it was compatible with how I was representing queries already, and it did not require parsing.&lt;/p&gt;

&lt;p&gt;This made it easier to introduce syntax for new queries and then building the implementation. Some of the new features here are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Negations, via the &lt;code&gt;not&lt;/code&gt; operator.&lt;/li&gt;
&lt;li&gt;Disjunctions, via the &lt;code&gt;or&lt;/code&gt; operator.&lt;/li&gt;
&lt;li&gt;Nested Conjunctions, via the &lt;code&gt;and&lt;/code&gt; operator.&lt;/li&gt;
&lt;li&gt;Filter expressions.&lt;/li&gt;
&lt;li&gt;Binding expressions.&lt;/li&gt;
&lt;li&gt;Passing data into a query to bind to a value.&lt;/li&gt;
&lt;li&gt;Aggregates, via the functions: &lt;code&gt;count&lt;/code&gt;, &lt;code&gt;sum&lt;/code&gt;, &lt;code&gt;avg&lt;/code&gt;, &lt;code&gt;first&lt;/code&gt;, &lt;code&gt;last&lt;/code&gt;, &lt;code&gt;max&lt;/code&gt;, &lt;code&gt;min&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most of these operations are performed in a similar way to Mulgara, though I've reimplemented everything from first principles.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;An important point to note here is that &lt;em&gt;most&lt;/em&gt; (not all!) of the files that implement the above in Mulgara total 11,251 lines of Java. &lt;strong&gt;Asami does it in 783 lines of Clojure.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This illustrates a few things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clojure allows for symbolic manipulation far more easily than Java.&lt;/li&gt;
&lt;li&gt;Java manages data structures through individual classes, which takes a lot of boilerplate code. In Clojure, it is more natural to use the built-in data structures, which simplifies things greatly.&lt;/li&gt;
&lt;li&gt;I could never have attempted this as an individual without a functional language with the facilities that Clojure offers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Storage
&lt;/h2&gt;

&lt;p&gt;Mulgara executes queries by requesting statements that match statement patterns and then performing various operations on each of these results.&lt;/p&gt;

&lt;p&gt;The statement patterns, or &lt;em&gt;constraints&lt;/em&gt; are typically in the form of a triple, (with a fourth value implied from context or simply not needed). They contain &lt;em&gt;ground values&lt;/em&gt; (such as URIs or strings), and variables. We refer to finding the statements that match a pattern as &lt;em&gt;resolving&lt;/em&gt; the pattern. A pattern resolution &lt;em&gt;binds&lt;/em&gt; the variables in the pattern to the parts of the statements that match it.&lt;/p&gt;

&lt;p&gt;For instance, in the following statements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:a :first-name "Fitzwilliam"
:a :last-name "Darcy"
:a :friend :c
:b :first-name "Elizabeth"
:b :last-name "Bennet"
:c :first-name "Charles"
:c :last-name "Bingley"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the constraint pattern: &lt;code&gt;[?person :first-name ?name]&lt;/code&gt;&lt;br&gt;
would resolve to the statements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:a :first-name "Fitzwilliam"
:b :first-name "Elizabeth"
:c :first-name "Charles"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;bindings&lt;/em&gt; would be pairwise for the variables of &lt;code&gt;?person&lt;/code&gt; and &lt;code&gt;?name&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{?person = :a, ?name = "Fitzwilliam"}
{?person = :b, ?name = "Elizabeth"}
{?person = :c, ?name = "Charles"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Queries are answered by resolving constraint patterns and combining the results according to the operations in the query. I presented a talk describing the operation of this at &lt;a href="https://youtu.be/tbVwmFBnfo4"&gt;ClojureD in 2019&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The operations are part of the "Query Engine", and the resolution step is part of an API for talking to storage. This abstraction makes it possible to store the data in various ways, or even to reinterpret other data as a graph, so long as an API can be implemented to resolve constraint patterns into bindings.&lt;/p&gt;

&lt;p&gt;Mulgara has a &lt;code&gt;Resolver&lt;/code&gt; interface to describe this API. Asami adopts the same approach, using the &lt;code&gt;Graph&lt;/code&gt; protocol.&lt;/p&gt;

&lt;p&gt;Mulgara has a number of &lt;code&gt;Resolver&lt;/code&gt; implementations, including the transactional store, an RDF document parser, relational databases, GIS information, Lucene data, in-memory data, network-accessible APIs, and many more.&lt;/p&gt;

&lt;p&gt;The first &lt;code&gt;Graph&lt;/code&gt; implementation for Asami was a simple in-memory data structure, described in my ClojureD talk. The code for this appears in &lt;a href="https://github.com/threatgrid/asami/blob/main/src/asami/index.cljc"&gt;&lt;code&gt;asami.index&lt;/code&gt;&lt;/a&gt;. This file started much smaller (as &lt;a href="https://github.com/threatgrid/naga/blob/d149904da8ecb510ddbbb5b73824c74da4b05d77/src/naga/storage/memory/index.clj"&gt;referenced&lt;/a&gt; above), but has since expanded with the needs extended functionality, such as transactions, and transitive closure operations.&lt;/p&gt;

&lt;p&gt;Some of the API needs of our project at Cisco required a weighting for various edges, so a second &lt;code&gt;Graph&lt;/code&gt; in-memory structure that could record multiples of the same edges (a so-called "Multi Graph"). This is found in &lt;a href="https://github.com/threatgrid/asami/blob/main/src/asami/multi_graph.cljc"&gt;asami.multi-graph&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Asami is in the process of gaining a new set of &lt;code&gt;Graph&lt;/code&gt; implementations, based on structures inspired by Mulgara, though with some major differences. The first is that the blocks are not necessarily backed by files, and the second is reduced complexity, fewer operations, improved efficiency, and greater utility. My next post will be about this, but the general structure is already documented on the &lt;a href="https://github.com/threatgrid/asami/wiki/Storage-Whitepaper"&gt;Asami Wiki&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The astute reader may notice a few differences from Mulgara already, but I intend to explain why those differences exist, and the benefits they confer.&lt;/p&gt;

</description>
      <category>clojure</category>
      <category>database</category>
    </item>
    <item>
      <title>Asami Background #2</title>
      <dc:creator>Paula Gearon</dc:creator>
      <pubDate>Mon, 08 Feb 2021 18:23:06 +0000</pubDate>
      <link>https://dev.to/quoll/asami-background-2-851</link>
      <guid>https://dev.to/quoll/asami-background-2-851</guid>
      <description>&lt;h1&gt;
  
  
  Mulgara (again)
&lt;/h1&gt;

&lt;p&gt;During my &lt;a href="https://dev.to/quoll/asami-7ll"&gt;last post&lt;/a&gt;, I wanted to start writing about what Asami does, rather than dwelling on the structure of Mulgara, but in so doing I missed an important part of the structure: &lt;em&gt;The Statement Store&lt;/em&gt;. Asami uses a similar statement store, so I think it deserves a little time.&lt;/p&gt;

&lt;p&gt;This post will be full of heavy detail. It's a useful exercise for me to write this since it's helping me review how Mulgara handles storage, and also because Asami is very similar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Indexes
&lt;/h2&gt;

&lt;p&gt;As described in the previous post, Mulgara uses 6 separate indexes to store quads. Each one of these indices starts with an AVL tree, where the payload in each node stores the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A reference to a data block in another file.&lt;/li&gt;
&lt;li&gt;The count of statements in that block.&lt;/li&gt;
&lt;li&gt;The first statement in the block.&lt;/li&gt;
&lt;li&gt;The last statement in the block.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, each node in the tree is associated with a block in another file. That block contains statements as a series of 4x64-bit &lt;code&gt;long&lt;/code&gt; values, up to the number of triples in that block. There is a 1:1 correspondence of AVL Nodes to blocks.&lt;/p&gt;

&lt;p&gt;The best way to describe this structure is to describe the operations on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Search
&lt;/h2&gt;

&lt;p&gt;Search is based on &lt;em&gt;constraint patterns&lt;/em&gt;. For instance, a constraint pattern that describes which &lt;em&gt;predicate&lt;/em&gt; connects a given &lt;em&gt;subject&lt;/em&gt; &lt;code&gt;A&lt;/code&gt; and &lt;em&gt;object&lt;/em&gt; of &lt;code&gt;B&lt;/code&gt; would be represented with a pattern like:&lt;br&gt;
&lt;code&gt;A ?predicate B&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Given that this provides the &lt;em&gt;subject&lt;/em&gt; and &lt;em&gt;object&lt;/em&gt;, but not the &lt;em&gt;predicate&lt;/em&gt; (nor the  &lt;em&gt;graph&lt;/em&gt;), then these statements could be found using the index ordered by:&lt;br&gt;
&lt;em&gt;object,subject,predicate,graph&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;object&lt;/em&gt; comes first on this index, so the search becomes:&lt;br&gt;
&lt;code&gt;B A * *&lt;/code&gt;&lt;br&gt;
Where the first &lt;code&gt;*&lt;/code&gt; represents the &lt;code&gt;?predicate&lt;/code&gt; value, and the second is the unused &lt;em&gt;graph&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Starting at the root of the AVL Tree, this pattern is compared to the "first", or “low” statement for the node. If it's lower, then the search continues on the left child node. Otherwise, the pattern is compared to the "last", or “high” statement for the node, and if it's higher then the search continues on the right child node.&lt;/p&gt;

&lt;p&gt;It is possible for a pattern to compare as being between blocks, in which case there are no matching statements. But usually, a node is reached where the pattern is higher than the "first" statement and lower than the "last" statement, so anything the pattern could match must be within the range of the associated block.&lt;/p&gt;

&lt;p&gt;At this point, the block is loaded from its file and the search continues there. The statements appear as a linear array of numbers, with each 4th number being the start of the next statement. A binary search finds the appropriate statement quickly.&lt;/p&gt;

&lt;p&gt;If an exact match is found for the pattern, then the location of the first statement that matches is returned in a 1 element array. If no match is found, then a pair of consecutive locations are returned in a 2 element array. This indicates the position that matching statements would appear between.&lt;/p&gt;

&lt;p&gt;Mulgara also does a second search, this time looking for the last possible match of pattern. This will typically go down the same branches of the AVL tree, meaning that they are cached and relatively cheap to search.&lt;/p&gt;

&lt;p&gt;These two search results provide start and end positions for an iterator that returns all statements that match the provided pattern. This iterator also adds to the reference count for the index in the current transaction. This is decremented when the iterator is closed, which is also done in the finalizer of the iterator object. This informs the free-list for the index so that it can detect when freed nodes are safe to use again.&lt;/p&gt;

&lt;p&gt;All nodes and statement blocks that have been copied into a transaction will be available for recycling when any iterators that can reach them are closed. This is done by adding their IDs to their respective free lists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Insert
&lt;/h2&gt;

&lt;p&gt;The first step for insertion is a search for the AVL Node representing where the statement should go. If the statement would go between 2 nodes, then the node with the smaller node count is selected. If both are the same size, then it picks the lower node.&lt;/p&gt;

&lt;p&gt;The first thing to check is if the AVL Node was allocated in the current transaction. If so, then it can be modified. But if not, then a copy of the AVL Node is made, updating the transaction ID. This operation iterates up the branch of the tree to the root, copying nodes into the current transaction, either until the root is reached, or until encountering a node that is already in the current transaction.&lt;/p&gt;

&lt;p&gt;For the node is being updated, its associated block will get updated too, meaning that it gets copied into the current transaction, if it's not already there.&lt;/p&gt;

&lt;p&gt;The next thing to check for is if the block is already full. If so, then it needs to be split in half (by allocating a new block and copying the top half of statements into it), and a new AVL Node created for the block with the upper statements. Both the original AVL Node and the new one have their counts, and their high and low statements updated. The node/block that is to be given the statement is then the one that gets processed.&lt;/p&gt;

&lt;p&gt;The block being updated is searched (using binary search) to find the location for the statement. An "array move" operation is used to slide all the statements up one position, and the new statement is written into the space created. The AVL Node is then updated to increment the statement count, and possibly change the high or low statement, if appropriate.&lt;/p&gt;

&lt;p&gt;Yes, I know... it's a lot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deletion
&lt;/h2&gt;

&lt;p&gt;The delete operation is very similar to insertion, with a couple of differences.&lt;/p&gt;

&lt;p&gt;If the statement is found then both the AVL Node and block will be copied into the current transaction. This time, blocks can't overflow, so no splitting occurs. Instead, if a block is emptied, it will be deallocated, putting it on the free list. Similarly, the AVL Node can be removed, putting it on the free list for its file.&lt;/p&gt;

&lt;p&gt;An empty node in an AVL tree is expected to be removed in a single write step, but there is a small chance that rebalancing will need to iterate towards the root. The further it iterates, the more write operations take place, but this is offset by the probability of needing to take the next step decreasing exponentially.&lt;/p&gt;

&lt;p&gt;Frustratingly, at the time, all the references we could find on rebalancing AVL trees during a deletion were &lt;em&gt;&lt;strong&gt;wrong&lt;/strong&gt;&lt;/em&gt;, which we discovered when the trees got out of balance. Finally, two of us sat down and we figured it out from first principles. That was an interesting morning. 😊&lt;/p&gt;

&lt;p&gt;Just like insertions, the block update is done using an array move operation. The exception is if it's the highest statement in the block. In that case, the AVL Node just decrements the statement count and updates the high statement to the next one down.&lt;/p&gt;

&lt;h1&gt;
  
  
  Complexity
&lt;/h1&gt;

&lt;p&gt;There are various tradeoffs made in each part of this structure.&lt;/p&gt;

&lt;p&gt;Statement blocks are full of uncompressed statements (as a tuple of 4 numbers), as this makes them fast to search and read. Space is left in each block, allowing for fast insertions. However, once a block's transaction has finished, it will never be written to again. The space at the end of that block is forever inaccessible. This is done for the sake of speed.&lt;/p&gt;

&lt;p&gt;AVL Trees are binary. This gives them &lt;em&gt;log(N)&lt;/em&gt; complexity in search like any other tree, but from a practical standpoint this will require more read operations than a tree with a fanout of &lt;em&gt;K&lt;/em&gt;&amp;gt;2. Typically, a fanout of &lt;em&gt;K&lt;/em&gt; would result in &lt;em&gt;logKN&lt;/em&gt; steps, which is the same as &lt;em&gt;log2N/log2K&lt;/em&gt;. If the fanout were, say, 32, then this could be about 5 times fewer steps.&lt;/p&gt;

&lt;p&gt;The use of blocks with 1024 statements provides a reduction in the number of steps for tree traversal than a larger fanout would give. In this case, &lt;em&gt;log2(N)-log21024&lt;/em&gt;  or &lt;em&gt;log2(N)-10&lt;/em&gt;. This subtraction is not as effective as a linear scaling factor, but for "small" numbers (&lt;em&gt;N&lt;/em&gt; up to the billions), the number of I/O operations is similar. The benefit of using a binary fanout (&lt;em&gt;K&lt;/em&gt;=2) is that we get to use the AVL structure, which permits insertions with O(1) complexity. So we get similar read characteristics to a B-Tree, but better insertion characteristics.&lt;/p&gt;

&lt;h1&gt;
  
  
  Files
&lt;/h1&gt;

&lt;p&gt;Mulgara would typically use memory-mapped access for the files full of AVL Nodes, and regular read/write access for the block files. This provided the full speed benefits of memory mapping for tree traversal while sparing the address space from the space requirements of the statement blocks. As we moved to 64-bit architectures though, we started using memory mapping more liberally with these larger files as well. This allowed the OS to cache them as appropriate, and schedule them for writing more efficiently than we, as developers, were able to.&lt;/p&gt;

&lt;p&gt;Finally, it is important to note just how many files were in use for all of this. Each index required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A file for the AVL tree.&lt;/li&gt;
&lt;li&gt;A file for statement blocks.&lt;/li&gt;
&lt;li&gt;A free list for freed AVL nodes.&lt;/li&gt;
&lt;li&gt;A free list for freed statement blocks.
And this was multiplied by the 6 different indexes. So even if everything was being done very efficiently, the system was forced to maintain 24 files while updating storage. This involved a lot of unnecessary seeking, regardless of how efficiently the OS reordered it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Similarly, the &lt;em&gt;String Pool&lt;/em&gt; that I described in the previous post required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A file for the AVL tree.&lt;/li&gt;
&lt;li&gt;A free list for the AVL tree.&lt;/li&gt;
&lt;li&gt;20 block files for the various sizes of data.&lt;/li&gt;
&lt;li&gt;20 free lists, one for each block file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While many of these files were not accessed for many operations, there was still a lot happening.&lt;/p&gt;

&lt;h1&gt;
  
  
  Wrap Up
&lt;/h1&gt;

&lt;p&gt;Of course, this does not cover the majority of what Mulgara did, but it does describe the principal structures, especially those that are relevant to Asami. Hopefully, I've provided sufficient background to explain the decisions taken in Asami, which I will get to in my next post.&lt;/p&gt;

</description>
      <category>clojure</category>
      <category>database</category>
    </item>
    <item>
      <title>Asami Background</title>
      <dc:creator>Paula Gearon</dc:creator>
      <pubDate>Sun, 07 Feb 2021 23:15:25 +0000</pubDate>
      <link>https://dev.to/quoll/asami-7ll</link>
      <guid>https://dev.to/quoll/asami-7ll</guid>
      <description>&lt;h1&gt;
  
  
  Mulgara
&lt;/h1&gt;

&lt;p&gt;In 2001, due to a need to store a lot of metadata and deciding that RDF was the way to do it, I was part of a team that designed and built the &lt;a href="http://mulgara.org/"&gt;Mulgara&lt;/a&gt; graph database. It was originally a commercial product called the Tucana Knowledge Store (TKS) and then mostly open-sourced as Kowari, but we renamed it to Mulgara after the original codebase was acquired by Northrup Grumman.&lt;/p&gt;

&lt;p&gt;After maintaining Mulgara for years, I eventually put it aside. This was not because I did not think it was a useful tool, but because it was too big to work on by myself in my spare time. This was exacerbated by being written in Java, which was both slower to develop in, and less fun.&lt;/p&gt;

&lt;p&gt;In the years since, I've been thinking of the lessons that I learned while working on Mulgara, and how things could be done better. I have also been exposed to a number of concepts and technologies that were not well known or did not exist 20 years ago, and these have informed my ideas on how such a database could be built.&lt;/p&gt;

&lt;p&gt;In recent years, I have had the chance to express a few of these ideas in the Asami database, though I still have a long way to go.&lt;/p&gt;

&lt;p&gt;In the meantime, people have been asking me about the design of Asami, so I thought it might be useful to document some of the history and my plans for the future here. I apologize in advance for what may appear to be random musings.&lt;/p&gt;

&lt;p&gt;This post will focus on the structure of Mulgara, and some of the reasons for those decisions.&lt;/p&gt;

&lt;h1&gt;
  
  
  Indices
&lt;/h1&gt;

&lt;h2&gt;
  
  
  AVL Trees
&lt;/h2&gt;

&lt;p&gt;When we were first trying to store large numbers of graph edges as triples, we discovered that it was extremely difficult to store them in a way that was searchable and could scale to the hundreds of GB we needed. Several of the developers tried different approaches, with varying degrees of success (my own did not scale well at all). But then the youngest and least experienced person in the office did a from-scratch implementation of an AVL Tree that was orders of magnitude faster than everyone else's attempts. This decided our course of action.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It also taught me that the youngest and least experienced person on a team can make contributions far beyond what the more senior people may expect. They have ideas, energy, and a lack of preconception which is extremely valuable and should never be overlooked. This has been a recurring theme in my career. I can't stress enough how important it is to have junior members on a team.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Memory Mapping
&lt;/h3&gt;

&lt;p&gt;The company was primarily a Java shop, and at the time of all this, the JDK 1.4 Beta had just been released. This introduced the &lt;a href="https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/nio/package-summary.html"&gt;New IO&lt;/a&gt; package, which included &lt;a href="https://en.wikipedia.org/wiki/Memory-mapped_file"&gt;memory-mapped files&lt;/a&gt;, which we were keen to try out. We convinced our engineering manager that using a Beta did not pose a significant risk, since 1.4 would be out of Beta by the time we released.&lt;/p&gt;

&lt;p&gt;Unfortunately, the Pentium 4 systems we were developing on were based on a 32-bit architecture, which limited the address space of an application to 4GB, or around 2GB for file mappings (this depended on the OS, where shared libraries were mapped, etc). With this in mind, we worked to abstract our file I/O to use either memory-mapping or standard read-write operations, allowing the user to select which one to use at startup.&lt;/p&gt;

&lt;h3&gt;
  
  
  TUX2
&lt;/h3&gt;

&lt;p&gt;Just a few months before, a few of us had been impressed at an idea posted by Daniel Phillips on the Linux Kernel Mailing List for the &lt;a href="https://linux.slashdot.org/story/00/10/13/2117258/tux2-the-filesystem-that-would-be-king"&gt;TUX2 filesystem&lt;/a&gt;. This described &lt;a href="https://web.archive.org/web/20001027203202/http://innominate.org/~phillips/tux2/phase.tree.algorithm.html"&gt;"Phase Trees"&lt;/a&gt;, which was my first exposure to &lt;a href="https://www.cs.cmu.edu/~rwh/theses/okasaki.pdf"&gt;functional data structures&lt;/a&gt;, though I did not know this at the time. The resilience and simplicity of this idea appealed to us, and one of my colleagues suggested that we should incorporate this into our AVL tree design.&lt;/p&gt;

&lt;p&gt;I did spend some time documenting this approach in Javascript and Java in my incomplete &lt;a href="https://dev.to/quoll/series/6140"&gt;dev.to series&lt;/a&gt; on Data Structures. I did this to explain to people some of the basic ideas behind Mulgara, in the lead-up to doing something similar in Asami, but I've since been distracted by actually writing that code. I consider that to be a better use of my time for the moment, though I do hope to return to the documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic structure
&lt;/h3&gt;

&lt;p&gt;The most important element of the AVL trees that we built was the tree &lt;em&gt;Node&lt;/em&gt;. These are a constant sized buffer, containing representations for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A left child (possibly empty)&lt;/li&gt;
&lt;li&gt;A right child (possibly empty)&lt;/li&gt;
&lt;li&gt;A balance (-1, 0, or 1)&lt;/li&gt;
&lt;li&gt;A transaction ID (assigned when the node is created and immutable).&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;payload&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;em&gt;payload&lt;/em&gt; was entirely dependent on the data being stored in the tree. It could contain everything known about the data, or it might contain partial information, along with a pointer to find the remaining data. The most important thing to know is that all AVL nodes were exactly the same size.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transactions
&lt;/h3&gt;

&lt;p&gt;Note that the AVL nodes were all associated with a transaction. This was used for tracking which nodes were under active use. Modifications to the tree were grouped into a &lt;em&gt;transaction&lt;/em&gt; which had an incrementing ID. Whenever a node needed to be modified, then this ID could be checked against the current transaction, and if it differed, then a new node was created, copying the existing node's data into it. That old node was then added to a list of nodes that were no longer in use, called the &lt;em&gt;Free List&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Free List&lt;/em&gt; was used to re-allocate nodes that were no longer in use. This was important for space usage, particularly when data was being removed as well as added. Back in the early 2000s, our hard drives were smaller (and slower) than today, so we were concerned with space, and reclaiming unused nodes was important. This stood in contrast to our mantra at the time of "Disk is cheap", but minimizing wastage was still a deeply ingrained habit from the 90s.&lt;/p&gt;

&lt;p&gt;When any operations that read from the tree were in progress, they would lock a window of the free list, ensuring that any "freed" nodes in there could not be reused until those operations were closed off. This worked well and was reasonably efficient, but it did lead to extra work. It was also (IMO) the most complex part of the codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Statements and the String Pool
&lt;/h2&gt;

&lt;p&gt;Mulgara initially stored all of its data statements as &lt;em&gt;triples&lt;/em&gt;, representing a tuple of &lt;code&gt;[subject predicate object]&lt;/code&gt;. It did not take long to realize that we wanted to group triples into identifiable graphs (which could then have information such as access and authentication properties), so we extended statements to &lt;em&gt;quads&lt;/em&gt; of &lt;code&gt;[subject predicate object graph]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For statements to be easily indexed and retrieved, we wanted them to be the same size. This meant mapping each element of a statement into a number and then providing a way to map those numbers back to the original data. Given that RDF was based on URIs (actually, &lt;a href="https://www.w3.org/TR/rdf-concepts/#dfn-URI-reference"&gt;URI References&lt;/a&gt; in RDF 1.0, and &lt;a href="https://www.ietf.org/rfc/rfc3987.txt"&gt;IRIs&lt;/a&gt; in &lt;a href="https://www.w3.org/TR/rdf11-primer/"&gt;RDF 1.1&lt;/a&gt;) and Literals with a string representation, this meant mapping strings of variable length to numbers, and back. The module that did this was called the &lt;em&gt;String Pool&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  String Pool
&lt;/h2&gt;

&lt;p&gt;We built the &lt;em&gt;String Pool&lt;/em&gt; with 2 indices and a whole lot of other files. The first index used a tree to provide searching for strings by regular comparison operations. The nodes of the tree held the beginning of the string, a pointer to another file to find the full string record, and finally, a number that represented the string (called a &lt;em&gt;gNode&lt;/em&gt;). The second index was a series of regular-sized records where the offset of the record was the &lt;em&gt;gNode&lt;/em&gt; multiplied by the record size. This record then contained the location of the full string record.&lt;/p&gt;

&lt;p&gt;Finding the &lt;em&gt;gNode&lt;/em&gt; for a string meant searching through the tree (possibly looking for the full string in the other file when the beginning of the string matched what was being looked for), and the tree node that was found contained the &lt;em&gt;gNode&lt;/em&gt; in its payload. Searching for the string associated with a &lt;em&gt;gNode&lt;/em&gt; meant going to an offset in the record file that was determined by: &lt;code&gt;gNode * size-of-record&lt;/code&gt;. This record contained the location of the string.&lt;/p&gt;

&lt;p&gt;Strings themselves were also stored in files containing blocks of regular size. Everything up to 16 bytes long went into a file of blocks that were 16 bytes in length. Everything larger than 16, and up to 32 bytes went into a file that contained blocks up to 32 bytes. This continued with blocks doubling in size up to our maximum data size of 8MB. This meant that we had 20 different files, and each file had approximately 25% of unused space. This came from the fact that the data in a block was guaranteed to fill 50% to 100% of the block.&lt;/p&gt;

&lt;h2&gt;
  
  
  Statements
&lt;/h2&gt;

&lt;p&gt;The Statement store initially used indices to sort and store triples in the following orders:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Subject, Predicate, Object&lt;/li&gt;
&lt;li&gt;Predicate, Object, Subject&lt;/li&gt;
&lt;li&gt;Object, Subject Predicate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are 6 possible orderings (calculated as &lt;code&gt;3!&lt;/code&gt; or 3 factorial). It turns out that the 3 orderings shown here allow someone to find all matching statements for any given group of &lt;em&gt;subject&lt;/em&gt;, &lt;em&gt;predicate&lt;/em&gt;, and &lt;em&gt;object&lt;/em&gt;. Interestingly, the remaining 3 possible orderings also permit this. The two groups of orderings are distinct, in that any group that tried to contain ordering from more than one group would need more than 3 indices to be able to fulfill every possible query.&lt;/p&gt;

&lt;p&gt;Once we moved to quads, things became more complex. Now there were &lt;code&gt;4!&lt;/code&gt; possible indices. We spent an afternoon mapping out every possibility and discovered that there are 4 groups of 6 indices that could be used to fulfill every possible query. One of these groups matched our existing indices quite closely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Subject, Predicate, Object, Graph&lt;/li&gt;
&lt;li&gt;Predicate, Object, Subject, Graph&lt;/li&gt;
&lt;li&gt;Object, Subject Predicate, Graph&lt;/li&gt;
&lt;li&gt;Graph, Subject, Predicate, Object&lt;/li&gt;
&lt;li&gt;Graph, Predicate, Object, Subject&lt;/li&gt;
&lt;li&gt;Graph, Object, Subject Predicate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few years later I looked at this more closely and &lt;a href="http://gearon.blogspot.com/2004/08/proof-reading-once-again-its-way-too.html"&gt;realized that it is related to N-dimensional hypercubes&lt;/a&gt;, where the number of groups is represented by opposing faces in the N-dimensional space. e.g. in 3D space, opposing faces of a cube appear in pairs, and there are 3 such pairs. 3 faces of the cube can be used to represent all of the space, with each opposing face providing equivalent information.&lt;/p&gt;

&lt;h1&gt;
  
  
  New Directions
&lt;/h1&gt;

&lt;p&gt;While Mulgara was very successful, there were several areas where I felt it could be improved. I did start on some of these in 2008, but then I moved back to working on rule engines (which Mulgara also has) in 2009. This also led to me working full time in Clojure, and eventually Datomic, and each of these eventually led me towards the design that Asami took on.&lt;/p&gt;

&lt;p&gt;I is still more to describe how the statement indexes worked, and I will discuss that &lt;a href="https://dev.to/quoll/asami-background-2-851"&gt;next&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>database</category>
      <category>clojure</category>
    </item>
  </channel>
</rss>
